""" Простая система локализации 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