news 2026/9/20 23:44:39

Ace 编辑器国际化实战指南:翻译文件生成、nls 消息提取与运行时查找机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ace 编辑器国际化实战指南:翻译文件生成、nls 消息提取与运行时查找机制

Ace 编辑器国际化实战指南:翻译文件生成、nls 消息提取与运行时查找机制

【免费下载链接】aceAce (Ajax.org Cloud9 Editor)项目地址: https://gitcode.com/gh_mirrors/ac/ace

本文基于 Ace(Ajax.org Cloud9 Editor)仓库的 translations/Readme.md 展开,系统讲解如何为 Ace 编辑器添加全新的语言翻译文件(.json)、如何通过构建脚本Makefile.dryice.js nls自动提取源码中的待翻译消息,并深入解析 Ace 运行时(src/lib/app_config.js)的nls()翻译查找与占位符替换机制。读完本文,你将掌握从“创建语言文件”到“消息被界面消费”的完整国际化工作流,并能够为 Ace 自行新增一种语言支持。

一、生成新翻译文件的标准流程

Ace 的界面文本(如自动补全弹窗提示、搜索框按钮标题、无障碍 ARIA 标签等)默认以英文硬编码在源码中,通过nls()调用包裹。若要提供本地化界面,需要按以下三步生成并填充翻译文件(原文出处:translations/Readme.md):

第 1 步:创建语言文件

在仓库的translations/目录下新建一个 JSON 文件,文件名为目标语言的 ID,例如中文可用zh.json、法语可用fr.json

translations/<language_id>.json

语言 ID 的命名完全由你决定,只要不与现有文件冲突即可。当前仓库已存在的语言文件包括am.json(阿姆哈拉语)、es.json(西班牙语)、ru.json(俄语)、sl.json(斯洛文尼亚语),新增文件时同样放在该目录下。

第 2 步:写入$id字段

在空的 JSON 文件中写入语言 ID 标识:

{ "$id": "<language_id>" }

例如为俄语文件写入的就是{"$id": "ru"}(见 translations/ru.json)。这个$id字段至关重要:运行时定位到某份翻译消息表后,会读取其$id用于调试告警信息(详见下文“运行时查找机制”)。

第 3 步:运行 nls 提取命令

在仓库根目录执行:

node Makefile.dryice.js nls

该命令会自动扫描src/下的源码,提取所有nls("key", "defaultString")调用,完成两件事:

  1. 同步默认英文消息表:把源码中新出现的、尚未登记的消息写入 src/lib/default_english_messages.js;
  2. 补齐所有翻译文件:把默认消息表中每个 key 都合并进translations/下每个.json翻译文件,缺失的翻译统一填充为空字符串"",供翻译者逐条填写。

命令执行后,控制台会输出Saved <文件名>之类的提示,对应实现见 Makefile.dryice.js 的extractNls()函数。

二、extractNls() 到底做了什么:源码级拆解

node Makefile.dryice.js nls入口在 Makefile.dryice.js,命中type == "nls"后调用extractNls()。其完整逻辑(Makefile.dryice.js)可拆解为以下步骤:

  1. 加载默认消息表require("./src/lib/default_english_messages").defaultEnglishMessages,得到当前默认英文消息的键值集合。
  2. 递归扫描src/目录:跳过包含_test的测试文件,用正则匹配所有形如nls("key", "defaultString")nls('key', 'defaultString')的调用:
    /nls\s*\(\s*("([^"\\]|\\.)+"|'([^'\\]|\\.)+'),\s*("([^"\\]|\\.)+"|'([^'\\]|\\.)+')/g

    该正则要求nls的第一个参数(key)和第二个参数(默认英文串)都是字符串字面量,因此只有“硬编码字符串常量”形式的消息才会被提取,动态拼接的字符串无法被识别。

  3. 合并新 key:若某 key 尚不存在于默认消息表,则以defaultData[key] = defaultString的形式追加。
  4. 回写默认消息文件:将更新后的默认消息表重新序列化写入 src/lib/default_english_messages.js,保持英文基准与源码同步。
  5. 补齐各翻译文件:遍历translations/下所有.json文件,将默认表中的每个 key 都写入其中(existing[i] = existing[i] || "")——已有翻译保留原值,缺失翻译补空字符串,从而保证所有语言文件始终拥有与默认表一致的完整 key 集合

这也是为什么步骤 2 只需写{"$id": "..."}一行:剩下的全部 key 会由extractNls()自动生成。执行完后打开新语言文件,你会看到类似 translations/ru.json 的结构——数十个 key 全部就位,翻译值待填。

三、翻译文件的结构与完整 key 清单

以 translations/ru.json 为参照,Ace 当前的全部可翻译消息分为以下几类(对应 key 前缀):

分类前缀覆盖的界面区域
自动补全autocomplete.补全弹窗的 ARIA 标签、加载提示
编辑器editor.编辑区滚动容器与槽(gutter)的无障碍描述
搜索框search-box.查找/替换输入框占位符、按钮标题、计数器
提示/命令面板prompt.最近使用、其他命令、无匹配命令
文本输入text-input.光标位置 ARIA 标签
代码折叠gutter.code-folding.折叠/展开按钮的标题与 ARIA 标签
行号槽标注gutter.annotation./gutter-tooltip.错误/警告/信息/安全/建议标注的无障碍描述
错误标记error-marker.错误状态提示
其他inline-fold.editor.tooltip.行内折叠、禁用编辑提示

这些消息在源码中的实际消费点包括(均为nls()调用处):

  • 自动补全弹窗 ARIA:src/autocomplete/popup.js
  • 搜索框全部按钮与占位符:src/ext/searchbox.js
  • 编辑器滚动区与槽的无障碍属性:src/editor.js
  • 行号槽折叠控件与标注:src/layer/gutter.js
  • 光标位置提示:src/keyboard/textinput.js

翻译时需注意:翻译值必须完整保留占位符(如$0$1{n}),仅翻译自然语言部分。以默认消息"search-box.search-counter": "$0 of $1"为例,俄语翻译为"$0 из $1"(见 translations/ru.json),$0/$1被原样保留,运行时由nls()填入实际数字。

四、运行时如何消费翻译:nls() 查找与占位符替换

翻译文件生成后,并不会被自动加载,还需要在应用中通过config.setMessages()注入,随后界面代码的nls()调用才会返回对应语言的文本。

4.1 消息注入与查找逻辑

config.setMessages(value, options)(src/lib/app_config.js)用于设置当前使用的消息表,可选options.placeholders指定占位符风格("dollarSigns""curlyBrackets")。

config.nls(key, defaultString, params)(src/lib/app_config.js)的查找优先级为:

  1. messages[key]:按 key 精确命中翻译;
  2. messages[defaultString]:key 未命中时,尝试用默认英文串本身作为 key 查找(允许“翻译了默认串但 key 不同”的情况);
  3. defaultString:以上都未命中时,回退到源码中的默认英文文本。

未命中时还会输出告警,提示在messages.$id对应的语言表中找不到某 key——这正是$id字段在运行时的用途。相关告警实现见 src/lib/app_config.js。

4.2 占位符替换

当传入params时,nls()支持两种占位符风格:

  • 美元符风格(默认)$0$1… 对应params[0]params[1]…,$$转义为字面$
  • 花括号风格{0}{1}… 对应params[0]params[1]…。

默认消息表 src/lib/default_english_messages.js 中的字符串(如"text-input.aria-label": "Cursor at row $0")即采用美元符风格。替换逻辑见 src/lib/app_config.js。

4.3 测试用例验证

仓库的 src/config_test.js 给出了完整的nls行为测试,可作为理解与排错参考:

  • nls("untranslated_key","bar $1")未命中任何翻译时返回默认串"bar $1"
  • key 未命中但默认串被翻译时,返回翻译结果;
  • nls("test_key", "this text should not appear")命中test_key时,返回翻译值而非默认串;
  • setMessages({...}, {placeholders: "curlyBrackets"}){placeholders: "dollarSigns"}下,同一字符串的$n/{n}替换结果不同(测试注释明确“默认使用美元符”)。

五、从零新增一种语言的完整清单

综合以上内容,为 Ace 新增一种语言的完整步骤如下:

  1. 在 translations/ 目录创建<language_id>.json,写入{"$id": "<language_id>"}
  2. 在仓库根目录运行node Makefile.dryice.js nls,生成带全部 key(值为空串)的翻译骨架;
  3. 打开生成的文件,逐条将英文翻译为目标语言,保留$0/$1/{n}等占位符
  4. 在应用初始化时通过config.setMessages(require(".../<language_id>.json"))注入消息表(若使用打包构建,还需将翻译文件纳入构建产物);
  5. 验证:对照 src/config_test.js 的用例逻辑,确认占位符替换与回退行为符合预期。

六、注意事项与限制

  • 仅提取字符串常量extractNls()的正则只匹配nls("key", "default")字面量形式,动态 key 不会被自动提取;
  • key 集合始终对齐:每次执行node Makefile.dryice.js nls都会把默认表中的新 key 合并进所有语言文件,因此建议在源码新增nls()消息后重新运行该命令,避免翻译文件缺 key;
  • 未翻译的 key 回退英文:翻译值为空串或缺失时,nls()依次回退到默认串翻译、默认英文串,界面不会因此报错;
  • 占位符风格统一:翻译文件中$n{n}混用可能导致替换行为不一致,建议跟随默认表统一使用$n风格,或在setMessages时显式指定placeholders

参考资料(仓库内路径)

  • 官方翻译流程文档:translations/Readme.md
  • nls 提取构建脚本:Makefile.dryice.js、命令分发入口 Makefile.dryice.js
  • 默认英文消息表:src/lib/default_english_messages.js
  • 运行时 nls 实现:src/lib/app_config.js
  • 现有翻译示例:translations/ru.json
  • nls 行为测试:src/config_test.js

【免费下载链接】aceAce (Ajax.org Cloud9 Editor)项目地址: https://gitcode.com/gh_mirrors/ac/ace

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

数学建模国赛论文写作核心逻辑:从结构到摘要的实战指南

简介&#xff1a;2021年数学建模优秀论文模板&#xff08;全国一等奖&#xff09;是一份面向全国大学生数学建模竞赛参赛者的排版与写作参考PDF&#xff0c;重点解决论文结构不规范、摘要提炼不到位、图表公式处理粗糙等问题。模板从问题重述、模型假设、符号说明&#xff0c;到…

作者头像 李华
网站建设 2026/9/20 23:43:56

MyBatis 缓存模块源码解析:Cache 接口、装饰器家族与 CacheKey 设计

MyBatis 缓存模块源码解析&#xff1a;Cache 接口、装饰器家族与 CacheKey 设计 【免费下载链接】source-code-hunter &#x1f631; 从源码层面&#xff0c;剖析挖掘互联网行业主流技术的底层实现原理&#xff0c;为广大开发者 “提升技术深度” 提供便利。目前开放 Spring 全…

作者头像 李华
网站建设 2026/9/20 23:43:12

ESP32智能小车从零到一:蓝牙遥控、超声波避障与红外循迹完整实战

简介&#xff1a;面向ESP32开发者与智能小车入门者&#xff0c;这份压缩包提供从零搭建智能小车的完整源码与配套文档&#xff0c;解决硬件选型、电路设计、固件编程到无线控制的全流程问题。内容以构建指南为主线&#xff0c;覆盖ESP32双核、Wi-Fi/蓝牙特性&#xff0c;包含模…

作者头像 李华
网站建设 2026/9/20 23:43:04

极验无感验证码技术解析与实战优化

1. 项目概述"无感验证码"这个概念最近两年在互联网产品圈越来越火&#xff0c;作为从业者我亲身体验过市面上几乎所有验证码方案&#xff0c;今天要聊的极验无感验证码确实让我眼前一亮。不同于传统需要用户点击、拖拽或输入的验证方式&#xff0c;它能在用户几乎无感…

作者头像 李华
网站建设 2026/9/20 23:43:04

FT2DR操作手册实战指南:C4FM、APRS与菜单设置全解析

简介&#xff1a;这份资源是YAESU八重洲FT2DR对讲机的官方操作手册&#xff0c;以PDF格式提供&#xff0c;面向业余无线电爱好者、户外通信用户以及初次接触数字对讲机的新手&#xff0c;可解决从开箱安装、触摸屏操作到中继台、APRS与GPS功能配置的全流程使用疑问。压缩包内为…

作者头像 李华
网站建设 2026/9/20 23:42:43

oMLX分层KV缓存实战:SSD当后备存储,32GB内存跑32K上下文

先说结论&#xff1a;在 Apple Silicon 的机器上&#xff0c;把 SSD 当成 KV 缓存的后备存储&#xff0c;是让 32GB 内存跑 30B 级别模型并撑住上万 token 上下文的性价比方案。我这几个月一直在折腾 oMLX 的分层 KV 缓存&#xff0c;拿它当 Claude Code 的本地后端&#xff0c…

作者头像 李华