Files
ollama-translate-model/translator_utils.py
T

299 lines
11 KiB
Python
Raw Normal View History

2026-05-31 18:45:38 +08:00
"""
Утилиты для Ollama Translator GUI
Дополнительные функции: история, batch обработка, статистика
"""
import json
import os
from datetime import datetime
from pathlib import Path
import hashlib
class TranslationHistory:
"""Управление историей переводов"""
def __init__(self, history_file="translation_history.json"):
self.history_file = history_file
self.history = self.load_history()
def load_history(self):
"""Загрузить историю из файла"""
if os.path.exists(self.history_file):
try:
with open(self.history_file, 'r', encoding='utf-8') as f:
return json.load(f)
except:
return []
return []
def save_history(self):
"""Сохранить историю в файл"""
try:
with open(self.history_file, 'w', encoding='utf-8') as f:
json.dump(self.history, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"Ошибка сохранения истории: {e}")
def add_translation(self, source_text, translated_text, source_lang="auto", target_lang="ru"):
"""Добавить перевод в историю"""
entry = {
"id": hashlib.md5(source_text.encode()).hexdigest()[:8],
"timestamp": datetime.now().isoformat(),
"source_text": source_text[:500], # Ограничение для экономии места
"translated_text": translated_text[:500],
"source_lang": source_lang,
"target_lang": target_lang,
"char_count": len(source_text),
"word_count": len(source_text.split())
}
self.history.insert(0, entry) # Добавить в начало
# Ограничить размер истории (последние 100 записей)
if len(self.history) > 100:
self.history = self.history[:100]
self.save_history()
def get_recent(self, limit=10):
"""Получить последние переводы"""
return self.history[:limit]
def search(self, query):
"""Поиск в истории"""
results = []
query_lower = query.lower()
for entry in self.history:
if (query_lower in entry['source_text'].lower() or
query_lower in entry['translated_text'].lower()):
results.append(entry)
return results
def clear_history(self):
"""Очистить историю"""
self.history = []
self.save_history()
def get_statistics(self):
"""Получить статистику"""
if not self.history:
return {
"total_translations": 0,
"total_chars": 0,
"total_words": 0,
"avg_chars": 0,
"avg_words": 0
}
total_chars = sum(entry.get('char_count', 0) for entry in self.history)
total_words = sum(entry.get('word_count', 0) for entry in self.history)
return {
"total_translations": len(self.history),
"total_chars": total_chars,
"total_words": total_words,
"avg_chars": total_chars // len(self.history) if self.history else 0,
"avg_words": total_words // len(self.history) if self.history else 0,
"first_translation": self.history[-1]['timestamp'] if self.history else None,
"last_translation": self.history[0]['timestamp'] if self.history else None
}
class BatchProcessor:
"""Batch обработка файлов"""
def __init__(self, translate_func):
self.translate_func = translate_func
self.results = []
def process_files(self, file_paths, output_dir=None):
"""Обработать несколько файлов"""
self.results = []
for file_path in file_paths:
try:
# Читаем файл
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# Переводим
translation = self.translate_func(content)
# Определяем путь для сохранения
if output_dir:
output_path = Path(output_dir) / f"{Path(file_path).stem}_ru{Path(file_path).suffix}"
else:
output_path = Path(file_path).parent / f"{Path(file_path).stem}_ru{Path(file_path).suffix}"
# Сохраняем
with open(output_path, 'w', encoding='utf-8') as f:
f.write(translation)
self.results.append({
"file": file_path,
"status": "success",
"output": str(output_path),
"chars": len(content)
})
except Exception as e:
self.results.append({
"file": file_path,
"status": "error",
"error": str(e)
})
return self.results
def get_summary(self):
"""Получить сводку по обработке"""
success = sum(1 for r in self.results if r['status'] == 'success')
failed = sum(1 for r in self.results if r['status'] == 'error')
total_chars = sum(r.get('chars', 0) for r in self.results if r['status'] == 'success')
return {
"total": len(self.results),
"success": success,
"failed": failed,
"total_chars": total_chars
}
class FileFormatHandler:
"""Обработка различных форматов файлов"""
@staticmethod
def read_file(file_path):
"""Прочитать файл с автоопределением кодировки"""
encodings = ['utf-8', 'cp1251', 'latin-1', 'utf-16']
for encoding in encodings:
try:
with open(file_path, 'r', encoding=encoding) as f:
return f.read()
except UnicodeDecodeError:
continue
raise ValueError(f"Не удалось определить кодировку файла: {file_path}")
@staticmethod
def save_file(file_path, content, encoding='utf-8'):
"""Сохранить файл"""
with open(file_path, 'w', encoding=encoding) as f:
f.write(content)
@staticmethod
def get_supported_formats():
"""Получить список поддерживаемых форматов"""
return [
("Текстовые файлы", "*.txt"),
("Markdown файлы", "*.md"),
("Python файлы", "*.py"),
("JavaScript файлы", "*.js"),
("HTML файлы", "*.html"),
("CSS файлы", "*.css"),
("JSON файлы", "*.json"),
("XML файлы", "*.xml"),
("Все файлы", "*.*")
]
class Settings:
"""Управление настройками приложения"""
def __init__(self, settings_file="settings.json"):
self.settings_file = settings_file
self.default_settings = {
"theme": "dark",
"font_size": 13,
"auto_save": False,
"save_history": True,
"max_history": 100,
"timeout": 120,
"model": "translator",
"window_width": 1000,
"window_height": 700
}
self.settings = self.load_settings()
def load_settings(self):
"""Загрузить настройки"""
if os.path.exists(self.settings_file):
try:
with open(self.settings_file, 'r', encoding='utf-8') as f:
loaded = json.load(f)
# Объединить с дефолтными настройками
return {**self.default_settings, **loaded}
except:
return self.default_settings.copy()
return self.default_settings.copy()
def save_settings(self):
"""Сохранить настройки"""
try:
with open(self.settings_file, 'w', encoding='utf-8') as f:
json.dump(self.settings, f, indent=2)
except Exception as e:
print(f"Ошибка сохранения настроек: {e}")
def get(self, key, default=None):
"""Получить значение настройки"""
return self.settings.get(key, default)
def set(self, key, value):
"""Установить значение настройки"""
self.settings[key] = value
self.save_settings()
def reset(self):
"""Сбросить настройки к дефолтным"""
self.settings = self.default_settings.copy()
self.save_settings()
def format_timestamp(iso_timestamp):
"""Форматировать timestamp для отображения"""
try:
dt = datetime.fromisoformat(iso_timestamp)
return dt.strftime("%d.%m.%Y %H:%M")
except:
return iso_timestamp
def format_file_size(size_bytes):
"""Форматировать размер файла"""
for unit in ['Б', 'КБ', 'МБ', 'ГБ']:
if size_bytes < 1024.0:
return f"{size_bytes:.1f} {unit}"
size_bytes /= 1024.0
return f"{size_bytes:.1f} ТБ"
def truncate_text(text, max_length=100):
"""Обрезать текст с многоточием"""
if len(text) <= max_length:
return text
return text[:max_length-3] + "..."
if __name__ == "__main__":
# Тестирование утилит
print("=== Тест TranslationHistory ===")
history = TranslationHistory("test_history.json")
history.add_translation("Hello world", "Привет мир")
history.add_translation("Good morning", "Доброе утро")
print(f"История: {len(history.history)} записей")
print(f"Статистика: {history.get_statistics()}")
print("\n=== Тест Settings ===")
settings = Settings("test_settings.json")
print(f"Тема: {settings.get('theme')}")
settings.set('theme', 'light')
print(f"Новая тема: {settings.get('theme')}")
print("\n=== Тест форматирования ===")
print(f"Timestamp: {format_timestamp(datetime.now().isoformat())}")
print(f"Размер: {format_file_size(1024*1024*5.5)}")
print(f"Текст: {truncate_text('A' * 150, 50)}")