diff --git a/documentation/theme_guide/README.md b/documentation/theme_guide/README.md index 4c5777f..130d1e1 100644 --- a/documentation/theme_guide/README.md +++ b/documentation/theme_guide/README.md @@ -31,7 +31,7 @@ mkdir -p ~/.local/share/PortProtonQT/themes/my_custom_theme ## 🎨 Style File (`styles.py`) -Create a `styles.py` in the theme root. It should define variables or functions that return QSS (Qt Style Sheets). For better organization, you can split your theme into multiple submodules by creating a `styles` subdirectory with separate Python files for different components, and import them in `styles.py`. +Create a `styles.py` in the theme root. It should define variables or functions that return QSS (Qt Style Sheets). For better organization, you can split your theme into multiple submodules by creating a subdirectory (e.g., `styles`, `components`, etc.) with separate Python files for different components, and import them in `styles.py`. **Example of modular structure:** ``` @@ -40,7 +40,7 @@ my_custom_theme/ β”œβ”€β”€ metainfo.ini β”œβ”€β”€ fonts/ β”œβ”€β”€ images/ -└── styles/ +└── styles/ # This can be named anything (e.g., components, modules, etc.) β”œβ”€β”€ __init__.py # This empty file makes the directory a Python package β”œβ”€β”€ constants.py β”œβ”€β”€ base.py @@ -54,7 +54,7 @@ my_custom_theme/ **Main styles.py file:** ```python # Import from the theme's submodules using absolute paths relative to the package -# Replace 'my_custom_theme' with your actual theme folder name +# Replace 'my_custom_theme' with your actual theme folder name and 'styles' with your subdirectory name from portprotonqt.themes.my_custom_theme.styles.constants import * from portprotonqt.themes.my_custom_theme.styles.base import * from portprotonqt.themes.my_custom_theme.styles.game_card import * @@ -239,18 +239,52 @@ GAME_CARD_ANIMATION = { ```ini [Metainfo] -name = My Custom Theme +name_en = My Custom Theme +name_ru = Моя ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠ°Ρ Ρ‚Π΅ΠΌΠ° author = Your Name author_link = https://example.com -description = Description of your theme. +description_en = Description of your theme. +description_ru = ОписаниС вашСй Ρ‚Π΅ΠΌΡ‹. ``` +### Translation Support + +You must provide translations for your theme's name and description by adding language-specific fields: +- `name_en`, `name_ru`, etc. for theme names +- `description_en`, `description_ru`, etc. for theme descriptions + +The application will automatically select the appropriate translation based on the user's system language, falling back to English if translations are not available for the user's language. + --- ## πŸ–Ό Screenshots Folder: `images/screenshots/` β€” place UI screenshots there. +### Screenshot Translation Support + +You can provide translations for screenshot captions by adding entries to the `[Screenshots]` section in your `metainfo.ini` file: + +```ini +[Screenshots] +auto_installs_en = Auto-installs +auto_installs_ru = Автоустановки +library_en = Library +library_ru = Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° +game_card_en = Game Card +game_card_ru = ΠšΠ°Ρ€Ρ‚ΠΎΡ‡ΠΊΠ° +context_menu_en = Context Menu +context_menu_ru = ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚Π½ΠΎΠ΅ мСню +portproton_settings_en = PortProton Settings +portproton_settings_ru = Настройки PortProton +wine_settings_en = Wine Settings +wine_settings_ru = Настройки Wine +themes_en = Themes +themes_ru = Π’Π΅ΠΌΡ‹ +``` + +Screenshot files should be named in English (without spaces), and the application will display the appropriate translated caption based on the user's system language, falling back to English if translations are not available. + --- ## πŸ”‘ Fonts and Icons (optional) diff --git a/documentation/theme_guide/README.ru.md b/documentation/theme_guide/README.ru.md index 81920b7..07a45b8 100644 --- a/documentation/theme_guide/README.ru.md +++ b/documentation/theme_guide/README.ru.md @@ -31,7 +31,7 @@ mkdir -p ~/.local/share/PortProtonQT/themes/my_custom_theme ## 🎨 Π€Π°ΠΉΠ» стилСй (`styles.py`) -Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ `styles.py` Π² ΠΊΠΎΡ€Π½Π΅ Ρ‚Π΅ΠΌΡ‹. Π’ Π½Ρ‘ΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ/ΠΈΠ»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‰ΠΈΠ΅ QSS-ΠΎΡ„ΠΎΡ€ΠΌΠ»Π΅Π½ΠΈΠ΅ (Qt Style Sheets). Для Π»ΡƒΡ‡ΡˆΠ΅ΠΉ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ΄Π°, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ Π½Π° нСсколько ΠΏΠΎΠ΄ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ, создав ΠΏΠΎΠ΄Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ `styles` с ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ Python-Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ для Ρ€Π°Π·Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΈ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… Π² `styles.py`. +Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ `styles.py` Π² ΠΊΠΎΡ€Π½Π΅ Ρ‚Π΅ΠΌΡ‹. Π’ Π½Ρ‘ΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ/ΠΈΠ»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‰ΠΈΠ΅ QSS-ΠΎΡ„ΠΎΡ€ΠΌΠ»Π΅Π½ΠΈΠ΅ (Qt Style Sheets). Для Π»ΡƒΡ‡ΡˆΠ΅ΠΉ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊΠΎΠ΄Π°, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ Π½Π° нСсколько ΠΏΠΎΠ΄ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ, создав ΠΏΠΎΠ΄Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, `styles`, `components` ΠΈ Ρ‚.Π΄.) с ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ Python-Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ для Ρ€Π°Π·Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΈ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… Π² `styles.py`. **ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½ΠΎΠΉ структуры:** ``` @@ -40,7 +40,7 @@ my_custom_theme/ β”œβ”€β”€ metainfo.ini β”œβ”€β”€ fonts/ β”œβ”€β”€ images/ -└── styles/ +└── styles/ # Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π½Π°Π·Π²Π°Π½ΠΎ ΠΊΠ°ΠΊ ΡƒΠ³ΠΎΠ΄Π½ΠΎ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, components, modules ΠΈ Ρ‚.Π΄.) β”œβ”€β”€ __init__.py # Π­Ρ‚ΠΎΡ‚ пустой Ρ„Π°ΠΉΠ» Π΄Π΅Π»Π°Π΅Ρ‚ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ Python-ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠΌ β”œβ”€β”€ constants.py β”œβ”€β”€ base.py @@ -54,7 +54,7 @@ my_custom_theme/ **Основной Ρ„Π°ΠΉΠ» styles.py:** ```python # Π˜ΠΌΠΏΠΎΡ€Ρ‚ ΠΈΠ· ΠΏΠΎΠ΄ΠΌΠΎΠ΄ΡƒΠ»Π΅ΠΉ Ρ‚Π΅ΠΌΡ‹ с использованиСм Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½Ρ‹Ρ… ΠΏΡƒΡ‚Π΅ΠΉ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° -# Π—Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ 'my_custom_theme' Π½Π° фактичСскоС имя ΠΏΠ°ΠΏΠΊΠΈ вашСй Ρ‚Π΅ΠΌΡ‹ +# Π—Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ 'my_custom_theme' Π½Π° фактичСскоС имя ΠΏΠ°ΠΏΠΊΠΈ вашСй Ρ‚Π΅ΠΌΡ‹ ΠΈ 'styles' Π½Π° имя вашСй ΠΏΠΎΠ΄Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ from portprotonqt.themes.my_custom_theme.styles.constants import * from portprotonqt.themes.my_custom_theme.styles.base import * from portprotonqt.themes.my_custom_theme.styles.game_card import * @@ -239,18 +239,52 @@ GAME_CARD_ANIMATION = { ```ini [Metainfo] -name = My Custom Theme +name_en = My Custom Theme +name_ru = Моя ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠ°Ρ Ρ‚Π΅ΠΌΠ° author = Π’Π°ΡˆΠ΅ имя author_link = https://example.com -description = ОписаниС вашСй Ρ‚Π΅ΠΌΡ‹. +description_en = Description of your theme. +description_ru = ОписаниС вашСй Ρ‚Π΅ΠΌΡ‹. ``` +### ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠ² + +Π’Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ для названия ΠΈ описания вашСй Ρ‚Π΅ΠΌΡ‹, Π΄ΠΎΠ±Π°Π²ΠΈΠ² поля с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ языка: +- `name_en`, `name_ru` ΠΈ Ρ‚.Π΄. для Π½Π°Π·Π²Π°Π½ΠΈΠΉ Ρ‚Π΅ΠΌ +- `description_en`, `description_ru` ΠΈ Ρ‚.Π΄. для описаний Ρ‚Π΅ΠΌ + +ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ автоматичСски Π²Ρ‹Π±Π΅Ρ€Π΅Ρ‚ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ Π½Π° основС языка систСмы ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, с ΠΎΡ‚ΠΊΠ°Ρ‚ΠΎΠΌ ΠΊ английскому языку, Ссли ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ нСдоступны для языка ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. + --- ## πŸ–Ό Π‘ΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚Ρ‹ Папка: `images/screenshots/` β€” Π»ΡŽΠ±Ρ‹Π΅ изобраТСния оформлСния Ρ‚Π΅ΠΌΡ‹. +### ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚ΠΎΠ² + +Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ для подписСй ΠΊ ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚Π°ΠΌ, Π΄ΠΎΠ±Π°Π²ΠΈΠ² записи Π² ΡΠ΅ΠΊΡ†ΠΈΡŽ `[Screenshots]` Π² Ρ„Π°ΠΉΠ»Π΅ `metainfo.ini`: + +```ini +[Screenshots] +auto_installs_en = Auto-installs +auto_installs_ru = Автоустановки +library_en = Library +library_ru = Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° +game_card_en = Game Card +game_card_ru = ΠšΠ°Ρ€Ρ‚ΠΎΡ‡ΠΊΠ° +context_menu_en = Context Menu +context_menu_ru = ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚Π½ΠΎΠ΅ мСню +portproton_settings_en = PortProton Settings +portproton_settings_ru = Настройки PortProton +wine_settings_en = Wine Settings +wine_settings_ru = Настройки Wine +themes_en = Themes +themes_ru = Π’Π΅ΠΌΡ‹ +``` + +Π€Π°ΠΉΠ»Ρ‹ ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚ΠΎΠ² Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π½Π°Π·Π²Π°Π½Ρ‹ Π½Π° английском языкС (Π±Π΅Π· ΠΏΡ€ΠΎΠ±Π΅Π»ΠΎΠ²), ΠΈ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Π΅Π½Π½ΡƒΡŽ подпись Π² зависимости ΠΎΡ‚ языка систСмы ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, с ΠΎΡ‚ΠΊΠ°Ρ‚ΠΎΠΌ ΠΊ английскому языку, Ссли ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ нСдоступны. + --- ## πŸ”‘ Π¨Ρ€ΠΈΡ„Ρ‚Ρ‹ ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠΈ (ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ) diff --git a/portprotonqt/config_utils.py b/portprotonqt/config_utils.py index eac55c5..a051194 100644 --- a/portprotonqt/config_utils.py +++ b/portprotonqt/config_utils.py @@ -3,6 +3,7 @@ import configparser import shutil import subprocess from portprotonqt.logger import get_logger +from portprotonqt.localization import get_theme_translations logger = get_logger(__name__) @@ -228,13 +229,17 @@ def load_theme_metainfo(theme_name): theme_folder = os.path.join(themes_dir, theme_name) metainfo_file = os.path.join(theme_folder, "metainfo.ini") if os.path.exists(metainfo_file): + # Load translated theme name and description + theme_translations = get_theme_translations(metainfo_file) + cp = configparser.ConfigParser() cp.read(metainfo_file, encoding="utf-8") if "Metainfo" in cp: meta["author"] = cp.get("Metainfo", "author", fallback="Unknown") meta["author_link"] = cp.get("Metainfo", "author_link", fallback="") - meta["description"] = cp.get("Metainfo", "description", fallback="") - meta["name"] = cp.get("Metainfo", "name", fallback=theme_name) + # Use translated name and description + meta["name"] = theme_translations.get("name", theme_name) + meta["description"] = theme_translations.get("description", "") break return meta diff --git a/portprotonqt/localization.py b/portprotonqt/localization.py index e278b9d..2f4f9c7 100644 --- a/portprotonqt/localization.py +++ b/portprotonqt/localization.py @@ -1,4 +1,5 @@ import gettext +import configparser from pathlib import Path import locale import os @@ -102,3 +103,97 @@ def read_metadata_translations(metadata_file, language_code): translations['description'] = line[len('description='):].strip() return translations + +def get_screenshot_caption(base_filename, metainfo_file, language_code=None): + """ + Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ названия ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚Π° Π½Π° основС языка ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. + + Args: + base_filename: Имя Ρ„Π°ΠΉΠ»Π° Π±Π΅Π· Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ + metainfo_file: ΠŸΡƒΡ‚ΡŒ ΠΊ Ρ„Π°ΠΉΠ»Ρƒ metainfo.ini + language_code: Код языка (Ссли None, Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ автоматичСски) + + Returns: + ΠŸΠ΅Ρ€Π΅Π²Π΅Π΄Π΅Π½Π½ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚Π° + """ + if language_code is None: + system_locale = get_system_locale() + language_code = system_locale.split('_')[0] if '_' in system_locale else system_locale + + # Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ ΠΈΠ· metainfo.ini + screenshot_translations = {} + if metainfo_file and os.path.exists(metainfo_file): + cp = configparser.ConfigParser() + cp.read(metainfo_file, encoding="utf-8") + if "Screenshots" in cp: + for key in cp.options("Screenshots"): + screenshot_translations[key] = cp.get("Screenshots", key) + + # Π˜Ρ‰Π΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅: base_filename_languagecode + caption = base_filename # По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π±Π°Π·ΠΎΠ²ΠΎΠ΅ имя Ρ„Π°ΠΉΠ»Π° + + if screenshot_translations: + # ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ для ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ языка (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, "library_ru") + lang_specific_key = f"{base_filename}_{language_code}" + # ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ английский ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, "library_en") + english_key = f"{base_filename}_en" + + if lang_specific_key in screenshot_translations: + caption = screenshot_translations[lang_specific_key] + elif english_key in screenshot_translations: + caption = screenshot_translations[english_key] + elif base_filename in screenshot_translations: + caption = screenshot_translations[base_filename] # fallback to untranslated key + + return caption + +def get_theme_translations(metainfo_file, language_code=None): + """ + Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ названия ΠΈ описания Ρ‚Π΅ΠΌΡ‹ Π½Π° основС языка ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. + + Args: + metainfo_file: ΠŸΡƒΡ‚ΡŒ ΠΊ Ρ„Π°ΠΉΠ»Ρƒ metainfo.ini + language_code: Код языка (Ссли None, Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ автоматичСски) + + Returns: + Π‘Π»ΠΎΠ²Π°Ρ€ΡŒ с полями 'name' ΠΈ 'description' с ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Π΅Π½Π½Ρ‹ΠΌΠΈ значСниями + """ + if language_code is None: + system_locale = get_system_locale() + language_code = system_locale.split('_')[0] if '_' in system_locale else system_locale + + # Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‹ ΠΈΠ· metainfo.ini + translations = {'name': '', 'description': ''} + + if metainfo_file and os.path.exists(metainfo_file): + cp = configparser.ConfigParser() + cp.read(metainfo_file, encoding="utf-8") + + if "Metainfo" in cp: + # ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ названия для ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ языка (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, "name_ru") + lang_specific_name_key = f"name_{language_code}" + # ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ английский ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ названия (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, "name_en") + english_name_key = "name_en" + + # Π˜Ρ‰Π΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ названия + if cp.has_option("Metainfo", lang_specific_name_key): + translations['name'] = cp.get("Metainfo", lang_specific_name_key) + elif cp.has_option("Metainfo", english_name_key): + translations['name'] = cp.get("Metainfo", english_name_key) + elif cp.has_option("Metainfo", "name"): + translations['name'] = cp.get("Metainfo", "name") + + # ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ описания для ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ языка (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, "description_ru") + lang_specific_desc_key = f"description_{language_code}" + # ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ английский ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ описания (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, "description_en") + english_desc_key = "description_en" + + # Π˜Ρ‰Π΅ΠΌ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ описания + if cp.has_option("Metainfo", lang_specific_desc_key): + translations['description'] = cp.get("Metainfo", lang_specific_desc_key) + elif cp.has_option("Metainfo", english_desc_key): + translations['description'] = cp.get("Metainfo", english_desc_key) + elif cp.has_option("Metainfo", "description"): + translations['description'] = cp.get("Metainfo", "description") + + return translations diff --git a/portprotonqt/main_window.py b/portprotonqt/main_window.py index 6b50c77..cb0c841 100644 --- a/portprotonqt/main_window.py +++ b/portprotonqt/main_window.py @@ -2494,8 +2494,8 @@ class MainWindow(QMainWindow): screenshots = load_theme_screenshots(theme_name) if screenshots: self.screenshotsCarousel.update_images([ - (pixmap, os.path.splitext(filename)[0]) - for pixmap, filename in screenshots + (pixmap, caption) + for pixmap, caption in screenshots ]) self.screenshotsCarousel.show() else: diff --git a/portprotonqt/theme_manager.py b/portprotonqt/theme_manager.py index ce0becd..45353f2 100644 --- a/portprotonqt/theme_manager.py +++ b/portprotonqt/theme_manager.py @@ -4,6 +4,7 @@ from portprotonqt.logger import get_logger from portprotonqt.theme_security import check_theme_safety, is_safe_image_file from PySide6.QtGui import QIcon, QFontDatabase, QPixmap from portprotonqt.config_utils import save_theme_to_config, load_theme_metainfo +from portprotonqt.localization import get_screenshot_caption # Icon caching for performance optimization _icon_cache = {} @@ -35,10 +36,20 @@ def list_themes(): def load_theme_screenshots(theme_name): """ Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ всС ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚Ρ‹ ΠΈΠ· ΠΏΠ°ΠΏΠΊΠΈ "screenshots", располоТСнной Π² ΠΏΠ°ΠΏΠΊΠ΅ Ρ‚Π΅ΠΌΡ‹. - Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ список ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠ΅ΠΉ (pixmap, filename). + Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ список ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠ΅ΠΉ (pixmap, caption), Π³Π΄Π΅ caption - это ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ названия ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚Π°. Если ΠΏΠ°ΠΏΠΊΠ° отсутствуСт ΠΈΠ»ΠΈ пуста, возвращаСтся пустой список. """ screenshots = [] + + # Find the metainfo file for the theme + metainfo_file = None + for themes_dir in THEMES_DIRS: + theme_folder = os.path.join(themes_dir, theme_name) + temp_metainfo_file = os.path.join(theme_folder, "metainfo.ini") + if os.path.exists(temp_metainfo_file): + metainfo_file = temp_metainfo_file + break + for themes_dir in THEMES_DIRS: theme_folder = os.path.join(themes_dir, theme_name) screenshots_folder = os.path.join(theme_folder, "images", "screenshots") @@ -48,7 +59,13 @@ def load_theme_screenshots(theme_name): if os.path.isfile(screenshot_path) and is_safe_image_file(screenshot_path): pixmap = QPixmap(screenshot_path) if not pixmap.isNull(): - screenshots.append((pixmap, file)) + # Get the base filename without extension + base_filename = os.path.splitext(file)[0] + + # Get translated caption using localization function + caption = get_screenshot_caption(base_filename, metainfo_file) + + screenshots.append((pixmap, caption)) return screenshots def load_theme_fonts(theme_name): diff --git a/portprotonqt/themes/standart/images/screenshots/Автоустановки.jpg b/portprotonqt/themes/standart/images/screenshots/auto_installs.jpg similarity index 100% rename from portprotonqt/themes/standart/images/screenshots/Автоустановки.jpg rename to portprotonqt/themes/standart/images/screenshots/auto_installs.jpg diff --git a/portprotonqt/themes/standart/images/screenshots/ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚Π½ΠΎΠ΅ мСню.jpg b/portprotonqt/themes/standart/images/screenshots/context_menu.jpg similarity index 100% rename from portprotonqt/themes/standart/images/screenshots/ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚Π½ΠΎΠ΅ мСню.jpg rename to portprotonqt/themes/standart/images/screenshots/context_menu.jpg diff --git a/portprotonqt/themes/standart/images/screenshots/ΠšΠ°Ρ€Ρ‚ΠΎΡ‡ΠΊΠ°.jpg b/portprotonqt/themes/standart/images/screenshots/game_card.jpg similarity index 100% rename from portprotonqt/themes/standart/images/screenshots/ΠšΠ°Ρ€Ρ‚ΠΎΡ‡ΠΊΠ°.jpg rename to portprotonqt/themes/standart/images/screenshots/game_card.jpg diff --git a/portprotonqt/themes/standart/images/screenshots/Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°.jpg b/portprotonqt/themes/standart/images/screenshots/library.jpg similarity index 100% rename from portprotonqt/themes/standart/images/screenshots/Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°.jpg rename to portprotonqt/themes/standart/images/screenshots/library.jpg diff --git a/portprotonqt/themes/standart/images/screenshots/Настройки PortProton.jpg b/portprotonqt/themes/standart/images/screenshots/portproton_settings.jpg similarity index 100% rename from portprotonqt/themes/standart/images/screenshots/Настройки PortProton.jpg rename to portprotonqt/themes/standart/images/screenshots/portproton_settings.jpg diff --git a/portprotonqt/themes/standart/images/screenshots/Π’Π΅ΠΌΡ‹.jpg b/portprotonqt/themes/standart/images/screenshots/themes.jpg similarity index 100% rename from portprotonqt/themes/standart/images/screenshots/Π’Π΅ΠΌΡ‹.jpg rename to portprotonqt/themes/standart/images/screenshots/themes.jpg diff --git a/portprotonqt/themes/standart/images/screenshots/Настройки Wine.jpg b/portprotonqt/themes/standart/images/screenshots/wine_settings.jpg similarity index 100% rename from portprotonqt/themes/standart/images/screenshots/Настройки Wine.jpg rename to portprotonqt/themes/standart/images/screenshots/wine_settings.jpg diff --git a/portprotonqt/themes/standart/metainfo.ini b/portprotonqt/themes/standart/metainfo.ini index 78b9340..625e630 100644 --- a/portprotonqt/themes/standart/metainfo.ini +++ b/portprotonqt/themes/standart/metainfo.ini @@ -1,5 +1,23 @@ [Metainfo] author = Dervart author_link = -description = Бтандартная Ρ‚Π΅ΠΌΠ° PortProtonQt (Ρ‚Ρ‘ΠΌΠ½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚) -name = Clean Dark +name_en = Clean Dark +name_ru = Чистая тСмная +description_en = Standard PortProtonQt theme (dark variant) +description_ru = Бтандартная Ρ‚Π΅ΠΌΠ° PortProtonQt (Ρ‚Ρ‘ΠΌΠ½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚) + +[Screenshots] +auto_installs_en = Auto-installs +auto_installs_ru = Автоустановки +library_en = Library +library_ru = Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° +game_card_en = Game Card +game_card_ru = ΠšΠ°Ρ€Ρ‚ΠΎΡ‡ΠΊΠ° +context_menu_en = Context Menu +context_menu_ru = ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚Π½ΠΎΠ΅ мСню +portproton_settings_en = PortProton Settings +portproton_settings_ru = Настройки PortProton +wine_settings_en = Wine Settings +wine_settings_ru = Настройки Wine +themes_en = Themes +themes_ru = Π’Π΅ΠΌΡ‹