From 2256c2c711c5f5940408bf5e1f5f2e0a0ac87db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=B4=E5=A4=A9?= Date: Thu, 14 May 2026 07:41:01 +0800 Subject: [PATCH] =?UTF-8?q?fix(audit):=20=E5=A4=8D=E6=9F=A5=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E6=B3=A2=20=E2=80=94=20Hermes=20=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E5=90=91=E5=AF=BC=20i18n=20=E5=8C=96=E6=BC=8F=E7=BD=91?= =?UTF-8?q?=E4=B8=AD=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 第三轮逐文件复查发现 hermes/pages/setup.js 还有大量用户首屏可见的 中文硬编码(之前两轮主要扫 timer/cleanup/syntax/listener 类 bug)。 ## 涉及修复 ### setup.js phase 标签(5 处) phase indicator 是用户最早看到的 UI 元素: ``` { id: 'detect', label: '检测' } → t('engine.hermesPhaseDetect') { id: 'install', label: '安装' } → t('engine.hermesPhaseInstall') { id: 'configure', label: '配置' } → t('engine.hermesPhaseConfigure') { id: 'gateway', label: '启动' } → t('engine.hermesPhaseGateway') { id: 'complete', label: '完成' } → t('engine.hermesPhaseComplete') ``` 英文用户原本看到的是 5 个汉字,现在按系统语言显示 Detect / Install / Configure / Start / Complete。 ### setup.js Provider 分组标题(4 组) configure 阶段渲染 provider 选择按钮时分组标题: ``` '国际 · API Key' → hermesProviderGroupIntl '国内 · API Key' → hermesProviderGroupCn '聚合 / 路由' → hermesProviderGroupAggregator 'OAuth 登录(需终端)' → hermesProviderGroupOAuth ':需运行' → hermesProviderOAuthRunHint ``` ### setup.js Provider 加载失败 fallback 文案 Web 模式下 provider 列表加载失败时的 12 行多行 hint,原本只有中文, 现已 11 语言 i18n。 ### setup.js 检测异常日志 prefix ```js logs.push(`检测错误: ${e}`) → `[detect error] ${e?.message || e}` ``` 日志输出(用户在向导首屏可见)跟其他英文 prefix 一致,便于日志聚合。 ## 新增 i18n key(engine 模块) - hermesPhaseDetect / Install / Configure / Gateway / Complete - hermesProviderGroupIntl / Cn / Aggregator / OAuth - hermesProviderOAuthRunHint - hermesProvidersLoadFallback 11 语言全覆盖(zh-CN / zh-TW / en / ja / ko / vi / es / pt / ru / fr / de)。 ## 复查范围(第三轮) - src-tauri/src/commands/*.rs unwrap 全 safe(regex / SystemTime / Mutex) - src/lib/ humanize-error / engine-manager / ws-client / message-db / tts 全部健全 - src/components/ modal / toast 无问题 - scripts/dev-api.js 176 个 handler 无 duplicate / 关键命令全有 - src/pages/ 没发现新硬编码(之前的 i18n 覆盖到位) - src/engines/hermes/pages/ setup.js 是唯一遗漏的中文重灾区,已修 ## 验证 - npm run build:PASS(1.46s) - 总计三轮复查共修 11 个 bug + 5 个 i18n 漏网 --- src/engines/hermes/pages/setup.js | 24 ++++++++++++------------ src/locales/modules/engine.js | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/engines/hermes/pages/setup.js b/src/engines/hermes/pages/setup.js index a24e660..32ce4db 100644 --- a/src/engines/hermes/pages/setup.js +++ b/src/engines/hermes/pages/setup.js @@ -67,11 +67,11 @@ export function render() { // --- 阶段指示器 --- function renderPhaseIndicator() { const phases = [ - { id: 'detect', label: '检测' }, - { id: 'install', label: '安装' }, - { id: 'configure', label: '配置' }, - { id: 'gateway', label: '启动' }, - { id: 'complete', label: '完成' }, + { id: 'detect', label: t('engine.hermesPhaseDetect') }, + { id: 'install', label: t('engine.hermesPhaseInstall') }, + { id: 'configure', label: t('engine.hermesPhaseConfigure') }, + { id: 'gateway', label: t('engine.hermesPhaseGateway') }, + { id: 'complete', label: t('engine.hermesPhaseComplete') }, ] const idx = phases.findIndex(p => p.id === phase) return `
${phases.map((p, i) => { @@ -420,7 +420,7 @@ export function render() { } draw() } catch (e) { - logs.push(`检测错误: ${e}`) + logs.push(`[detect error] ${e?.message || e}`) phase = 'install' draw() } @@ -686,7 +686,7 @@ export function render() { function renderGroupedProviderButtons() { if (!hermesProviders.length) { return `
- 未能加载 provider 列表。Web 模式下可手动填写下方 Base URL 与 API Key 完成配置。 + ${t('engine.hermesProvidersLoadFallback')}
` } @@ -708,19 +708,19 @@ function renderGroupedProviderButtons() { const parts = [] if (hermesGroups.apiKeyIntl.length) { - parts.push(`
国际 · API Key
${hermesGroups.apiKeyIntl.map(btn).join('')}
`) + parts.push(`
${t('engine.hermesProviderGroupIntl')}
${hermesGroups.apiKeyIntl.map(btn).join('')}
`) } if (hermesGroups.apiKeyCn.length) { - parts.push(`
国内 · API Key
${hermesGroups.apiKeyCn.map(btn).join('')}
`) + parts.push(`
${t('engine.hermesProviderGroupCn')}
${hermesGroups.apiKeyCn.map(btn).join('')}
`) } if (hermesGroups.aggregators.length) { - parts.push(`
聚合 / 路由
${hermesGroups.aggregators.map(btn).join('')}
`) + parts.push(`
${t('engine.hermesProviderGroupAggregator')}
${hermesGroups.aggregators.map(btn).join('')}
`) } if (hermesGroups.oauth.length) { const oauthItems = hermesGroups.oauth.map(p => - `
${p.name}:需运行 ${p.cliAuthHint}
` + `
${p.name}:${t('engine.hermesProviderOAuthRunHint') || '需运行'} ${p.cliAuthHint}
` ).join('') - parts.push(`
OAuth 登录(需终端)
${oauthItems}
`) + parts.push(`
${t('engine.hermesProviderGroupOAuth')}
${oauthItems}
`) } return parts.join('') diff --git a/src/locales/modules/engine.js b/src/locales/modules/engine.js index a8cedc8..40d4e50 100644 --- a/src/locales/modules/engine.js +++ b/src/locales/modules/engine.js @@ -46,6 +46,31 @@ export default { choiceSecondaryLater: _('稍后再说', 'Decide later', '稍後再說'), hermesSetupDesc: _('安装并配置 Hermes Agent', 'Install and configure Hermes Agent', '安裝並配置 Hermes Agent'), hermesPhaseClickHint: _('点击可返回此步骤', 'Click to go back to this step', '點擊可返回此步驟', 'このステップに戻るにはクリック', '이 단계로 돌아가려면 클릭'), + // 安装向导 5 个阶段标签 + hermesPhaseDetect: _('检测', 'Detect', '檢測', '検出', '감지', 'Phát hiện', 'Detectar', 'Detectar', 'Обнаружение', 'Détection', 'Erkennung'), + hermesPhaseInstall: _('安装', 'Install', '安裝', 'インストール', '설치', 'Cài đặt', 'Instalar', 'Instalar', 'Установка', 'Installer', 'Installieren'), + hermesPhaseConfigure: _('配置', 'Configure', '配置', '設定', '구성', 'Cấu hình', 'Configurar', 'Configurar', 'Настройка', 'Configurer', 'Konfigurieren'), + hermesPhaseGateway: _('启动', 'Start', '啟動', '起動', '시작', 'Khởi động', 'Iniciar', 'Iniciar', 'Запуск', 'Démarrer', 'Starten'), + hermesPhaseComplete: _('完成', 'Complete', '完成', '完了', '완료', 'Hoàn tất', 'Completo', 'Concluído', 'Готово', 'Terminé', 'Fertig'), + // Provider 分组标题 + hermesProviderGroupIntl: _('国际 · API Key', 'International · API Key', '國際 · API Key', '海外 · API Key', '국제 · API Key', 'Quốc tế · API Key', 'Internacional · API Key', 'Internacional · API Key', 'Международные · API Key', 'International · API Key', 'International · API Key'), + hermesProviderGroupCn: _('国内 · API Key', 'Mainland · API Key', '中國大陸 · API Key', '中国大陸 · API Key', '중국 본토 · API Key', 'Trung Quốc · API Key', 'China · API Key', 'China · API Key', 'Китай · API Key', 'Chine continentale · API Key', 'China · API Key'), + hermesProviderGroupAggregator: _('聚合 / 路由', 'Aggregator / Router', '聚合 / 路由', 'アグリゲーター / ルーター', '집계 / 라우터', 'Tổng hợp / Định tuyến', 'Agregador / Enrutador', 'Agregador / Roteador', 'Агрегатор / Маршрутизатор', 'Agrégateur / Routeur', 'Aggregator / Router'), + hermesProviderGroupOAuth: _('OAuth 登录(需终端)', 'OAuth Login (Terminal needed)', 'OAuth 登入(需終端)', 'OAuth ログイン(ターミナルが必要)', 'OAuth 로그인 (터미널 필요)', 'Đăng nhập OAuth (cần Terminal)', 'OAuth Login (requiere Terminal)', 'Login OAuth (requer Terminal)', 'OAuth вход (требуется терминал)', 'Connexion OAuth (Terminal requis)', 'OAuth-Login (Terminal erforderlich)'), + hermesProviderOAuthRunHint: _('需运行', 'run', '需執行', '実行', '실행 필요', 'cần chạy', 'ejecuta', 'execute', 'требуется', 'exécuter', 'ausführen'), + hermesProvidersLoadFallback: _( + '未能加载 provider 列表。Web 模式下可手动填写下方 Base URL 与 API Key 完成配置。', + 'Failed to load provider list. In Web mode you can fill in Base URL and API Key manually below.', + '未能載入 provider 列表。Web 模式下可手動填寫下方 Base URL 與 API Key 完成設定。', + 'プロバイダー一覧の読み込みに失敗しました。Web モードでは下の Base URL と API Key を手動で入力できます。', + 'provider 목록을 불러오지 못했습니다. Web 모드에서 아래 Base URL과 API Key를 수동으로 입력할 수 있습니다.', + 'Không tải được danh sách provider. Ở chế độ Web bạn có thể điền Base URL và API Key bên dưới.', + 'No se pudo cargar la lista de providers. En modo Web puedes rellenar Base URL y API Key abajo.', + 'Não foi possível carregar a lista de providers. No modo Web preencha manualmente Base URL e API Key abaixo.', + 'Не удалось загрузить список провайдеров. В Web-режиме укажите Base URL и API Key ниже вручную.', + 'Impossible de charger la liste des providers. En mode Web, saisissez Base URL et API Key ci-dessous.', + 'Provider-Liste konnte nicht geladen werden. Im Web-Modus Base URL und API Key unten manuell eintragen.' + ), hermesSetupIntro: _( 'Hermes Agent 是一个具有工具调用能力的 AI 助手框架。点击下方按钮一键安装,无需终端操作。', 'Hermes Agent is an AI assistant with tool-calling capabilities. Click the button below to install — no terminal needed.',