Skip to main content
国际化(通常简写为 i18n)通过两部分实现:一个存放你翻译内容的 _locales 文件夹,以及在运行时读取它们的 chrome.i18n API。 Extension.js 会读取项目根目录下的 _locales 文件夹,并校验每个声明的 locale 都有一份 messages.json。它会把 locale JSON 资源输出到针对每个浏览器的构建产物中。在开发期,它会捕获任意 locale 文件的编辑,而无需完全重启。

模板示例

action-locales

action-locales template screenshot 通过 _locales 支持来查看本地化的扩展元数据与 UI 字符串。
仓库:extension-js/examples/action-locales

Locale 能力

期望的目录结构

manifest.json 中的 default_locale 应当映射到一个存在的 _locales/<default>/messages.json

传统布局:_locales 放在 manifest 旁边

即使你的 manifest 位于 src/ 之类的子文件夹中,项目根目录仍然是 _locales 的规范位置。放在嵌套 manifest 旁边的 _locales 文件夹依然能构建。编译器会输出一条 LocalesLayoutWarning,要求你把它移到根目录。浏览器从扩展根目录读取 locale,所以放在根目录与最终发布的产物一致。

manifest.json 中的 locales 声明示例

下面演示了如何在 manifest.json 中声明 locales:
然后你需要在 _locales 文件夹中为每个 locale 包含 JSON 文件:

messages.json 文件示例

用于翻译的 messages.json 文件示例:

在运行时用 chrome.i18n 读取字符串

__MSG_*__ 占位符是 manifest 的能力。浏览器只会在 manifest.json 里,以及 manifest 声明的 CSS 文件里展开它们。其他地方都不会。 你自己代码中的每个字符串,都要调用这个 API:
替换内容来自第二个参数:
_locales/en/messages.json
还有两个调用很有用:
  • chrome.i18n.getUILanguage() 返回浏览器的语言。
  • chrome.i18n.getAcceptLanguages() 返回用户接受的语言列表。

Extension.js 不会替你替换占位符

Extension.js 会读取 __MSG_*__ 引用,但从不改写它们。
  • manifest.json 中,它会把每个引用与默认 locale 比对,并报告缺失的那些。
  • 在打包时,它会解析 __MSG_*__ 名称,让 zip 文件名带上翻译后的名字。
  • 在 HTML、JavaScript 和 JSON 文件中,它不会改动文本。
所以你写进 HTML 文件的占位符,会作为字面文本发布。请改为在脚本里设置这个字符串:
pages/popup.html
同样的限制也适用于内容脚本以 <style> 文本形式插入的 CSS。__MSG_@@extension_id__ 在那里不会展开。Extension.js 已经会把那段 CSS 里的 url() 引用改写到扩展根目录,所以你并不需要这个占位符。

browser.i18n 写法

Firefox 和 Safari 原生提供 browser.i18n。在 Chromium 上,Extension.js 通过 webextension-polyfill 提供 browser 命名空间,所以 browser.i18n.getMessage 在每个目标上都能用。细节请阅读跨浏览器兼容性

输出路径

Extension.js 会把 locale JSON 文件输出到:

开发期行为

  • Extension.js 会把 locale JSON 文件加入编译依赖并监视它们。
  • Locale 变更会触发扩展的重载行为(硬重载),而不是组件式的热模块替换(HMR)。
  • 当必需的 locale 文件缺失或无效时,Extension.js 会以可操作的诊断信息让校验失败。

校验行为

Extension.js 会校验:
  • 存在 _locales 文件夹但 manifest 中没有 default_locale 会让构建失败,因为浏览器会拒绝这种组合
  • _locales/<default> 及其 messages.json 是否存在
  • 每个 locale 的 messages.json 的 JSON 合法性
  • manifest 中的 __MSG_*__ 引用是否与默认 locale 的键匹配
__MSG_*__ 扫描有两个细节:
  • 预定义的 @@ 消息,例如 __MSG_@@ui_locale__,是豁免的,因为它们由浏览器提供。
  • 消息键内部允许出现 @ 字符,这与 Chrome 对消息名的语法一致。

排查缺失的 locale 键

如果 manifest 使用了 __MSG_extension_description__,请确保默认 locale 文件包含 extension_description
如果默认 locale 没有定义该键,Extension.js 会输出一条说明此不一致的诊断信息。

打包行为

当你使用 --zip--zip-source 构建时,Extension.js 会在打包时再次检查默认 locale。声明了 default_locale 却没有对应 messages.json 的 manifest 会产生一条警告,因为应用商店会拒绝缺少默认 locale 的包。 zip 文件名来自 manifest 中的 name。__MSG_*__ 形式的 name 会依据默认 locale 的 messages.json 解析,因此归档文件带的是翻译后的名字,而不是占位符。

最佳实践

  • 保持 messages.json 的键在各 locale 之间一致。
  • 先更新默认 locale,然后再把键扩散到其他 locale。
  • 在持续集成(CI)中校验 locale JSON,在打包前发现损坏的文件。
  • _locales 放在项目根目录,这也是浏览器和打包步骤读取的位置。

下一步

视频讲解