主题
国际化系统
本文引用的源码文件
本文引用的文件
目录
引言
本文件系统性说明该项目的双端国际化体系:扩展端基于 Chrome Extension Messages API,Agent 端使用自定义 Node.js 翻译框架。文档覆盖消息文件组织结构、语言代码约定、键名规范、嵌套对象结构、运行时语言切换、缓存与动态更新、复数与 ICU 支持现状、翻译工作流、Intl API 使用建议、最佳实践以及多语言测试策略。
项目结构
本项目在两个独立进程中实现国际化:
- 扩展端(Manifest V3):通过 _locales 目录提供 chrome.i18n 消息;运行时由 src/shared/i18n.js 管理 UI 文案、语言检测、持久化与 DOM 自动填充。
- Agent 端(Node.js):通过 agent/src/i18n.js 解析 HTTP Accept-Language,加载 agent/src/locales/*.json 文案,并提供 t(lang, key, params) 能力。
graph TB subgraph "扩展端" M["manifest.json<br/>声明 _locales"] L_en["_locales/en/messages.json"] L_zh["_locales/zh_CN/messages.json"] I18N["src/shared/i18n.js<br/>t / setLanguage / initI18n / applyI18n"] EN_js["src/shared/locales/en.js"] ZH_js["src/shared/locales/zh.js"] end subgraph "Agent 端" A_i18n["agent/src/i18n.js<br/>parseAcceptLanguage / t"] A_sys["agent/src/sys-lang.js<br/>detectSystemLang"] A_srv["agent/src/server.js<br/>HTTP 路由 + i18n 注入"] A_cli["agent/src/locales/cli.json"] A_en["agent/src/locales/en.json"] A_zh["agent/src/locales/zh.json"] end M --> L_en M --> L_zh I18N --> EN_js I18N --> ZH_js A_i18n --> A_sys A_i18n --> A_en A_i18n --> A_zh A_srv --> A_i18n A_srv --> A_cli
图示来源
- manifest.json
- _locales/en/messages.json#L1-L12
- _locales/zh_CN/messages.json#L1-L12
- src/shared/i18n.js#L1-L251
- src/shared/locales/en.js#L1-L800
- src/shared/locales/zh.js#L1-L800
- agent/src/i18n.js#L1-L100
- agent/src/sys-lang.js#L1-L30
- agent/src/server.js#L1-L60
- agent/src/locales/cli.json#L1-L187
- agent/src/locales/en.json#L1-L368
- agent/src/locales/zh.json#L1-L368
章节来源
- manifest.json
- _locales/en/messages.json#L1-L12
- _locales/zh_CN/messages.json#L1-L12
- src/shared/i18n.js#L1-L251
- agent/src/i18n.js#L1-L100
- agent/src/server.js#L1-L60
核心组件
- 扩展端运行时 i18n:提供 t(key, params)、setLanguage(lang, persist)、initI18n()、applyI18n(root)、registerTranslations(lang, dict)、subscribe(callback)。
- Agent 端运行时 i18n:提供 parseAcceptLanguage(header)、t(lang, key, params)、getRequestI18n(req),默认语言来自环境变量或系统语言检测。
- 文案资源:
- 扩展端:_locales/* 用于 Chrome 消息;src/shared/locales/{en,zh}.js 为 UI 模块文案。
- Agent 端:agent/src/locales/{en,zh}.json 为服务与工具文案;agent/src/locales/cli.json 为 CLI 文案。
章节来源
- src/shared/i18n.js#L1-L251
- agent/src/i18n.js#L1-L100
- agent/src/sys-lang.js#L1-L30
- agent/src/server.js#L1-L60
架构总览
扩展端与 Agent 端的 i18n 是两条独立链路:
- 扩展端:Chrome 扩展消息 + 运行时 JS 字典。语言偏好存储在 chrome.storage.local,跨 background/side_panel/options/content 同步。
- Agent 端:HTTP 请求携带 Accept-Language,服务端解析并返回对应语言文案;CLI 输出也走同一套文案。
sequenceDiagram
participant Ext as "扩展端页面"
participant SW as "Service Worker/Background"
participant Storage as "chrome.storage.local"
participant SharedI18n as "shared/i18n.js"
participant Agent as "Agent 服务器"
participant AgentI18n as "agent/src/i18n.js"
Ext->>SharedI18n : initI18n()
SharedI18n->>Storage : get('language')
Storage-->>SharedI18n : 用户偏好或空
SharedI18n->>SharedI18n : detectBrowserLanguage()
SharedI18n->>Storage : set({ language })
Note over SharedI18n : 订阅 storage.onChanged 实现跨环境同步
Ext->>Agent : HTTP/WebSocket 请求
Agent->>AgentI18n : getRequestI18n(req)
AgentI18n->>AgentI18n : parseAcceptLanguage(accept-language)
AgentI18n-->>Agent : { lang, t }
Agent-->>Ext : 响应中包含本地化文案
图示来源
详细组件分析
扩展端运行时 i18n(src/shared/i18n.js)
- 语言检测:优先读取 chrome.storage.local.language;未设置则根据 chrome.i18n.getUILanguage() 推断 zh/en。
- 字典合并:支持 registerTranslations(lang, dict) 按模块追加文案,内部 deepMerge。
- 插值:{name} 占位符替换,缺失参数保留原占位符。
- 回退:当前语言 → 英文 fallback → 返回 key 本身,便于发现遗漏。
- 持久化与同步:setLanguage 写入 chrome.storage.local;storage.onChanged 触发订阅者刷新。
- DOM 批量填充:applyI18n 扫描 data-i18n、data-i18n-placeholder、data-i18n-title、data-i18n-aria-label。
flowchart TD
Start(["调用 t(key, params)"]) --> Lookup["在当前语言字典中查找 key"]
Lookup --> Found{"找到?"}
Found --> |是| Interp["执行 {name} 插值"]
Found --> |否| FallbackEn{"当前语言不是 en ?"}
FallbackEn --> |是| LookupEn["在英文字典中查找 key"]
FallbackEn --> |否| ReturnKey["返回 key 本身"]
LookupEn --> EnFound{"找到?"}
EnFound --> |是| Interp
EnFound --> |否| ReturnKey
Interp --> End(["返回结果"])
ReturnKey --> End
图示来源
章节来源
- src/shared/i18n.js#L17-L24
- src/shared/i18n.js#L31-L38
- src/shared/i18n.js#L86-L96
- src/shared/i18n.js#L111-L125
- src/shared/i18n.js#L142-L157
- src/shared/i18n.js#L168-L207
- src/shared/i18n.js#L214-L238
Agent 端运行时 i18n(agent/src/i18n.js)
- 默认语言优先级:AI_HELPER_LANG 环境变量 > --lang CLI 选项 > 系统语言检测(detectSystemLang)。
- Accept-Language 解析:支持 zh/zh-CN/en-US 等,按权重排序后精确匹配或前缀匹配。
- 翻译函数:t(lang, key, params) 支持点分 key 与 {name} 插值;找不到时回退到默认语言,再找不到返回 key。
- 请求级封装:getRequestI18n(req) 返回 { lang, t },供路由层注入。
classDiagram
class AgentI18n {
+parseAcceptLanguage(header) string
+t(lang, key, params) string
+getRequestI18n(req) object
}
class SysLang {
+detectSystemLang() 'zh'|'en'
}
AgentI18n --> SysLang : "默认语言检测"
图示来源
- agent/src/i18n.js#L18-L24
- agent/src/i18n.js#L32-L56
- agent/src/i18n.js#L65-L86
- agent/src/i18n.js#L93-L99
- agent/src/sys-lang.js#L14-L29
章节来源
文案资源与模块划分
- 扩展端 Chrome 消息:_locales/en/messages.json、_locales/zh_CN/messages.json,用于扩展名称、描述、命令等。
- 扩展端 UI 文案:src/shared/locales/en.js、src/shared/locales/zh.js,按模块分组(common、dialog、settings、header、chat、toolPanel 等),key 采用点分访问。
- Agent 端服务文案:agent/src/locales/en.json、agent/src/locales/zh.json,涵盖 error、rag、message、auth、exec、security、trash、search、skill、mcp、server、memory 等。
- Agent 端 CLI 文案:agent/src/locales/cli.json,包含命令帮助、启动选项、状态信息等。
章节来源
- _locales/en/messages.json#L1-L12
- _locales/zh_CN/messages.json#L1-L12
- src/shared/locales/en.js#L1-L800
- src/shared/locales/zh.js#L1-L800
- agent/src/locales/en.json#L1-L368
- agent/src/locales/zh.json#L1-L368
- agent/src/locales/cli.json#L1-L187
依赖关系分析
- 扩展端 shared/i18n.js 依赖:
- 浏览器 API:chrome.i18n、chrome.storage。
- 文案模块:src/shared/locales/{en,zh}.js。
- Agent 端 server.js 依赖:
- agent/src/i18n.js 提供 t、parseAcceptLanguage、getRequestI18n。
- 各子系统通过 setXxxLang 注入语言上下文(如 security、executor、skill、mcp、rag 等),统一消费 t。
graph LR SharedI18n["shared/i18n.js"] --> EN_js["locales/en.js"] SharedI18n --> ZH_js["locales/zh.js"] Server["agent/src/server.js"] --> AI18n["agent/src/i18n.js"] AI18n --> A_en["locales/en.json"] AI18n --> A_zh["locales/zh.json"]
图示来源
章节来源
性能与运行时特性
- 扩展端:
- 语言检测与存储读写仅在初始化阶段执行一次;后续 t() 为内存查表,O(1)。
- applyI18n 使用 querySelectorAll 批量填充,适合页面加载或语言切换后一次性调用。
- subscribe 回调需避免重渲染风暴,建议在 React/Vue 中仅触发必要局部更新。
- Agent 端:
- 文案 JSON 在进程启动时一次性加载至内存;t() 为字符串 reduce 路径查找,开销极低。
- Accept-Language 解析仅在请求入口执行一次,避免重复计算。
[本节为通用性能建议,不直接分析具体文件]
文案组织与命名规范
- 语言代码约定:
- 扩展端:SUPPORTED_LANGUAGES 定义 zh、en;UI 语言检测将 zh-CN 等归一化为 zh。
- Agent 端:支持 zh、en;Accept-Language 支持 zh-CN、en-US 等前缀匹配。
- 键名命名规范:
- 采用“模块.子模块.键”的点分形式,例如 common.confirm、dialog.remainingTime、error.fileNotFound。
- 模块划分遵循功能域:common、dialog、settings、header、chat、toolPanel、toolStats、tokenStatsPanel、customConfirm、promptDialog、promptManager、clarify、prototype、shortcuts、versionInfo、imageEditor、chatExport、agentEditor、auditLog、input、model、sectionSelect、provider、promptSelector、memory、toggle、selection、toolCategory、presetMode、tool、react、reflection、toolbar 等。
- 嵌套对象结构:
- 扩展端与 Agent 端均采用嵌套对象,t() 通过 split('.') 逐级查找。
- 不支持数组索引访问,复杂列表应拆分为多个键或使用模板拼接。
章节来源
- src/shared/i18n.js#L18-L21
- src/shared/i18n.js#L55-L64
- agent/src/i18n.js#L32-L56
- agent/src/i18n.js#L65-L86
复数与本地化格式
- 复数与 ICU 消息:
- 当前扩展端与 Agent 端均未实现 ICU MessageFormat 或复数规则引擎;t() 仅支持 {name} 简单插值。
- 若需复数,应在业务层根据数量选择不同键,例如 items.one、items.many,或在模板中拼接单位。
- Intl API 使用建议:
- 数字、日期、货币格式化建议使用 Intl.NumberFormat、Intl.DateTimeFormat、Intl.RelativeTimeFormat、Intl.PluralRules 等。
- 注意:这些 API 属于运行时本地化,不应替代文案键;它们用于数据展示而非用户可见文案。
[本节为通用指导,不直接分析具体文件]
翻译工作流程
- 文案提取:
- 扩展端:从源码中收集 t('...') 调用与 data-i18n* 属性,生成待翻译键清单。
- Agent 端:从源码中收集 t(lang, '...') 调用与服务日志中的 key,生成清单。
- 缺失键检测:
- 运行期当 t() 找不到 key 时返回原始 key,可在开发模式高亮显示或上报埋点。
- 建议在构建阶段对比 en.js/en.json 与 zh.js/zh.json,报告缺失键。
- 自动同步机制:
- 可扩展脚本在新增 key 时自动在目标语言文件中插入占位值(以英文为基准)。
- 对 _locales/messages.json 的变更可通过 Chrome 扩展消息校验器检查一致性。
[本节为流程建议,不直接分析具体文件]
最佳实践
- 文案上下文管理:
- 使用模块前缀区分上下文,避免键冲突;长文案放入 settings、react、reflection 等模块。
- 敏感操作提示统一放在 dialog、sensitiveTool 等模块,保持语义一致。
- 性能优化:
- 避免在高频渲染路径中调用 t() 进行复杂拼接;预计算模板或拆分键。
- applyI18n 只在页面加载或语言切换后调用,不要每帧执行。
- 错误处理:
- t() 找不到 key 返回原始 key,便于发现遗漏;生产环境可记录日志但不暴露给用户。
- Agent 端 t() 找不到 key 同样返回 key,确保接口稳定。
章节来源
多语言测试策略
- 断言验证:
- 单元测试覆盖 t() 插值、fallback、setLanguage 与 subscribe 行为。
- Agent 端测试覆盖 parseAcceptLanguage 的各种 Accept-Language 组合。
- 视觉回归测试:
- 使用 Playwright 截图对比不同语言下的 UI 布局与文案长度是否溢出。
- 针对 data-i18n* 元素,断言其文本或属性不为原始 key。
- 端到端场景:
- 模拟语言切换,验证 storage.onChanged 触发后的界面刷新。
- 模拟 Agent 端语言变化,验证 HTTP 响应中文案语言正确。
[本节为测试建议,不直接分析具体文件]
故障排查
- 语言未生效:
- 检查 initI18n() 是否在各环境启动时调用。
- 确认 chrome.storage.local.language 是否被其他逻辑覆盖。
- 文案缺失:
- 观察控制台或埋点中出现的原始 key;补充对应语言包。
- 检查 key 拼写与点分路径是否正确。
- Agent 端语言异常:
- 检查 AI_HELPER_LANG 环境变量或 --lang 参数。
- 检查 Accept-Language 头是否被代理或网关改写。
章节来源
结论
该项目的国际化体系以“扩展端 Chrome 消息 + 运行时 JS 字典”和“Agent 端 HTTP 语言感知 + JSON 文案”两条链路构成。扩展端强调 UI 体验与跨环境同步,Agent 端强调请求级语言解析与模块化文案。当前版本未内置 ICU 复数引擎,但提供了稳定的 {name} 插值与回退机制。通过规范的键命名、模块化的文案组织、完善的测试与最佳实践,可保障多语言质量与可维护性。