From fdff99c9f8158a5112fa89bbf57c7c27b7d2743e Mon Sep 17 00:00:00 2001 From: Michael Lam Date: Sun, 17 May 2026 06:09:08 -0700 Subject: [PATCH] fix: refresh theme command i18n help --- CHANGELOG.md | 4 +++ static/i18n.js | 12 ++++----- tests/test_issue2462_theme_i18n.py | 43 ++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 tests/test_issue2462_theme_i18n.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 93fb8cdd..f74d7c6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- **PR #2463** by @Michaelyklam (closes #2462) — Align `/theme` command help strings in Russian, German, Simplified Chinese, Traditional Chinese, and French with the current Theme × Skin contract. The localized command descriptions now mention `system/dark/light` plus the full skin list through `nous`, and French invalid-usage text now uses the actual `/theme ` slash command prefix. + ## [v0.51.82] — 2026-05-17 — Release BF (stage-375 — 2-PR batch — table renderer pipe protection + Catppuccin appearance skin) ### Added diff --git a/static/i18n.js b/static/i18n.js index d108fc20..084c6ce8 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -3762,7 +3762,7 @@ const LOCALES = { cmd_terminal: 'Открыть терминал рабочей области', cmd_new: 'Начать новую сессию чата', cmd_usage: 'Показать или скрыть использование токенов', - cmd_theme: 'Переключить тему (dark/light/slate/solarized/monokai/nord/oled)', + cmd_theme: 'Переключить внешний вид (тема: system/dark/light, скин: default/ares/mono/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous)', cmd_personality: 'Переключить личность агента', cmd_skills: 'Показать доступные навыки Hermes', available_commands: 'Доступные команды:', @@ -6042,7 +6042,7 @@ const LOCALES = { cmd_terminal: 'Workspace-Terminal öffnen', cmd_new: 'Neue Chat-Sitzung starten', cmd_usage: 'Token-Verbrauchsanzeige umschalten', - cmd_theme: 'Darstellung wechseln (Theme: system/dark/light, Skin: default/ares/mono/slate/poseidon/sisyphus/charizard)', + cmd_theme: 'Darstellung wechseln (Theme: system/dark/light, Skin: default/ares/mono/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous)', cmd_personality: 'Agenten-Persönlichkeit wechseln', cmd_skills: 'Verfügbare Hermes-Skills auflisten', available_commands: 'Verfügbare Befehle:', @@ -7206,7 +7206,7 @@ const LOCALES = { cmd_terminal: '打开工作区 Terminal', cmd_new: '新建聊天会话', cmd_usage: '切换 token 用量显示', - cmd_theme: '切换外观(主题:system/dark/light,皮肤:default/ares/mono/slate/poseidon/sisyphus/charizard)', + cmd_theme: '切换外观(主题:system/dark/light,皮肤:default/ares/mono/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous)', cmd_personality: '切换 Agent 人设', cmd_skills: '列出可用的 Hermes 技能', available_commands: '可用命令:', @@ -8307,7 +8307,7 @@ const LOCALES = { cmd_terminal: '\u6253\u958b\u5de5\u4f5c\u5340 Terminal', cmd_new: '\u65b0\u5efa\u804a\u5929\u6703\u8a71', cmd_usage: '\u5207\u63db token \u7528\u91cf\u986f\u793a', - cmd_theme: '\u5207\u63db\u5916\u89c0\uff08\u4e3b\u984c\uff1asystem/dark/light\uff0c\u76ae\u819a\uff1adefault/ares/mono/slate/poseidon/sisyphus/charizard\uff09', + cmd_theme: '\u5207\u63db\u5916\u89c0\uff08\u4e3b\u984c\uff1asystem/dark/light\uff0c\u76ae\u819a\uff1adefault/ares/mono/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous\uff09', cmd_personality: '\u5207\u63db Agent \u4eba\u8a2d', cmd_skills: '\u5217\u51fa\u53ef\u7528\u7684 Hermes \u6280\u80fd', available_commands: '\u53ef\u7528\u547d\u4ee4\uff1a', @@ -11779,7 +11779,7 @@ const LOCALES = { cmd_terminal: 'Ouvrez le terminal de l\'espace de travail', cmd_new: 'Démarrer une nouvelle session de discussion', cmd_usage: 'Activer/désactiver l\'affichage de l\'utilisation du jeton', - cmd_theme: 'Changer d\'apparence (thème : système/dark/light, skin : default/ares/mono/slate/poseidon/sisyphus/charizard)', + cmd_theme: 'Changer d\'apparence (thème : system/dark/light, skin : default/ares/mono/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous)', cmd_personality: 'Personnalité de l\'agent de commutation', cmd_skills: 'Lister les compétences Hermès disponibles', available_commands: 'Commandes disponibles :', @@ -11805,7 +11805,7 @@ const LOCALES = { focus_label: 'Se concentrer', token_usage_on: 'Utilisation du jeton sur', token_usage_off: 'Utilisation des jetons désactivée', - theme_usage: 'Utilisation : /thème', + theme_usage: 'Utilisation : /theme ', theme_set: 'Thème:', no_active_session: 'Aucune session active', cmd_queue: 'Mettre un message en file d\'attente pour le prochain tour', diff --git a/tests/test_issue2462_theme_i18n.py b/tests/test_issue2462_theme_i18n.py new file mode 100644 index 00000000..c34bea37 --- /dev/null +++ b/tests/test_issue2462_theme_i18n.py @@ -0,0 +1,43 @@ +"""Regression coverage for #2462 stale /theme i18n help strings.""" + +from pathlib import Path +import re + +ROOT = Path(__file__).resolve().parents[1] +I18N_JS = (ROOT / "static" / "i18n.js").read_text(encoding="utf-8") + + +def _locale_block(locale: str) -> str: + # Locale keys are mostly bare identifiers, but zh-Hant is quoted. Match the + # requested block up to the next top-level locale block or the LOCALES close. + match = re.search( + rf"\n\s*['\"]?{re.escape(locale)}['\"]?:\s*\{{(?P.*?)(?=\n\s*['\"]?[a-z][\w-]*['\"]?:\s*\{{|\n\}};)", + I18N_JS, + re.S, + ) + assert match, f"locale block {locale!r} not found" + return match.group("body") + + +def _literal_value(block: str, key: str) -> str: + match = re.search(rf"\n\s*{re.escape(key)}:\s*'(?P(?:\\'|[^'])*)',", block) + assert match, f"{key!r} not found in locale block" + return match.group("value") + + +def test_theme_command_help_mentions_current_theme_and_skin_values(): + """Every /theme help string should describe the current Theme × Skin contract.""" + required_fragments = ( + "system/dark/light", + "default/ares/mono/slate/poseidon/sisyphus/charizard/sienna/catppuccin/nous", + ) + for locale in ("en", "it", "ja", "ru", "es", "de", "zh", "zh-Hant", "pt", "ko", "fr"): + value = _literal_value(_locale_block(locale), "cmd_theme") + for fragment in required_fragments: + assert fragment in value, f"{locale} cmd_theme missing {fragment!r}: {value!r}" + + +def test_french_theme_usage_uses_actual_slash_command_with_space(): + fr_theme_usage = _literal_value(_locale_block("fr"), "theme_usage") + assert fr_theme_usage == "Utilisation : /theme " + assert "/thème" not in fr_theme_usage