From 284543a6d980341632abf175956b36b6bd06b9b2 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Tue, 23 Jan 2024 22:02:22 +0200 Subject: [PATCH] Rare: Decouple Rare's locale from legendary's * Instead of using legendary's locale as fallback, use system't locale as default. * Do not hardcode language names and countries but use QLocale on the translation filenames. --- rare/components/__init__.py | 5 +- rare/components/tabs/settings/rare.py | 46 ++++++++----------- rare/components/tabs/settings/widgets/wine.py | 3 +- rare/launcher/__init__.py | 4 +- rare/models/options.py | 2 + rare/models/signals.py | 4 +- rare/utils/misc.py | 42 +++++------------ rare/utils/paths.py | 1 + rare/widgets/rare_app.py | 28 +++++------ 9 files changed, 56 insertions(+), 79 deletions(-) diff --git a/rare/components/__init__.py b/rare/components/__init__.py index f4c9cce4..63c97693 100644 --- a/rare/components/__init__.py +++ b/rare/components/__init__.py @@ -9,6 +9,7 @@ from PyQt5.QtCore import QThreadPool, QTimer, pyqtSlot, Qt from PyQt5.QtWidgets import QApplication, QMessageBox from requests import HTTPError +from rare.models.options import options from rare.components.dialogs.launch_dialog import LaunchDialog from rare.components.main_window import MainWindow from rare.shared import RareCore @@ -45,8 +46,8 @@ class Rare(RareApp): self.signals = RareCore.instance().signals() self.core = RareCore.instance().core() - lang = self.settings.value("language", self.core.language_code, type=str) - self.load_translator(lang) + language = self.settings.value(*options.language) + self.load_translator(language) # set Application name for settings self.main_window: Optional[MainWindow] = None diff --git a/rare/components/tabs/settings/rare.py b/rare/components/tabs/settings/rare.py index b366ba38..ad03b80f 100644 --- a/rare/components/tabs/settings/rare.py +++ b/rare/components/tabs/settings/rare.py @@ -23,17 +23,6 @@ from rare.utils.paths import create_desktop_link, desktop_link_path, log_dir, de logger = getLogger("RareSettings") -languages = [("en", "English"), - ("de", "Deutsch"), - ("fr", "Français"), - ("zh-Hans", "Simplified Chinese"), - ("zh_TW", "Chinese Taiwan"), - ("pt_BR", "Portuguese (Brazil)"), - ("ca", "Catalan"), - ("ru", "Russian"), - ("tr", "Turkish"), - ("uk", "Ukrainian")] - class RareSettings(QWidget, Ui_RareSettings): def __init__(self, parent=None): @@ -42,20 +31,19 @@ class RareSettings(QWidget, Ui_RareSettings): self.core = LegendaryCoreSingleton() self.settings = QSettings(self) - language = self.settings.value("language", self.core.language_code, type=str) - # Select lang - self.lang_select.addItems([i[1] for i in languages]) - if language in get_translations(): - index = [lang[0] for lang in languages].index(language) + language = self.settings.value(*options.language) + self.lang_select.addItem(self.tr("System default"), "") + for locale, title in get_translations(): + self.lang_select.addItem(title, locale) + if (index := self.lang_select.findData(language, Qt.UserRole)) > 0: self.lang_select.setCurrentIndex(index) else: self.lang_select.setCurrentIndex(0) - self.lang_select.currentIndexChanged.connect(self.update_lang) + self.lang_select.currentIndexChanged.connect(self.on_lang_changed) - colors = get_color_schemes() - self.color_select.addItems(colors) - if (color := self.settings.value("color_scheme")) in colors: + self.color_select.addItems(get_color_schemes()) + if (color := self.settings.value("color_scheme")) in get_color_schemes(): self.color_select.setCurrentIndex(self.color_select.findText(color)) self.color_select.setDisabled(False) self.style_select.setDisabled(True) @@ -63,9 +51,8 @@ class RareSettings(QWidget, Ui_RareSettings): self.color_select.setCurrentIndex(0) self.color_select.currentIndexChanged.connect(self.on_color_select_changed) - styles = get_style_sheets() - self.style_select.addItems(styles) - if (style := self.settings.value("style_sheet")) in styles: + self.style_select.addItems(get_style_sheets()) + if (style := self.settings.value("style_sheet")) in get_style_sheets(): self.style_select.setCurrentIndex(self.style_select.findText(style)) self.style_select.setDisabled(False) self.color_select.setDisabled(True) @@ -129,7 +116,7 @@ class RareSettings(QWidget, Ui_RareSettings): self.desktop_link_btn.clicked.connect(self.create_desktop_link) self.startmenu_link_btn.clicked.connect(self.create_start_menu_link) - self.log_dir_open_button.clicked.connect(self.open_dir) + self.log_dir_open_button.clicked.connect(self.open_directory) self.log_dir_clean_button.clicked.connect(self.clean_logdir) # get size of logdir @@ -212,7 +199,8 @@ class RareSettings(QWidget, Ui_RareSettings): self.color_select.setDisabled(False) set_style_sheet("") - def open_dir(self): + @staticmethod + def open_directory(): if platform.system() == "Windows": os.startfile(log_dir()) # pylint: disable=E1101 else: @@ -223,5 +211,9 @@ class RareSettings(QWidget, Ui_RareSettings): self.settings.setValue(options.save_size.key, self.save_size.isChecked()) self.settings.remove(options.window_size.key) - def update_lang(self, i: int): - self.settings.setValue("language", languages[i][0]) + def on_lang_changed(self, index: int): + if not index: + self.settings.remove(options.language.key) + return + language = self.lang_select.itemData(index, Qt.UserRole) + self.settings.setValue(options.language.key, language) diff --git a/rare/components/tabs/settings/widgets/wine.py b/rare/components/tabs/settings/widgets/wine.py index 38aad691..9d2f239f 100644 --- a/rare/components/tabs/settings/widgets/wine.py +++ b/rare/components/tabs/settings/widgets/wine.py @@ -19,7 +19,7 @@ class WineSettings(QGroupBox): def __init__(self, parent=None): super(WineSettings, self).__init__(parent=parent) - self.setTitle(self.tr("Wine Setings")) + self.setTitle(self.tr("Wine settings")) self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() @@ -79,7 +79,6 @@ class WineSettings(QGroupBox): raise RuntimeError config.save_wine_prefix(self.app_name, path) self.environ_changed.emit("WINEPREFIX") - self.signals.application.prefix_updated.emit() def load_exec(self) -> str: if self.app_name is None: diff --git a/rare/launcher/__init__.py b/rare/launcher/__init__.py index cd26bf45..090c710f 100644 --- a/rare/launcher/__init__.py +++ b/rare/launcher/__init__.py @@ -143,8 +143,8 @@ class RareLauncher(RareApp): return self.rgame = RareGameSlim(self.core, game) - lang = self.settings.value("language", self.core.language_code, type=str) - self.load_translator(lang) + language = self.settings.value(*options.language) + self.load_translator(language) if QSettings(self).value(*options.log_games): self.console = ConsoleDialog(game.app_title) diff --git a/rare/models/options.py b/rare/models/options.py index f5bb4f2e..42f0529d 100644 --- a/rare/models/options.py +++ b/rare/models/options.py @@ -1,3 +1,4 @@ +import locale import platform as pf from argparse import Namespace from typing import Any, Type @@ -24,6 +25,7 @@ class Defaults(Namespace): exclude_non_asset = Value(key="exclude_non_asset", default=False, dtype=bool) exclude_entitlements = Value(key="exclude_entitlements", default=False, dtype=bool) + language = Value(key="language", default=locale.getlocale()[0], dtype=str) sys_tray = Value(key="sys_tray", default=True, dtype=bool) auto_update = Value(key="auto_update", default=False, dtype=bool) auto_sync_cloud = Value(key="auto_sync_cloud", default=False, dtype=bool) diff --git a/rare/models/signals.py b/rare/models/signals.py index 522ad7f9..e79ef531 100644 --- a/rare/models/signals.py +++ b/rare/models/signals.py @@ -14,11 +14,11 @@ class GlobalSignals: # str: title, str: body notify = pyqtSignal(str, str) # none - prefix_updated = pyqtSignal() - # none update_tray = pyqtSignal() # none update_statusbar = pyqtSignal() + # str: locale + # change_translation = pyqtSignal(str) class GameSignals(QObject): # model diff --git a/rare/utils/misc.py b/rare/utils/misc.py index aa27a36a..77a64865 100644 --- a/rare/utils/misc.py +++ b/rare/utils/misc.py @@ -1,16 +1,15 @@ import os from enum import IntEnum from logging import getLogger -from typing import List, Union, Type, Dict +from typing import Union, Type, Dict, Tuple, Iterable import qtawesome -import requests from PyQt5.QtCore import ( QObject, QSettings, QFile, QDir, - Qt, + Qt, QLocale, ) from PyQt5.QtGui import QPalette, QColor, QFontMetrics from PyQt5.QtWidgets import qApp, QStyleFactory, QLabel @@ -106,11 +105,8 @@ def set_color_pallete(color_scheme: str) -> None: qtawesome.set_defaults(color=icon_color) -def get_color_schemes() -> List[str]: - colors = [] - for file in QDir(":/schemes"): - colors.append(file) - return colors +def get_color_schemes() -> Iterable[str]: + yield from QDir(":/schemes") def set_style_sheet(style_sheet: str) -> None: @@ -132,31 +128,17 @@ def set_style_sheet(style_sheet: str) -> None: qtawesome.set_defaults(color="#eeeeee") -def get_style_sheets() -> List[str]: - styles = [] - for file in QDir(":/stylesheets/"): - styles.append(file) - return styles +def get_style_sheets() -> Iterable[str]: + yield from QDir(":/stylesheets/") -def get_translations(): - langs = ["en"] +def get_translations() -> Tuple[Tuple[str, str], ...]: + langs = [] for i in os.listdir(os.path.join(resources_path, "languages")): if i.endswith(".qm") and not i.startswith("qt_"): - langs.append(i.split(".")[0]) - return langs - - -def get_latest_version(): - try: - resp = requests.get( - "https://api.github.com/repos/RareDevs/Rare/releases/latest", - timeout=2, - ) - tag = resp.json()["tag_name"] - return tag - except requests.exceptions.ConnectionError: - return "0.0.0" + locale = QLocale(i.split(".")[0]) + langs.append((locale.name(), f"{locale.nativeLanguageName()} ({locale.nativeCountryName()})")) + return tuple(langs) def path_size(path: Union[str, os.PathLike]) -> int: @@ -169,7 +151,7 @@ def path_size(path: Union[str, os.PathLike]) -> int: def format_size(b: Union[int, float]) -> str: - for s in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"]: + for s in ("", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"): if b < 1024: return f"{b:.2f} {s}B" b /= 1024 diff --git a/rare/utils/paths.py b/rare/utils/paths.py index 119ef1e1..ac7630cb 100644 --- a/rare/utils/paths.py +++ b/rare/utils/paths.py @@ -15,6 +15,7 @@ if platform.system() == "Windows": logger = getLogger("Paths") +# This depends on the location of this file (obviously) resources_path = Path(__file__).absolute().parent.parent.joinpath("resources") # lk: delete old Rare directories diff --git a/rare/widgets/rare_app.py b/rare/widgets/rare_app.py index c3c86c66..5b8ba3c5 100644 --- a/rare/widgets/rare_app.py +++ b/rare/widgets/rare_app.py @@ -101,11 +101,11 @@ class RareApp(QApplication): f" - Qt version: {QT_VERSION_STR}, PyQt version: {PYQT_VERSION_STR}" ) - self.settings = QSettings() + self.settings = QSettings(self) # Translator - self.translator = QTranslator() - self.qt_translator = QTranslator() + self.translator = QTranslator(self) + self.qt_translator = QTranslator(self) # Style # lk: this is a bit silly but serves well until we have a class @@ -129,15 +129,15 @@ class RareApp(QApplication): self.setWindowIcon(QIcon(":/images/Rare.png")) def load_translator(self, lang: str): - if os.path.isfile(f := os.path.join(paths.resources_path, "languages", f"{lang}.qm")): - self.translator.load(f) - self.logger.info(f"Your language is supported: {lang}") - elif not lang == "en": - self.logger.info("Your language is not supported") - self.installTranslator(self.translator) - # translator for qt stuff - if os.path.isfile(f := os.path.join(paths.resources_path, f"qt_{lang}.qm")): - self.qt_translator = QTranslator() - self.qt_translator.load(f) - self.installTranslator(self.qt_translator) + if self.qt_translator.load(f"qt_{lang}", os.path.join(paths.resources_path, "languages")): + self.logger.debug("Using translation for locale: $s", lang) + else: + self.logger.info("Couldn't find translation for locale: %s", lang) + self.installTranslator(self.qt_translator) + + if self.translator.load(lang, os.path.join(paths.resources_path, "languages")): + self.logger.info("Using translation for locale: $s", lang) + else: + self.logger.info("Couldn't find translation for locale: %s", lang) + self.installTranslator(self.translator)