Brackets 国际化(i18n)实战指南:核心代码与插件本地化完整解析
【免费下载链接】bracketsAn open source code editor for the web, written in JavaScript, HTML and CSS.项目地址: https://gitcode.com/gh_mirrors/br/brackets
Brackets 是一款用 JavaScript、HTML 与 CSS 编写的开源 Web 代码编辑器,其对用户可见文本的多语言支持(Localization / i18n)以nls目录 + RequireJSi18n插件为核心。本文基于 LocalizationExample 示例插件文档 展开,结合 src/strings.js、src/nls/strings.js 等核心实现,系统讲解如何在 Brackets 核心代码与第三方插件中正确添加、加载和渲染本地化字符串。读完本文,你将掌握:如何为 Brackets 核心新增语言翻译、如何在 JS 与 HTML 中消费本地化字符串、如何编写一个完整支持多语言的插件,以及插件字符串与核心字符串加载方式的区别。
一、Brackets 本地化机制总览
Brackets 为用户可见文本提供了基础的多语言支持(详见 LocalizationExample/README.md)。其设计核心约束是:任何向用户显示文本的 JavaScript 和 HTML 代码,都不应把英文静态字符串直接写在代码里,而应把字符串集中存放在nls目录下的strings.js文件中,再按需动态加载。
整个机制由三个环节组成:
- 字符串仓库(nls 目录):所有语言的字符串以
define({...})形式存放在 src/nls 下,root目录存放英文基准串,其余每个语言目录(如fr、de、zh-cn)存放对应翻译。 - 字符串入口模块(src/strings.js):代码通过
require("strings")加载 src/strings.js,该模块内部借助i18n!nls/strings加载当前 locale 对应的strings.js。 - i18n 加载插件:Brackets 使用 RequireJS 的 i18n 插件(
i18n!前缀)按用户 locale 动态加载字符串文件,并在缺失翻译时自动回退到英文,保证任何语言环境下界面都不会出现空串。
核心模块 src/strings.js 的实现清晰地体现了这一点:
var strings = require("i18n!nls/strings"), urls = require("i18n!nls/urls"), stringsApp = require("i18n!nls/strings-app"), ... module.exports = strings;该模块还做了两件额外的事:把APP_NAME、APP_TITLE、VERSION、BUILD_TYPE等应用级元数据作为额外全局值,用正则{名称}替换的方式注入到所有字符串模板中;并通过stringsApp叠加产品特定字符串,最终将合并结果导出为Strings模块。这意味着strings.js中的字符串还支持占位符替换(如{APP_NAME}),为模板化文案提供了底层能力。
二、locale 的注册与解析:nls/strings.js 配置
无论是核心还是插件,都通过nls目录下的strings.js来声明支持的 locale 列表。以核心为例,src/nls/strings.js 内容如下:
module.exports = { root: true, "bg": true, "cs": true, "da": true, "de": true, "el": true, "en-gb": true, "es": true, "fa-ir": true, "fi": true, "fr": true, "gl": true, "hr": true, "hu": true, "id": true, "it": true, "ja": true, "ko": true, "lv": true, "nb": true, "nl": true, "pl": true, "pt-br": true, "pt-pt": true, "ro": true, "ru": true, "sk": true, "sr": true, "sv": true, "tr": true, "uk": true, "zh-cn": true, "zh-tw": true };几点关键说明:
root: true是必填项,表示以root目录为英文基准;root目录中缺少的翻译会自动回退到英文。- 每个键即一个 locale 标识,命名遵循「语言-国家/地区」惯例(如
zh-cn、zh-tw、pt-br)。locale 目录结构形如nls/<locale>/strings.js。 - 新增一种语言时,需要同时做三件事:在
nls/strings.js中登记 locale 键、新建nls/<locale>/strings.js翻译文件、在root/strings.js中补充英文基准串。 - 目前核心支持 30+ 种语言/区域变体,完整的翻译文件位于 src/nls 各语言目录中,实际存在的内容可对照 src/nls 目录逐一查看。
三、为 Brackets 核心新增本地化字符串
3.1 英文基准串:写入 root/strings.js
新增英文字符串时,把键值对添加到 src/nls/root/strings.js。该文件是 Brackets 全部用户可见文本的英文主档,例如其中定义:
"NOT_FOUND_ERR" : "The file/directory could not be found.",3.2 其他语言翻译:写入对应 locale 目录
其他语言的翻译应添加到nls目录下各 locale 文件夹内的strings.js。例如法语翻译应修改 src/nls/fr/strings.js。翻译文件与 root 文件采用相同的键名结构,仅替换值为对应语言的文本。
建议:为某个语言补充翻译时,与 src/nls/root/strings.js 保持键名一一对应;未翻译的键会由 i18n 插件自动回退到英文,因此部分翻译不会导致崩溃,但完整的键覆盖才能提供最佳体验。
四、在 Brackets 模块中使用本地化字符串
4.1 JavaScript 中使用字符串
在需要显示字符串的文件中加载Strings模块,然后通过属性访问:
Strings = require("strings");随后即可按属性名引用字符串,例如Strings.NOT_FOUND_ERR在英文 locale 下返回 “The file/directory could not be found.”(该键定义于 src/nls/root/strings.js)。Strings模块会根据当前 locale 自动返回对应翻译,无需在业务代码中做任何语言判断。
4.2 HTML 中使用字符串(Mustache 模板)
HTML 无法直接引用strings.js中的属性,因此 Brackets 引入 Mustache.js 模板引擎来完成替换。JS 与 HTML 共用的字符串都存放在src/nls/root/strings.js,但 HTML 中通过模板语法{{stringKeyName}}引用。例如:
<h1 class="dialog-title">{{SAVE_CHANGES}}</h1>渲染后得到:
<h1 class="dialog-title">Save Changes</h1>其底层流程是:Mustache 在 Brackets 启动、模块加载时运行——src/brackets.js 中的代码使用 i18n 加载对应的strings.js,以 text 方式加载 HTML 文件内容,以strings.js为数据源对文本执行Mustache.render,最后将结果插入 DOM。实际证据可见 src/brackets.js:
$("body").html(Mustache.render(MainViewHTML, { shouldAddAA: (brackets.platform === "mac"), Strings: Strings }));此外,src/brackets.js 还通过Object.defineProperty(window, "Mustache", ...)把 Mustache 暴露为全局对象(并附带弃用警告),建议插件改用brackets.getModule("thirdparty/mustache/mustache")获取。
依赖 DOM 的核心代码在检查或操作 DOM 之前,应监听"htmlContentLoadComplete"事件,确保 Mustache 渲染完成。
五、本地化准则与已知限制
- 禁止拼接多个字符串键:
strings.js中的多个字符串键不应被拼接组合使用,因为不同语言的词序差异很大(例如形容词与名词的位置、主谓宾顺序),硬拼接会导致翻译错乱。应尽量让每个键承载完整、自洽的句子。 - 键盘快捷键暂不支持本地化:目前 Brackets 尚未支持针对键盘快捷键(keyboard shortcuts)的本地化,快捷键相关显示不在 i18n 覆盖范围内。
六、插件本地化实战:LocalizationExample 全解析
插件本地化的机制与核心模块几乎一致:同样使用 RequireJS 的 i18n 插件按 locale 动态加载strings.js,JavaScript 通过属性名引用字符串,HTML 片段则借助 Mustache 插入本地化文本。完整示例见 src/extensions/samples/LocalizationExample。
6.1 运行示例插件
示例插件默认位于samples目录(不会被自动加载),将其移动到用户插件目录extensions/user/即可运行。加载后,它会在Edit 菜单末尾新增一个 “My New Command” 菜单项;点击该命令会先弹出一个包含本地化文本的 alert,随后展示一个包含本地化 HTML 内容的模态对话框。
6.2 目录结构与各文件职责
示例插件的目录结构如下(与 README 描述一致):
LocalizationExample/ ├── main.js # 加载插件 Strings 模块并用 Mustache 本地化 HTML ├── package.json # 声明支持的语言与本地化元数据 ├── strings.js # 用 i18n 加载 nls 目录中的 strings.js ├── htmlContent/ │ └── sampleHTMLFragment.html # 待 Mustache 本地化的 HTML 模板 └── nls/ ├── strings.js # 配置 i18n:指定 root 目录并列出插件支持的 locale ├── root/ │ └── strings.js # 英文(root)字符串 └── fr/ └── strings.js # 法语字符串各文件具体职责如下:
main.js—— main.js 是插件的核心逻辑:
var CommandManager = brackets.getModule("command/CommandManager"), Menus = brackets.getModule("command/Menus"), Dialogs = brackets.getModule("widgets/Dialogs"), Mustache = brackets.getModule("thirdparty/mustache/mustache"); var browserWrapperHtml = require("text!htmlContent/sampleHTMLFragment.html"); var Strings = require("strings"); function testCommand() { window.alert(Strings.ALERT_MESSAGE); var localizedTemplate = Mustache.render(browserWrapperHtml, Strings); Dialogs.showModalDialogUsingTemplate(localizedTemplate); } var myCommandID = "localizationExample.command"; CommandManager.register(Strings.COMMAND_NAME, myCommandID, testCommand); var menu = Menus.getMenu(Menus.AppMenuBar.EDIT_MENU); menu.addMenuItem(myCommandID, null, Menus.AFTER, myCommandID);要点:
require("strings")加载本插件的字符串模块(指向插件目录下的 strings.js);核心字符串则用brackets.getModule("strings")。- 命令名通过
Strings.COMMAND_NAME本地化,因此菜单项文本随 locale 变化。 Mustache.render(html, Strings)以字符串模块为数据源渲染模板,再交给Dialogs.showModalDialogUsingTemplate展示。
package.json—— package.json 声明语言支持与本地化元数据:
{ "name": "localization-example", "title": "Localization Example", "description": "A guide on how to localize your extension.", "version": "1.0.0", "author": "The Brackets team", "license": "MIT", "engines": { "brackets": ">=0.42.0" }, "i18n": ["en", "fr"], "package-i18n": { "fr": { "title": "Localisation Exemple", "description": "Un guide sur la façon de localiser votre poste." } } }"i18n": ["en", "fr"]:声明插件支持的语言列表。"package-i18n":提供各语言下的本地化元数据(如 Extension Manager 中显示的标题与描述),键为 locale,值为覆盖字段。
strings.js—— strings.js 是插件字符串入口,一行即完成动态加载:
module.exports = require("i18n!nls/strings");nls/strings.js—— nls/strings.js 配置 i18n:指定 root 目录并列出插件支持的 locale:
module.exports = { root: true, "fr": true };nls/root/strings.js—— 英文基准串(查看完整文件):
define({ "COMMAND_NAME" : "My New Command", "ALERT_MESSAGE" : "This is a sample alert message", "DIALOG_TITLE" : "Localized Dialog Example", "DIALOG_TEXT" : "This is an example of localized text in Brackets", "DIALOG_OK" : "OK" });nls/fr/strings.js—— 法语翻译(查看完整文件),键名与 root 一致,仅值不同,如"COMMAND_NAME": "Ma nouvelle commande"。
htmlContent/sampleHTMLFragment.html—— Mustache 模板(查看完整文件):
<div class="sample-localized-dialog modal"> <div class="modal-header"> <h1 class="dialog-title">{{DIALOG_TITLE}}</h1> </div> <div class="modal-body"> {{DIALOG_TEXT}} </div> <div class="modal-footer"> <a href="#" class="dialog-button btn primary" contenteditable="false">【免费下载链接】bracketsAn open source code editor for the web, written in JavaScript, HTML and CSS.
项目地址: https://gitcode.com/gh_mirrors/br/brackets创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考