diff --git a/CHANGELOG.md b/CHANGELOG.md index da1fa30c..284a82be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### Added - **PR #2460** by @Michaelyklam (closes #2449) — Add a copy button to Thinking card headers so users can copy the card's reasoning text without selecting the `
` manually. The button stops header-toggle propagation and shows the same short checkmark feedback pattern used by existing copy actions.
+- **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)
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