From 42851370e144e16190f74379cd3e9108038413ad Mon Sep 17 00:00:00 2001 From: JeffreyChen Date: Sun, 26 Jul 2026 21:49:32 +0800 Subject: [PATCH] Name the wordings that appear three times, and let translation tables repeat Four strings in the settings menu and one on the scene pages each appear three times - at construction, at registration, and in a warning box or a re-chooser. Three copies of the same sentence is three chances for them to drift, so each is now a constant. The other three were in the language dictionaries, where a repeated word is the normal state of affairs: Italian "Velocita" is both video speed and pet speed, Russian "Udalit" is "remove" in several dialogs. Hoisting those into constants would make the tables harder to read and harder to hand to a translator, which is the one thing they exist for, so S1192 is switched off for that directory with the reason written down next to it. --- .sonarcloud.properties | 14 ++++++++ frontengine/ui/menu/settings_menu.py | 33 ++++++++++++------- .../scene_page/base_scene_page.py | 11 +++++-- 3 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 .sonarcloud.properties diff --git a/.sonarcloud.properties b/.sonarcloud.properties new file mode 100644 index 0000000..dfaa36b --- /dev/null +++ b/.sonarcloud.properties @@ -0,0 +1,14 @@ +# SonarCloud 自動分析的設定 / Settings for SonarCloud automatic analysis. + +# 翻譯字典裡同一個詞在不同的鍵底下重複出現是正常的:義大利文的「Velocità」既是 +# 影片速度也是寵物速度,俄文的「Удалить」在好幾個對話框都是「移除」。把它們提成 +# 常數只會讓字典更難讀、更難交給翻譯的人看——那正是這種檔案存在的理由。 +# +# In a translation table the same word legitimately recurs under different +# keys: Italian "Velocità" is both video speed and pet speed, Russian +# "Удалить" is "remove" in several dialogs. Hoisting those into constants +# would make the tables harder to read and harder to hand to a translator, +# which is the one thing these files exist for. +sonar.issue.ignore.multicriteria=e1 +sonar.issue.ignore.multicriteria.e1.ruleKey=python:S1192 +sonar.issue.ignore.multicriteria.e1.resourceKey=frontengine/utils/multi_language/**/*.py diff --git a/frontengine/ui/menu/settings_menu.py b/frontengine/ui/menu/settings_menu.py index 9629da9..9503562 100644 --- a/frontengine/ui/menu/settings_menu.py +++ b/frontengine/ui/menu/settings_menu.py @@ -34,6 +34,15 @@ def _t(key: str, fallback: str) -> str: return language_wrapper.language_word_dict.get(key, fallback) +# 同一段文字會出現在建構、登記與警告框三個地方,提成常數免得三份各自漂移。 +# The same wording appears at construction, at registration and in a warning +# box; a constant keeps the three from drifting apart. +_AUTOSTART = "Start with the system" +_PLUGINS = "Load plugins (advanced)" +_EXPORT_SETTINGS = "Export settings..." +_IMPORT_SETTINGS = "Import settings..." + + def build_settings_menu(ui: "FrontEngineMainUI") -> None: """Build the Settings menu with hotkey configuration and settings I/O.""" front_engine_logger.info(f"[SettingsMenu] build_settings_menu | ui={ui}") @@ -55,8 +64,8 @@ def build_settings_menu(ui: "FrontEngineMainUI") -> None: menu.addAction(theme_schedule_action) ui.theme_schedule_action = theme_schedule_action - autostart_action = QAction(_t("settings_menu_autostart", "Start with the system"), menu) - retranslator.bind(autostart_action, "settings_menu_autostart", "Start with the system") + autostart_action = QAction(_t("settings_menu_autostart", _AUTOSTART), menu) + retranslator.bind(autostart_action, "settings_menu_autostart", _AUTOSTART) autostart_action.setCheckable(True) autostart_action.setChecked(autostart_service.is_enabled()) autostart_action.toggled.connect(lambda checked: _toggle_autostart(ui, checked)) @@ -71,8 +80,8 @@ def build_settings_menu(ui: "FrontEngineMainUI") -> None: menu.addAction(restore_action) ui.restore_session_action = restore_action - plugins_action = QAction(_t("settings_menu_plugins", "Load plugins (advanced)"), menu) - retranslator.bind(plugins_action, "settings_menu_plugins", "Load plugins (advanced)") + plugins_action = QAction(_t("settings_menu_plugins", _PLUGINS), menu) + retranslator.bind(plugins_action, "settings_menu_plugins", _PLUGINS) plugins_action.setCheckable(True) plugins_action.setChecked(bool(user_setting_dict.get("load_plugins"))) plugins_action.toggled.connect(lambda checked: _toggle_plugins(ui, checked)) @@ -137,13 +146,13 @@ def build_settings_menu(ui: "FrontEngineMainUI") -> None: ui.clipboard_toggle_action = clipboard_toggle menu.addSeparator() - export_action = QAction(_t("settings_menu_export", "Export settings..."), menu) - retranslator.bind(export_action, "settings_menu_export", "Export settings...") + export_action = QAction(_t("settings_menu_export", _EXPORT_SETTINGS), menu) + retranslator.bind(export_action, "settings_menu_export", _EXPORT_SETTINGS) export_action.triggered.connect(lambda: _export_settings(ui)) menu.addAction(export_action) - import_action = QAction(_t("settings_menu_import", "Import settings..."), menu) - retranslator.bind(import_action, "settings_menu_import", "Import settings...") + import_action = QAction(_t("settings_menu_import", _IMPORT_SETTINGS), menu) + retranslator.bind(import_action, "settings_menu_import", _IMPORT_SETTINGS) import_action.triggered.connect(lambda: _import_settings(ui)) menu.addAction(import_action) @@ -214,7 +223,7 @@ def _toggle_autostart(ui: "FrontEngineMainUI", enabled: bool) -> None: action.blockSignals(False) QMessageBox.warning( ui, - _t("settings_menu_autostart", "Start with the system"), + _t("settings_menu_autostart", _AUTOSTART), _t("settings_autostart_failed", "Could not change the autostart setting."), ) @@ -236,7 +245,7 @@ def _toggle_plugins(ui: "FrontEngineMainUI", enabled: bool) -> None: if enabled: QMessageBox.warning( ui, - _t("settings_menu_plugins", "Load plugins (advanced)"), + _t("settings_menu_plugins", _PLUGINS), _t("settings_plugins_warning", "Plugins are Python code and run with the same privileges as FrontEngine. " "Only install plugins you trust. Takes effect on the next launch."), @@ -266,7 +275,7 @@ def _open_hotkey_dialog(ui: "FrontEngineMainUI") -> None: def _export_settings(ui: "FrontEngineMainUI") -> None: - title = _t("settings_menu_export", "Export settings...") + title = _t("settings_menu_export", _EXPORT_SETTINGS) destination, _ok = QFileDialog.getSaveFileName( ui, title, "frontengine_settings.json", _t("settings_file_filter", "Settings files (*.json)") ) @@ -281,7 +290,7 @@ def _export_settings(ui: "FrontEngineMainUI") -> None: def _import_settings(ui: "FrontEngineMainUI") -> None: - title = _t("settings_menu_import", "Import settings...") + title = _t("settings_menu_import", _IMPORT_SETTINGS) source, _ok = QFileDialog.getOpenFileName( ui, title, "", _t("settings_file_filter", "Settings files (*.json)") ) diff --git a/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py b/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py index 7ceedfa..ea59001 100644 --- a/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +++ b/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py @@ -10,6 +10,11 @@ from frontengine.utils.multi_language.retranslate import retranslator, translate +# 建構、登記與「重選檔案」時各用一次,提成常數免得三份各自漂移。 +# Used at construction, at registration and when a file is re-chosen. +_NOT_READY = "Not Ready" + + class BaseSceneSettingUI(QWidget): """ Template Method base for the scene-setting pages. Subclasses lay out @@ -41,8 +46,8 @@ def _build_slider( return label, value_label, slider def _make_ready_label(self) -> QLabel: - label = QLabel(translate("Not Ready")) - retranslator.bind(label, "Not Ready") + label = QLabel(translate(_NOT_READY)) + retranslator.bind(label, _NOT_READY) return label def _wire_chooser( @@ -61,7 +66,7 @@ def handler() -> None: # set_text 而不是 setText:換語言時要跟著目前是就緒還是未就緒 # set_text, not setText, so a language change follows whichever # state the label is actually in. - retranslator.set_text(ready_label, "Not Ready") + retranslator.set_text(ready_label, _NOT_READY) on_reset() path = chooser(self) if path: