Skip to content

国际化系统 ​

本文引用的源码文件

本文引用的文件

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与运行时特性
  8. 文案组织与命名规范
  9. 复数与本地化格式
  10. 翻译工作流程
  11. 最佳实践
  12. 多语言测试策略
  13. 故障排查
  14. 结论

引言 ​

本文件系统性说明该项目的双端国际化体系:扩展端基于 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

图示来源

章节来源

核心组件 ​

  • 扩展端运行时 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 文案。

章节来源

架构总览 ​

扩展端与 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

图示来源

章节来源

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 : "默认语言检测"

图示来源

章节来源

文案资源与模块划分 ​

  • 扩展端 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,包含命令帮助、启动选项、状态信息等。

章节来源

依赖关系分析 ​

  • 扩展端 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('.') 逐级查找。
    • 不支持数组索引访问,复杂列表应拆分为多个键或使用模板拼接。

章节来源

复数与本地化格式 ​

  • 复数与 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} 插值与回退机制。通过规范的键命名、模块化的文案组织、完善的测试与最佳实践,可保障多语言质量与可维护性。