From 731e919884ba74173cc260180c80f28fd699746f Mon Sep 17 00:00:00 2001 From: Boris Yumankulov Date: Sun, 6 Jul 2025 13:10:37 +0500 Subject: [PATCH] feat: added translate support to custom data Signed-off-by: Boris Yumankulov --- portprotonqt/custom_data/.gitkeep | 0 portprotonqt/localization.py | 30 ++++++++++++++++++ portprotonqt/main_window.py | 51 +++++++++++++------------------ 3 files changed, 52 insertions(+), 29 deletions(-) delete mode 100644 portprotonqt/custom_data/.gitkeep diff --git a/portprotonqt/custom_data/.gitkeep b/portprotonqt/custom_data/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/portprotonqt/localization.py b/portprotonqt/localization.py index 8c2becd..e278b9d 100644 --- a/portprotonqt/localization.py +++ b/portprotonqt/localization.py @@ -1,6 +1,7 @@ import gettext from pathlib import Path import locale +import os from babel import Locale LOCALE_MAP = { @@ -72,3 +73,32 @@ def get_egs_language(): # Если что-то пошло не так — используем английский по умолчанию return 'en' + +def read_metadata_translations(metadata_file, language_code): + """ + Читает переводы из metadata.txt для указанного языка. + Возвращает словарь с полями name и description. + Для name: использует name_, затем name_en, затем name, и наконец _('Unknown Game'). + Для description: использует description_, затем description_en, затем description. + """ + translations = {'name': _('Unknown Game'), 'description': ''} + if not os.path.exists(metadata_file): + return translations + + with open(metadata_file, encoding='utf-8') as f: + for line in f: + line = line.strip() + if line.startswith(f'name_{language_code}='): + translations['name'] = line[len(f'name_{language_code}='):].strip() + elif line.startswith('name_en=') and translations['name'] == _('Unknown Game'): + translations['name'] = line[len('name_en='):].strip() + elif line.startswith('name=') and translations['name'] == _('Unknown Game'): + translations['name'] = line[len('name='):].strip() + elif line.startswith(f'description_{language_code}='): + translations['description'] = line[len(f'description_{language_code}='):].strip() + elif line.startswith('description_en=') and not translations['description']: + translations['description'] = line[len('description_en='):].strip() + elif line.startswith('description=') and not translations['description']: + translations['description'] = line[len('description='):].strip() + + return translations diff --git a/portprotonqt/main_window.py b/portprotonqt/main_window.py index 099b416..4d59595 100644 --- a/portprotonqt/main_window.py +++ b/portprotonqt/main_window.py @@ -28,7 +28,7 @@ from portprotonqt.config_utils import ( save_fullscreen_config, read_window_geometry, save_window_geometry, reset_config, clear_cache, read_auto_fullscreen_gamepad, save_auto_fullscreen_gamepad, read_rumble_config, save_rumble_config ) -from portprotonqt.localization import _ +from portprotonqt.localization import _, get_egs_language, read_metadata_translations from portprotonqt.logger import get_logger from portprotonqt.downloader import Downloader @@ -465,11 +465,9 @@ class MainWindow(QMainWindow): os.makedirs(user_custom_folder, exist_ok=True) builtin_cover = "" - builtin_name = None - builtin_desc = None user_cover = "" - user_name = None - user_desc = None + user_game_folder="" + builtin_game_folder="" if game_exe: exe_name = os.path.splitext(os.path.basename(game_exe))[0] @@ -477,6 +475,7 @@ class MainWindow(QMainWindow): user_game_folder = os.path.join(user_custom_folder, exe_name) os.makedirs(user_game_folder, exist_ok=True) + # Чтение обложки builtin_files = set(os.listdir(builtin_game_folder)) if os.path.exists(builtin_game_folder) else set() for ext in [".jpg", ".png", ".jpeg", ".bmp"]: candidate = f"cover{ext}" @@ -484,16 +483,6 @@ class MainWindow(QMainWindow): builtin_cover = os.path.join(builtin_game_folder, candidate) break - builtin_metadata_file = os.path.join(builtin_game_folder, "metadata.txt") - if os.path.exists(builtin_metadata_file): - with open(builtin_metadata_file, encoding="utf-8") as f: - for line in f: - line = line.strip() - if line.startswith("name="): - builtin_name = line[len("name="):].strip() - elif line.startswith("description="): - builtin_desc = line[len("description="):].strip() - user_files = set(os.listdir(user_game_folder)) if os.path.exists(user_game_folder) else set() for ext in [".jpg", ".png", ".jpeg", ".bmp"]: candidate = f"cover{ext}" @@ -501,16 +490,7 @@ class MainWindow(QMainWindow): user_cover = os.path.join(user_game_folder, candidate) break - user_metadata_file = os.path.join(user_game_folder, "metadata.txt") - if os.path.exists(user_metadata_file): - with open(user_metadata_file, encoding="utf-8") as f: - for line in f: - line = line.strip() - if line.startswith("name="): - user_name = line[len("name="):].strip() - elif line.startswith("description="): - user_desc = line[len("description="):].strip() - + # Чтение статистики if self.portproton_location: statistics_file = os.path.join(self.portproton_location, "data", "tmp", "statistics") try: @@ -526,13 +506,26 @@ class MainWindow(QMainWindow): print(f"Failed to parse playtime data: {e}") def on_steam_info(steam_info: dict): - final_name = user_name or builtin_name or desktop_name - final_desc = (user_desc if user_desc is not None else - builtin_desc if builtin_desc is not None else - steam_info.get("description", "")) + # Определяем текущий язык + language_code = get_egs_language() + + # Чтение переводов из metadata.txt + user_metadata_file = os.path.join(user_game_folder, "metadata.txt") + builtin_metadata_file = os.path.join(builtin_game_folder, "metadata.txt") + + # Сначала пытаемся загрузить пользовательские переводы + translations = {'name': desktop_name, 'description': ''} + if os.path.exists(user_metadata_file): + translations = read_metadata_translations(user_metadata_file, language_code) + elif os.path.exists(builtin_metadata_file): + translations = read_metadata_translations(builtin_metadata_file, language_code) + + final_name = translations['name'] + final_desc = translations['description'] or steam_info.get("description", "") final_cover = (user_cover if user_cover else builtin_cover if builtin_cover else steam_info.get("cover", "") or entry.get("Icon", "")) + callback(( final_name, final_desc,