news 2026/9/19 22:06:41

Brackets 国际化(i18n)实战指南:核心代码与插件本地化完整解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Brackets 国际化(i18n)实战指南:核心代码与插件本地化完整解析

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文件中,再按需动态加载。

整个机制由三个环节组成:

  1. 字符串仓库(nls 目录):所有语言的字符串以define({...})形式存放在 src/nls 下,root目录存放英文基准串,其余每个语言目录(如frdezh-cn)存放对应翻译。
  2. 字符串入口模块(src/strings.js):代码通过require("strings")加载 src/strings.js,该模块内部借助i18n!nls/strings加载当前 locale 对应的strings.js
  3. 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_NAMEAPP_TITLEVERSIONBUILD_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-cnzh-twpt-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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 22:05:07

Atlas 300V 24G推理加速卡详解:从环境配置到YOLO部署实践

打个比方&#xff0c;你拿一张 Atals 300V 24G 插到服务器上&#xff0c;系统里npu-smi info能看到芯片&#xff0c;但它没有视频输出口&#xff0c;装完驱动之后也不会像显卡那样多出一个桌面分辨率。很多人第一次接触这个卡都会懵&#xff1a;这东西到底算什么&#xff1f;是…

作者头像 李华
网站建设 2026/9/19 22:05:05

PeaZip 11 Linux多架构安装指南:AMD64、ARM64与龙芯LoongArch64实战

1. 项目背景与架构选择思路1.1 为什么PeaZip值得在三类架构上折腾一次PeaZip是一款免费开源的图形化压缩解压工具&#xff0c;我对它的定位是“日常文件管理的瑞士军刀”。和系统自带的Archive Manager&#xff08;File Roller&#xff09;相比&#xff0c;PeaZip最大的优势在于…

作者头像 李华
网站建设 2026/9/19 22:04:37

用IT思维拆解公路施工组织设计:从进度到质量的工程闭环

简介&#xff1a;一份面向山岭重丘二级公路施工管理人员与技术人员的二零二一年施工组织设计范本&#xff0c;内容以某二级公路第二标段一点七五公里路段为背景&#xff0c;涵盖工程概况、设计标准、主要工程数量、自然条件及施工组织方案&#xff0c;适合用于编制同类投标文件…

作者头像 李华