Initial release: Comfy-Studio v1.0.0
Десктопная галерея и менеджер изображений ComfyUI (PyQt6 + SQLite): - мультипапочный мониторинг (watchdog), грид миниатюр, drag-and-drop - теги, избранное, рейтинг, поиск по промтам - парсер метаданных ComfyUI (PNG/WebP/JPEG), редактор workflow/prompt JSON - перевод выделенного текста через контекстное меню (настраиваемые языки) - отправка промта в очередь ComfyUI с внедрением правок и нового seed - полноэкранный просмотр, локализация ru/en, тёмная тема Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
"""
|
||||
Простая система локализации ru/en.
|
||||
Использование:
|
||||
from comfy_studio.core.i18n import tr, set_language
|
||||
tr("search_placeholder") -> "Поиск по имени или промтам..." | "Search by name or prompts..."
|
||||
"""
|
||||
|
||||
from typing import Dict
|
||||
|
||||
_current_language = "ru"
|
||||
|
||||
STRINGS: Dict[str, Dict[str, str]] = {
|
||||
# --- Общее ---
|
||||
"app_ready": {"ru": "Готов к работе", "en": "Ready"},
|
||||
"error": {"ru": "Ошибка", "en": "Error"},
|
||||
"success": {"ru": "Успешно", "en": "Success"},
|
||||
"save": {"ru": "Сохранить", "en": "Save"},
|
||||
"cancel": {"ru": "Отмена", "en": "Cancel"},
|
||||
"delete": {"ru": "Удалить", "en": "Delete"},
|
||||
"rename": {"ru": "Переименовать", "en": "Rename"},
|
||||
|
||||
# --- Левая панель ---
|
||||
"search_placeholder": {"ru": "Поиск по имени или промтам...", "en": "Search by name or prompts..."},
|
||||
"active_folder": {"ru": "Активная папка:", "en": "Active folder:"},
|
||||
"subfolder_tree": {"ru": "Дерево подпапок:", "en": "Subfolder tree:"},
|
||||
"filter_favorites": {"ru": "Только избранное", "en": "Favorites only"},
|
||||
"filter_tag": {"ru": "Фильтр по тегу:", "en": "Filter by tag:"},
|
||||
"all_tags": {"ru": "Все теги", "en": "All tags"},
|
||||
|
||||
# --- Центральная панель ---
|
||||
"select_folder": {"ru": "Выберите папку...", "en": "Select a folder..."},
|
||||
"folder_label": {"ru": "Папка", "en": "Folder"},
|
||||
"zoom": {"ru": "Масштаб:", "en": "Zoom:"},
|
||||
"files_shown": {"ru": "Файлов отображено", "en": "Files shown"},
|
||||
|
||||
# --- Правая панель ---
|
||||
"no_image_selected": {"ru": "Нет выделенного изображения", "en": "No image selected"},
|
||||
"preview_error": {"ru": "Ошибка рендеринга превью", "en": "Preview rendering error"},
|
||||
"model": {"ru": "Модель:", "en": "Model:"},
|
||||
"sampler": {"ru": "Сэмплер:", "en": "Sampler:"},
|
||||
"rating": {"ru": "Рейтинг:", "en": "Rating:"},
|
||||
"no_rating": {"ru": "Без рейтинга", "en": "No rating"},
|
||||
"not_specified": {"ru": "Не указано", "en": "Not specified"},
|
||||
"positive_prompt": {"ru": "Позитивный промт:", "en": "Positive prompt:"},
|
||||
"negative_prompt": {"ru": "Негативный промт:", "en": "Negative prompt:"},
|
||||
"save_changes": {"ru": "Сохранить изменения", "en": "Save changes"},
|
||||
"workflow_not_found": {"ru": "Workflow не найден", "en": "Workflow not found"},
|
||||
"tab_generation": {"ru": "Генерация", "en": "Generation"},
|
||||
"tab_workflow": {"ru": "Workflow", "en": "Workflow"},
|
||||
"copy_positive": {"ru": "Коп. Pos", "en": "Copy Pos"},
|
||||
"copy_negative": {"ru": "Коп. Neg", "en": "Copy Neg"},
|
||||
"copy_workflow": {"ru": "Коп. Work", "en": "Copy WF"},
|
||||
"send_to_comfy": {"ru": "Отправить в ComfyUI", "en": "Send to ComfyUI"},
|
||||
"favorite": {"ru": "★ Избранное", "en": "★ Favorite"},
|
||||
"tags": {"ru": "Теги:", "en": "Tags:"},
|
||||
"add_tag_placeholder": {"ru": "Новый тег + Enter", "en": "New tag + Enter"},
|
||||
|
||||
# --- Контекстное меню ---
|
||||
"show_on_disk": {"ru": "Показать на диске", "en": "Show on disk"},
|
||||
"delete_selected": {"ru": "Удалить выбранные", "en": "Delete selected"},
|
||||
"rename_title": {"ru": "Переименование", "en": "Rename"},
|
||||
"rename_prompt": {"ru": "Новое имя файла для", "en": "New filename for"},
|
||||
"open_fullscreen": {"ru": "Открыть на весь экран", "en": "Open fullscreen"},
|
||||
"toggle_favorite": {"ru": "Добавить/убрать из избранного", "en": "Toggle favorite"},
|
||||
|
||||
# --- Диалоги ---
|
||||
"settings_title": {"ru": "Настройки", "en": "Settings"},
|
||||
"settings_btn": {"ru": "Настройки", "en": "Settings"},
|
||||
"comfy_api_url": {"ru": "Адрес API ComfyUI:", "en": "ComfyUI API URL:"},
|
||||
"tracked_folders": {"ru": "Отслеживаемые папки генерации:", "en": "Tracked generation folders:"},
|
||||
"add_folder": {"ru": "Добавить папку", "en": "Add folder"},
|
||||
"remove_selected": {"ru": "Удалить выбранную", "en": "Remove selected"},
|
||||
"language": {"ru": "Язык интерфейса:", "en": "Interface language:"},
|
||||
"language_restart_note": {"ru": "Язык применится после перезапуска приложения.",
|
||||
"en": "Language change takes effect after restart."},
|
||||
"url_empty_error": {"ru": "Адрес API не может быть пустым.", "en": "API URL cannot be empty."},
|
||||
"paths_empty_error": {"ru": "Должна быть добавлена хотя бы одна папка.",
|
||||
"en": "At least one folder must be added."},
|
||||
"choose_tracked_folder": {"ru": "Выбрать отслеживаемую папку", "en": "Select folder to track"},
|
||||
"delete_confirm_title": {"ru": "Удаление", "en": "Delete"},
|
||||
"delete_confirm_text": {"ru": "Вы действительно хотите безвозвратно удалить {n} файлов?",
|
||||
"en": "Permanently delete {n} file(s)?"},
|
||||
"deleted_from_disk": {"ru": "Удалено файлов с диска", "en": "Files deleted from disk"},
|
||||
"copied_to_clipboard": {"ru": "Изображение скопировано в буфер обмена.",
|
||||
"en": "Image copied to clipboard."},
|
||||
"renamed_ok": {"ru": "Файл успешно переименован", "en": "File renamed"},
|
||||
"rename_failed": {"ru": "Не удалось переименовать файл", "en": "Failed to rename file"},
|
||||
"settings_applied": {"ru": "Настройки успешно применены.", "en": "Settings applied."},
|
||||
"watcher_restarting": {"ru": "Перезапуск службы отслеживания...", "en": "Restarting watcher..."},
|
||||
"params_updated": {"ru": "Параметры успешно обновлены.", "en": "Parameters updated."},
|
||||
"db_save_error": {"ru": "Не удалось сохранить изменения в БД.", "en": "Failed to save changes to DB."},
|
||||
|
||||
# --- Перевод ---
|
||||
"translate_to": {"ru": "Перевести на {lang}", "en": "Translate to {lang}"},
|
||||
"translation_title": {"ru": "Перевод", "en": "Translation"},
|
||||
"original_text": {"ru": "Оригинал:", "en": "Original:"},
|
||||
"translated_text": {"ru": "Перевод (можно редактировать):",
|
||||
"en": "Translation (editable):"},
|
||||
"translating": {"ru": "Перевод...", "en": "Translating..."},
|
||||
"apply": {"ru": "Применить", "en": "Apply"},
|
||||
"translation_failed": {"ru": "Не удалось выполнить перевод", "en": "Translation failed"},
|
||||
"translation_languages": {"ru": "Языки перевода (в контекстном меню):",
|
||||
"en": "Translation languages (in context menu):"},
|
||||
|
||||
# --- Редактор workflow/prompt ---
|
||||
"tab_prompt_json": {"ru": "Prompt JSON", "en": "Prompt JSON"},
|
||||
"save_workflow": {"ru": "Сохранить workflow", "en": "Save workflow"},
|
||||
"save_prompt_json": {"ru": "Сохранить prompt", "en": "Save prompt"},
|
||||
"invalid_json": {"ru": "Некорректный JSON: {err}", "en": "Invalid JSON: {err}"},
|
||||
"json_saved": {"ru": "JSON сохранён в БД.", "en": "JSON saved to DB."},
|
||||
"format_json": {"ru": "Форматировать", "en": "Format"},
|
||||
"prompt_json_not_found": {"ru": "Prompt не найден", "en": "Prompt not found"},
|
||||
|
||||
"randomize_seed": {"ru": "Новый seed при отправке", "en": "New seed on send"},
|
||||
|
||||
# --- ComfyUI ---
|
||||
"sending_prompt": {"ru": "Отправка промта в ComfyUI...", "en": "Sending prompt to ComfyUI..."},
|
||||
"prompt_queued": {"ru": "Промт успешно добавлен в очередь ComfyUI!",
|
||||
"en": "Prompt queued in ComfyUI!"},
|
||||
"prompt_send_failed": {"ru": "Не удалось отправить промт.", "en": "Failed to send prompt."},
|
||||
"no_prompt_graph": {"ru": "У изображения отсутствует prompt-граф.",
|
||||
"en": "Image has no prompt graph."},
|
||||
"network_error_title": {"ru": "Ошибка сети / API", "en": "Network / API error"},
|
||||
"task_id": {"ru": "ID задачи", "en": "Task ID"},
|
||||
"comfy_connect_error": {"ru": "Не удалось подключиться к ComfyUI по адресу {url}.\nУбедитесь, что сервер запущен.",
|
||||
"en": "Could not connect to ComfyUI at {url}.\nMake sure the server is running."},
|
||||
"comfy_server_error": {"ru": "Сервер ComfyUI вернул ошибку {code}", "en": "ComfyUI server returned error {code}"},
|
||||
"metadata_error": {"ru": "Ошибка метаданных изображения (неверный формат JSON)",
|
||||
"en": "Image metadata error (invalid JSON)"},
|
||||
}
|
||||
|
||||
|
||||
def set_language(lang: str) -> None:
|
||||
global _current_language
|
||||
_current_language = lang if lang in ("ru", "en") else "ru"
|
||||
|
||||
|
||||
def get_language() -> str:
|
||||
return _current_language
|
||||
|
||||
|
||||
def tr(key: str, **kwargs) -> str:
|
||||
"""Возвращает строку для текущего языка; {placeholders} подставляются из kwargs."""
|
||||
entry = STRINGS.get(key)
|
||||
if not entry:
|
||||
return key
|
||||
text = entry.get(_current_language) or entry.get("ru") or key
|
||||
if kwargs:
|
||||
try:
|
||||
text = text.format(**kwargs)
|
||||
except (KeyError, IndexError):
|
||||
pass
|
||||
return text
|
||||
Reference in New Issue
Block a user