From db082e8d922df4d0cf10af2b26723591e21d239c Mon Sep 17 00:00:00 2001 From: Isla-Liu Date: Wed, 8 Jul 2026 11:50:13 +0800 Subject: [PATCH] fix: localize process wakeup label --- static/i18n.js | 15 +++++++++++++++ static/ui.js | 2 +- tests/test_process_wakeup_rendering.py | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/static/i18n.js b/static/i18n.js index b7ed9244..d2576da9 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -355,6 +355,7 @@ const LOCALES = { bg_label:'Background result:', bg_no_answer:'(no answer)', bg_failed:'Background task failed: ', + process_wakeup_label:'Background wakeup', undo_exchange:'Undo last exchange', cmd_status:'Show session info', cmd_voice:'Toggle microphone input', @@ -2056,6 +2057,7 @@ const LOCALES = { bg_label:'Risultato background:', bg_no_answer:'(nessuna risposta)', bg_failed:'Task in background fallito: ', + process_wakeup_label:'Riattivazione in background', undo_exchange:'Annulla ultimo scambio', cmd_status:'Mostra info sessione', cmd_voice:'Attiva/disattiva input microfono', @@ -3748,6 +3750,7 @@ const LOCALES = { bg_label:'バックグラウンド結果:', bg_no_answer:'(回答なし)', bg_failed:'バックグラウンドタスク失敗: ', + process_wakeup_label:'バックグラウンド起動', undo_exchange:'最後のやり取りを取り消す', cmd_status:'セッション情報を表示', cmd_voice:'マイク入力を切り替え', @@ -5361,6 +5364,7 @@ const LOCALES = { composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', composer_placeholder_busy_steer: 'Enter = steer | /queue | /background | /interrupt', + process_wakeup_label: 'Фоновое пробуждение', no_personalities: 'Личности не найдены (добавьте их в ~/.hermes/personalities/)', clarify_heading: 'Требуется уточнение', @@ -7042,6 +7046,7 @@ const LOCALES = { composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', composer_placeholder_busy_steer: 'Enter = steer | /queue | /background | /interrupt', + process_wakeup_label: 'Activación en segundo plano', no_personalities: 'No se encontraron personalidades (añádelas a ~/.hermes/personalities/)', available_personalities: 'Personalidades disponibles:', personality_switch_hint: '\n\nUsa `/personality ` para cambiar, o `/personality none` para limpiar.', @@ -8640,6 +8645,7 @@ const LOCALES = { composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', composer_placeholder_busy_steer: 'Enter = steer | /queue | /background | /interrupt', + process_wakeup_label: 'Hintergrund-Aktivierung', no_personalities: 'Keine Persönlichkeiten gefunden (füge sie in ~/.hermes/personalities/ hinzu)', available_personalities: 'Verfügbare Persönlichkeiten:', personality_switch_hint: '\n\nNutze `/personality ` zum Wechseln, oder `/personality none` zum Löschen.', @@ -10301,6 +10307,7 @@ const LOCALES = { composer_placeholder_busy_queue: 'Enter = 队列 | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = 中断 | /queue | /background | /steer', composer_placeholder_busy_steer: 'Enter = 引导 | /queue | /background | /interrupt', + process_wakeup_label: '后台唤醒', settings_plugins_title: '插件', plugins_enable_toggle: '启用', settings_plugins_meta: '查看已安装的 Hermes 插件及其注册的生命周期挂钩。此面板为只读。', @@ -11965,6 +11972,7 @@ const LOCALES = { bg_label: '背景結果:', bg_no_answer: '(沒有回答)', bg_failed: '背景任務失敗:', + process_wakeup_label: '背景喚醒', undo_exchange: '復原上一組問答', cmd_status: '顯示對話資訊', cmd_voice: '切換麥克風輸入', @@ -13585,6 +13593,7 @@ const LOCALES = { bg_label: 'Resultado de background:', bg_no_answer: '(sem resposta)', bg_failed: 'Tarefa de background falhou: ', + process_wakeup_label: 'Reativação em background', undo_exchange: 'Desfazer última troca', cmd_status: 'Mostrar info da sessão', cmd_voice: 'Alternar input de microfone', @@ -15154,6 +15163,7 @@ const LOCALES = { bg_label: '백그라운드 결과:', bg_no_answer: '(답변 없음)', bg_failed: '백그라운드 작업 실패: ', + process_wakeup_label: '백그라운드 깨우기', undo_exchange: '마지막 교환 실행 취소', cmd_status: '세션 정보 표시', cmd_voice: '마이크 입력 전환', @@ -16845,6 +16855,7 @@ const LOCALES = { bg_label: 'Résultat en arrière-plan :', bg_no_answer: '(aucune réponse)', bg_failed: 'Échec de la tâche en arrière-plan : ', + process_wakeup_label: 'Réveil en arrière-plan', undo_exchange: 'Annuler le dernier échange', cmd_status: 'Afficher les informations de la session', cmd_voice: 'Activer/désactiver la saisie microphone', @@ -19350,6 +19361,7 @@ const LOCALES = { available_personalities: 'Dostupné osobnosti:', bg_complete: 'Úkol na pozadí dokončen', bg_failed: 'Úkol na pozadí se nezdařil:', + process_wakeup_label: 'Probuzení na pozadí', bg_label: 'Výsledek na pozadí:', bg_no_answer: 'Žádná odpověď', bg_running: 'Běží na pozadí...', @@ -20171,6 +20183,7 @@ const LOCALES = { bg_label: 'Arka plan sonucu:', bg_no_answer: '(cevap yok)', bg_failed: 'Arka plan görevi başarısız oldu:', + process_wakeup_label: 'Arka plan uyandırması', undo_exchange: 'Son değişimi geri al', cmd_status: 'Oturum bilgilerini göster', cmd_voice: 'Mikrofon girişini değiştir', @@ -21866,6 +21879,7 @@ const LOCALES = { bg_label: 'Wynik z tła:', bg_no_answer: '(brak odpowiedzi)', bg_failed: 'Zadanie w tle nie powiodło się: ', + process_wakeup_label: 'Wybudzenie w tle', undo_exchange: 'Cofnij ostatnią wymianę', cmd_status: 'Pokaż informacje o sesji', cmd_voice: 'Przełącz wejście mikrofonu', @@ -23520,6 +23534,7 @@ const LOCALES = { bg_label:'Kết quả nền:', bg_no_answer:'(không có câu trả lời)', bg_failed:'Tác vụ nền thất bại: ', + process_wakeup_label:'Đánh thức nền', undo_exchange:'Hoàn tác lượt trao đổi cuối', cmd_status:'Hiển thị thông tin phiên', cmd_voice:'Bật/tắt nhập microphone', diff --git a/static/ui.js b/static/ui.js index 6f21f9a8..59682d7f 100644 --- a/static/ui.js +++ b/static/ui.js @@ -14504,7 +14504,7 @@ function renderMessages(options){ const processText=String(rowDisplayContent||'').trim(); const processFootHtml=`
${timeHtml}${copyBtn}
`; const processTextHtml=processText?`
${esc(processText)}
`:''; - const nextRowHtml=`
${li('terminal',13)}Background wakeup
${filesHtml}
${processTextHtml}
${processFootHtml}
`; + const nextRowHtml=`
${li('terminal',13)}${esc(t('process_wakeup_label'))}
${filesHtml}
${processTextHtml}
${processFootHtml}
`; if(row){ row.className='msg-row process-wakeup-row'; row.id=_userMessageDomId(rawIdx); diff --git a/tests/test_process_wakeup_rendering.py b/tests/test_process_wakeup_rendering.py index 051a3845..cee5b91b 100644 --- a/tests/test_process_wakeup_rendering.py +++ b/tests/test_process_wakeup_rendering.py @@ -8,6 +8,7 @@ preceded the notification and the assistant response produced by the wakeup. """ import json +import re import shutil import subprocess from pathlib import Path @@ -18,6 +19,7 @@ import pytest ROOT = Path(__file__).resolve().parents[1] UI_JS_PATH = ROOT / "static" / "ui.js" STYLE_CSS = (ROOT / "static" / "style.css").read_text(encoding="utf-8") +I18N_JS = (ROOT / "static" / "i18n.js").read_text(encoding="utf-8") NODE = shutil.which("node") pytestmark = pytest.mark.skipif(NODE is None, reason="node not on PATH") @@ -193,6 +195,8 @@ def test_process_wakeup_uses_compact_status_row_not_normal_user_bubble(): assert "process-wakeup-notice" in process_branch assert "data-role='process_wakeup'" in process_branch or "dataset.role='process_wakeup'" in process_branch assert "${filesHtml}" in process_branch + assert "t('process_wakeup_label')" in process_branch + assert "Background wakeup" not in process_branch assert "const rowDisplayContent=displayContent;" in ui assert "const rowDisplayContent=isProcessWakeup?content:displayContent;" not in ui @@ -207,3 +211,15 @@ def test_process_wakeup_uses_compact_status_row_not_normal_user_bubble(): assert "margin-left:30px" not in notice_rule assert "max-width:680px" not in notice_rule assert "@media(max-width:700px){.process-wakeup-notice{margin-left:0;}}" in STYLE_CSS + + +def test_process_wakeup_label_key_exists_in_all_locales(): + locale_pattern = re.compile( + r"^\s{2}(?:'(?P[A-Za-z0-9-]+)'|(?P[A-Za-z0-9-]+))\s*:\s*\{", + re.MULTILINE, + ) + locales = [m.group("quoted") or m.group("plain") for m in locale_pattern.finditer(I18N_JS)] + assert locales, "expected at least the English locale" + key_defs = re.findall(r"\bprocess_wakeup_label\s*:", I18N_JS) + assert len(key_defs) >= len(locales), "process_wakeup_label must be defined in every locale" + assert "process_wakeup_label:'Background wakeup'" in I18N_JS