Skip to content

国际化支持 ​

本文引用的源码文件

本文引用的文件

目录 ​

  1. 引言
  2. 项目结构与 i18n 定位
  3. 双端 i18n 架构总览
  4. 扩展端:Chrome 消息系统与运行时语言切换
  5. Agent 端:本地化文件与请求级语言解析
  6. 多语言消息管理机制
  7. 运行时语言切换流程
  8. 翻译文件维护指南
  9. 使用示例:JavaScript 与 HTML 模板
  10. i18n 工具函数说明
  11. 依赖关系分析
  12. 性能与可维护性考量
  13. 常见问题与排错
  14. 最佳实践与工作流建议
  15. 结论

引言 ​

本文件面向开发者与维护者,系统性说明 AI Helper 的双端国际化方案。项目采用“扩展端 + Agent 端”双进程架构:扩展端基于 Chrome Manifest V3 Service Worker,使用 _locales 与 shared/i18n.js;Agent 端为 Node.js 服务,使用 agent/src/i18n.js 与 agent/src/locales/*.json。文档重点覆盖:

  • 双端 i18n 架构差异与协作方式
  • 消息键命名、参数插值与回退策略
  • 运行时语言检测、持久化与界面刷新
  • 新增语言、翻译质量保证与同步机制
  • JavaScript 调用与 HTML 模板嵌入方式
  • 工具函数、注意事项与常见故障排查

项目结构与 i18n 定位 ​

仓库中与国际化直接相关的资源分布在以下位置:

  • 扩展端 Chrome 标准消息:_locales/{locale}/messages.json
  • 扩展端运行时 i18n 模块:src/shared/i18n.js
  • 扩展端运行时语言包:src/shared/locales/{en,zh}.js
  • Agent 端 i18n 模块:agent/src/i18n.js
  • Agent 端系统语言检测:agent/src/sys-lang.js
  • Agent 端语言包:agent/src/locales/{en,zh}.json
  • Agent 服务端入口:agent/src/server.js
  • 扩展清单:manifest.json
graph TB
subgraph "扩展端"
M["manifest.json<br/>Chrome 消息占位"]
L1["_locales/en/messages.json"]
L2["_locales/zh_CN/messages.json"]
I18N["src/shared/i18n.js"]
ENJS["src/shared/locales/en.js"]
ZHJS["src/shared/locales/zh.js"]
end
subgraph "Agent 端"
AI18N["agent/src/i18n.js"]
SLANG["agent/src/sys-lang.js"]
AEN["agent/src/locales/en.json"]
AZH["agent/src/locales/zh.json"]
SRV["agent/src/server.js"]
end
M --> L1
M --> L2
I18N --> ENJS
I18N --> ZHJS
AI18N --> AEN
AI18N --> AZH
AI18N --> SLANG
SRV --> AI18N

图表来源

章节来源

双端 i18n 架构总览 ​

本项目存在两套相对独立但语义对齐的国际化体系:

维度扩展端Agent 端
主要用途浏览器侧 UI、命令描述、设置页、内容脚本提示等HTTP/WebSocket API 返回的错误、状态、日志、RAG、Skill、MCP 等后端文案
核心模块src/shared/i18n.jsagent/src/i18n.js
语言包格式JS 对象导出(en.js / zh.js)JSON 文件(en.json / zh.json)
Chrome 标准消息_locales/*/messages.json,由 manifest.json 引用不适用
默认语言zhen,可通过环境变量或系统语言检测
运行时切换通过 setLanguage + chrome.storage.local 跨环境同步按请求 Accept-Language 解析,或由 CLI/env 固定
参数插值{name} 形式{name} 形式
回退策略当前语言 → 英文 → key 本身指定语言 → 默认语言 → key 本身

关键设计要点:

  • 扩展端适合“用户可见界面”,强调运行时动态切换和 DOM 自动填充。
  • Agent 端适合“服务端输出”,强调请求级语言选择、错误信息本地化和日志可读性。
  • 两端都使用点分 key 与 {param} 插值,便于统一理解,但实现细节不同。

章节来源

扩展端:Chrome 消息系统与运行时语言切换 ​

Chrome 标准消息 ​

manifest.json 中声明了扩展名、描述和命令描述,这些字符串通过 __MSG_*__ 占位符引用 _locales 下的 messages.json。例如:

  • name 使用 __MSG_extName__
  • description 使用 __MSG_extDescription__
  • 命令描述使用 __MSG_commandToggleSidepanel__

这意味着 Chrome 商店展示、快捷键提示、扩展名称等由 Chrome 自身根据 default_locale 和用户语言加载对应 messages.json。

运行时 i18n 模块 ​

src/shared/i18n.js 提供扩展端运行时翻译能力:

  • 内置支持语言:zh、en
  • 默认语言:zh
  • 支持点分 key 查找
  • 支持 {name} 参数插值
  • 支持运行时语言切换
  • 支持订阅语言变更并刷新界面
  • 支持从 chrome.storage.local 读取/写入语言偏好
  • 支持 data-i18n* 属性自动填充文本、placeholder、title、aria-label
flowchart TD
Start(["页面或服务 Worker 启动"]) --> InitI18n["调用 initI18n()"]
InitI18n --> CheckStorage{"chrome.storage.local 中有 language?"}
CheckStorage --> |是| UseStored["使用已保存语言"]
CheckStorage --> |否| DetectBrowser["detectBrowserLanguage()"]
DetectBrowser --> PersistAuto["持久化自动检测结果"]
UseStored --> Subscribe["注册 storage.onChanged 监听"]
PersistAuto --> Subscribe
Subscribe --> Ready(["t() 可用"])

图表来源

章节来源

Agent 端:本地化文件与请求级语言解析 ​

Agent 端的 i18n 模块负责:

  • 在进程启动时加载 agent/src/locales/en.json 与 agent/src/locales/zh.json
  • 确定默认语言:CLI 参数或 AI_HELPER_LANG 环境变量优先,否则调用 sys-lang.js 检测系统语言
  • 解析 HTTP 请求的 Accept-Language 头,匹配最合适的语言
  • 提供 t(lang, key, params) 和 getRequestI18n(req)
sequenceDiagram
participant Client as "HTTP 客户端"
participant Server as "agent/src/server.js"
participant I18N as "agent/src/i18n.js"
participant SysLang as "agent/src/sys-lang.js"
participant Locales as "agent/src/locales/*.json"
Client->>Server : HTTP 请求
Server->>I18N : getRequestI18n(req)
I18N->>I18N : parseAcceptLanguage(Accept-Language)
I18N->>SysLang : detectSystemLang()
SysLang-->>I18N : zh 或 en
I18N->>Locales : 加载 zh.json / en.json
I18N-->>Server : { lang, t }
Server->>I18N : t(key, params)
I18N-->>Server : 本地化消息
Server-->>Client : 响应

图表来源

章节来源

多语言消息管理机制 ​

消息键命名规范 ​

  • 扩展端与 Agent 端均使用点分 key,例如 common.confirm、error.fileNotFound、server.httpStarted。
  • 推荐按功能域分组:
    • 通用文案:common.*
    • 对话框与交互:dialog.*、chat.*、input.*
    • 设置页:settings.*、react.*、toolbar.*
    • 工具相关:tool.*、toolCategory.*
    • Agent 错误:error.*、security.*、exec.*
    • Agent 业务:rag.*、memory.*、skill.*、mcp.*、server.*

参数插值 ​

  • 扩展端与 Agent 端均使用 {name} 占位符。
  • 若参数缺失,扩展端会保留原占位符或 key;Agent 端也会保留未提供的参数名。
  • 建议始终传入必要参数,避免显示原始 {name}。

复数形式处理 ​

  • 当前实现未提供复数规则引擎。
  • 对于数量相关文案,建议在 key 层面区分或使用自然语言表达,例如:
    • 使用带数量的文案 key,如 foundResults,并在参数中传入具体数字。
    • 在翻译层用自然语言描述数量,而不是依赖复数规则。

回退策略 ​

  • 扩展端:当前语言 → 英文 → key 本身。
  • Agent 端:指定语言 → 默认语言 → key 本身。

章节来源

运行时语言切换流程 ​

扩展端的语言切换由 setLanguage 驱动,核心流程如下:

flowchart TD
Change(["调用 setLanguage(lang)"]) --> Validate{"lang 是否有效且不同于当前语言?"}
Validate --> |否| Ignore["忽略变更"]
Validate --> |是| UpdateState["更新 currentLang"]
UpdateState --> Persist{"是否允许持久化?"}
Persist --> |是| SaveStorage["写入 chrome.storage.local.language"]
Persist --> |否| SkipPersist["跳过持久化"]
SaveStorage --> Notify["通知所有订阅者"]
SkipPersist --> Notify
Notify --> RefreshUI["UI 组件重新渲染"]

图表来源

关键点:

  • 语言变更后,会通过订阅者回调通知 UI 层。
  • 语言偏好会写入 chrome.storage.local,其他页面(background、side panel、options、content script)可通过 storage.onChanged 同步。
  • applyI18n 用于批量刷新带 data-i18n* 属性的 DOM 元素。

章节来源

翻译文件维护指南 ​

新增语言的步骤 ​

当前仓库仅维护中文与英文。若需新增语言,应同时考虑扩展端与 Agent 端:

  1. 扩展端

    • 在 src/shared/locales/ 下新增语言文件,例如 xx.js。
    • 在 src/shared/i18n.js 中导入新语言包,并加入 SUPPORTED_LANGUAGES。
    • 在 initI18n 的语言字典中注册新语言。
    • 如需 Chrome 标准消息,可在 _locales/xx/ 下新增 messages.json。
  2. Agent 端

    • 在 agent/src/locales/ 下新增 xx.json。
    • 在 agent/src/i18n.js 中加载新语言文件。
    • 确保 parseAcceptLanguage 能识别新语言代码。
  3. 验证

    • 运行构建脚本验证无语法错误。
    • 检查扩展端 UI 是否能切换到新语言。
    • 检查 Agent 端 API 返回文案是否按预期本地化。

翻译质量保证 ​

  • 保持 key 一致:新增 key 必须同时在所有语言文件中出现。
  • 保持参数一致:如果某个 key 使用 {name},所有语言版本都应保留相同占位符。
  • 避免硬编码:不要在业务逻辑中直接写死文案,统一走 t()。
  • 审查长文案:中文、英文长度差异较大,注意 UI 布局与换行。
  • 测试边界情况:空值、null、超长文本、特殊字符。

同步机制 ​

  • 扩展端语言包以 JS 对象为主,适合模块化按需引入。
  • Agent 端语言包以 JSON 为主,适合静态加载与快速解析。
  • 建议在代码审查中检查新增 key 是否遗漏翻译。

章节来源

使用示例:JavaScript 与 HTML 模板 ​

JavaScript 中调用翻译函数 ​

扩展端推荐使用 src/shared/i18n.js 导出的 t:

  • 基本用法:t('common.confirm')
  • 参数插值:t('dialog.remainingTime', { time: '1:30' })
  • 获取当前语言:getLanguage()
  • 设置语言:setLanguage('en')
  • 订阅语言变化:subscribe((lang) => { ... })
  • 初始化语言:await initI18n()
  • 注册额外翻译:registerTranslations(lang, dict)

Agent 端推荐使用 agent/src/i18n.js:

  • 基础用法:t(lang, 'error.fileNotFound', { path: '/foo' })
  • 请求级 i18n:const { lang, t } = getRequestI18n(req)

HTML 模板中嵌入动态文本 ​

扩展端支持通过 data-i18n* 属性配合 applyI18n 自动填充:

  • data-i18n="common.confirm":设置元素文本
  • data-i18n-placeholder="ui.inputPlaceholder":设置 placeholder
  • data-i18n-title="ui.tip":设置 title
  • data-i18n-aria-label="ui.accessibleLabel":设置 aria-label

注意:

  • 动态内容(如版本号、计数、格式化结果)不应只依赖 data-i18n,应在 JS 中调用 t() 后插入。
  • 语言切换后应再次调用 applyI18n 刷新 DOM。

章节来源

i18n 工具函数说明 ​

扩展端工具函数 ​

函数作用返回值备注
t(key, params?)根据当前语言查找翻译并插值string找不到时返回 key
getLanguage()获取当前语言代码string默认 zh
setLanguage(lang, persist?)设置语言并可选持久化void触发订阅者
subscribe(callback)订阅语言变更function返回取消订阅函数
registerTranslations(lang, dict)合并某语言翻译字典void深度合并
initI18n()初始化语言并从存储恢复Promise<string>注册 storage 监听
applyI18n(root?)刷新 DOM 中的 data-i18n* 元素void需要 root 为 DOM 节点

Agent 端工具函数 ​

函数作用返回值备注
parseAcceptLanguage(header?)解析 Accept-Languagestring返回 zh 或 en
t(lang, key, params?)根据指定语言查找翻译并插值string找不到时返回 key
getRequestI18n(req)从请求中提取语言并返回 tobject包含 lang 和 t

格式化、日期处理和数字转换 ​

当前 i18n 模块未内置日期格式化、数字格式化或复数规则引擎。建议:

  • 在业务层使用 Intl.DateTimeFormat、Intl.NumberFormat 进行格式化。
  • 将格式化后的结果作为参数传给 t()。
  • 对需要区域化显示的数值、时间、货币,优先使用浏览器或 Node.js 原生 Intl API。

章节来源

依赖关系分析 ​

扩展端 i18n 依赖:

  • src/shared/locales/en.js
  • src/shared/locales/zh.js
  • Chrome API:chrome.i18n、chrome.storage

Agent 端 i18n 依赖:

  • agent/src/locales/en.json
  • agent/src/locales/zh.json
  • agent/src/sys-lang.js
  • Node.js:fs、path、process.env、Intl
graph LR
SharedI18N["src/shared/i18n.js"] --> EnJS["src/shared/locales/en.js"]
SharedI18N --> ZhJS["src/shared/locales/zh.js"]
AgentI18N["agent/src/i18n.js"] --> EnJSON["agent/src/locales/en.json"]
AgentI18N --> ZhJSON["agent/src/locales/zh.json"]
AgentI18N --> SysLang["agent/src/sys-lang.js"]
Server["agent/src/server.js"] --> AgentI18N

图表来源

章节来源

性能与可维护性考量 ​

  • 扩展端语言包为 JS 模块,编译期可被打包器优化;运行时查表复杂度近似 O(1)。
  • Agent 端语言包为 JSON,进程启动时一次性加载,适合服务端高频调用。
  • applyI18n 会遍历 DOM,频繁调用可能带来性能开销,建议仅在语言切换或页面初始化时调用。
  • registerTranslations 使用深度合并,适合模块分散注册翻译,但应避免重复覆盖。
  • 语言切换通过订阅者模式解耦 UI 刷新,降低耦合度。

[本节为通用性能讨论,不直接分析具体代码片段]

常见问题与排错 ​

问题:语言切换后部分文案未更新 ​

可能原因:

  • 动态生成的 DOM 没有 data-i18n* 属性。
  • 语言切换后未调用 applyI18n。
  • 文案是通过 JS 直接赋值而非 t()。

解决建议:

  • 对静态文案使用 data-i18n*。
  • 对动态文案在 JS 中调用 t()。
  • 语言切换后调用 applyI18n(document)。

章节来源

问题:Agent 端返回英文而非中文 ​

可能原因:

  • 请求未携带正确的 Accept-Language。
  • 环境变量 AI_HELPER_LANG 设置为 en。
  • 系统语言检测结果为 en。

解决建议:

  • 检查请求头 Accept-Language。
  • 检查 AI_HELPER_LANG 环境变量。
  • 检查系统语言环境变量或 Intl.DateTimeFormat().resolvedOptions().locale。

章节来源

问题:Chrome 扩展名或命令描述未本地化 ​

可能原因:

  • _locales 下缺少对应语言的 messages.json。
  • manifest.json 中使用了错误的消息 key。
  • 浏览器语言与 _locales 目录名不匹配。

解决建议:

  • 确保 _locales/en 与 _locales/zh_CN 中存在完整 messages.json。
  • 核对 manifest.json 中的 __MSG_*__ key。
  • 确认 Chrome 语言设置与 _locales 目录匹配。

章节来源

最佳实践与工作流建议 ​

  • 新增功能时先定义 key,再补充中英文翻译。
  • 避免在业务逻辑中硬编码文案。
  • 对含参数的文案,统一使用 {name} 插值。
  • 对 UI 文案优先使用 data-i18n* + applyI18n。
  • 对动态内容使用 t() 后插入 DOM。
  • 对 Agent 端错误信息,使用 getRequestI18n(req) 获取请求级 t。
  • 新增语言时同步扩展端与 Agent 端。
  • 在代码审查中检查 key 是否遗漏翻译。
  • 对长文案进行 UI 适配测试。
  • 对日期、数字、货币使用 Intl API 格式化后再传给 t()。

[本节为通用工作流建议,不直接分析具体代码片段]

结论 ​

AI Helper 的国际化方案围绕“扩展端运行时 i18n”和“Agent 端请求级 i18n”两条主线展开。扩展端侧重用户界面体验,支持运行时语言切换、DOM 自动填充和跨环境同步;Agent 端侧重服务端输出,支持 Accept-Language 解析、系统语言检测和 JSON 语言包。两者均采用点分 key 与 {name} 插值,具备清晰的回退策略。通过本文档的架构说明、使用示例、维护指南和排错建议,开发者可以更系统地扩展、维护和调试项目的国际化能力。

[本节为总结性内容,不直接分析具体代码片段]