☰
如何读懂 Obsidian i18n:Babel AST 字符串提取原理完整解析
2026/9/25 2:50:34 网站建设 项目流程

如何读懂 Obsidian i18n:Babel AST 字符串提取原理完整解析

【免费下载链接】obsidian-i18n项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-i18n

Obsidian i18n是一款专为 Obsidian 打造的插件国际化工具,核心能力是Babel AST 字符串提取:它把社区插件的main.js解析成语法树,像"拆积木"一样精准定位所有界面文案,再配合大模型批量翻译并安全写回,让不懂代码的用户也能一键完成 Obsidian 插件汉化。本文用图解方式带你完整看懂这套"字符串提取"的工作原理。

为什么不用正则,而要用 AST 提取字符串?

最朴素的汉化方案是"全文搜索替换":在main.js里搜"Cancel",替换成"取消"。但这样做很容易翻车:

  • 误伤代码里的同名标识符、URL 或日志常量;
  • 插件更新后文本位置变化,替换规则全部失效;
  • 无法记录"这段文字出现在哪个上下文",同一句OK在不同弹窗里含义可能不同。

Obsidian i18n 选择了更稳妥的路线:先理解代码结构,再提取字符串。Babel 是 JavaScript 生态最成熟的语法解析器,它能把一整份压缩代码还原成结构清晰的"抽象语法树"(AST,Abstract Syntax Tree)。树的每个节点都带着"这句话是什么类型的语法、变量叫什么、出现在哪个函数调用里"等上下文信息——这正是安全提取界面文案所需的依据。

💡 简单说:正则是在"找词",AST 是在"读懂句子结构后挑词"。

Babel AST 字符串提取的完整流程

整个提取引擎的核心实现在 core-ast-translator.ts,可以拆成四步流水线:

① 解析(Parse):代码 → 语法树

引擎调用 Babel 的parse把插件main.js读成 AST。值得注意的是解析配置里开启了errorRecovery(容错模式)和一整套现代语法插件(TypeScript、JSX、可选链等),保证再"怪异"的压缩产物也能尽量解析成功,而不是直接报错放弃。相关代码见 parseAst。

② 遍历(Traverse):按白名单锁定"UI 上下文"

这是提取策略的灵魂——极度保守的白名单机制。引擎不会把代码里所有字符串都抓出来,只收集以下五类节点的字符串:

节点类型代码长相提取条件
变量声明const title = "..."变量名在"赋值白名单"中
赋值表达式el.textContent = "..."属性名在白名单中
对象属性{ name: "..." }键名在"键名白名单"中
函数调用new Notice("...")函数名在"函数白名单"中
构造表达式new Setting(...)同上

默认白名单本身就是一份"Obsidian UI 词典":title、placeholder、textContent、setName、setDesc、Notice、renderMarkdown等等,覆盖几乎所有面向用户的展示位置,配置集中在 config.ts。遍历逻辑见 traverseWhitelist。

③ 过滤(Filter):双重校验内容有效性

通过白名单的字符串还要过第二道关 isValidText,采用"先拒绝、后放行"的双重校验:

  • 拒绝规则(命中即丢弃):URL、文件路径、十六进制颜色、CSS 单位、camelCase 变量名、纯数字、kebab-case ID……共 14 条正则,定义在 AST_DEFAULT_RULES;
  • 放行规则(命中其一即保留):包含空格(多半是人类语句)、包含中文等非 ASCII 字符、以标点结尾;纯英文单词则作为兜底直接放行。

这套设计的哲学是:宁可漏提,不可错提——漏掉的词条用户可以在表格里手动补,而错提的词条会在"应用"时破坏代码。

④ 指纹(Fingerprint)与去重

每条提取结果最终被整理成一个结构简单的词条:

{ type: 'CallExpression', name: 'Notice', source: 'Saving...', target: 'Saving...' }

对应类型定义 PluginTranslationV1Ast,其中type+name+source三元组构成唯一"指纹",用于去重和后续精准回写,实现见 deduplicateResults。

提取之后:表格化编辑与译文回写

提取出的词条进入可视化 AST 编辑器,按"节点类型 / 变量名 / 原文 / 译文"四列展示,支持行内直写、全文搜索与"仅看未翻译"筛选,完整操作说明见官方文档 ast-editor.mdx。

当你点击"应用",真正的回写发生。InjectorManager 会按"备份 → 替换 → 健康检查"三步安全执行:

  1. 优先从备份读取原始代码再翻译,保证永远基于母语原文而非已翻译内容做二次替换;
  2. 调用 translate 做两级匹配:先用完整指纹严格匹配,匹配不到再退化为"按原文宽松匹配",这样即使插件版本微调、变量重命名,旧译文也能继续命中;
  3. 替换字符串时若译文里含${变量},会先重新解析成模板字符串节点再写回(见 replaceSource),避免把${name}当成普通文本写坏语法。

写回后系统会自动重启目标插件做健康检查:一旦发现插件加载失败,立刻触发自动回滚,用备份恢复原始文件(injector.ts)。此外还有 validateSecurity 对译文做安全审计,拦截eval()、<script>等危险模式——这套"备份 + 回滚 + 审计"机制就是插件汉化敢直接改写main.js的底气。

如何按你的目标插件微调提取规则?

白名单和过滤正则都开放给用户自定义,入口在插件设置的"AST 配置"面板(i18n-ast.ts),共五个可调项:

  • 变量赋值白名单:追加目标插件私有的变量名;
  • 函数调用白名单:追加自定义 UI 函数名;
  • 对象键名白名单:追加自定义配置项键名;
  • 排除正则:命中即丢弃的文本特征;
  • 有效特征正则:命中其一才保留的文本特征。

举个例子:若某插件总用showToast("...")弹提示,把showToast加进函数白名单即可让 AST 提取引擎自动捕获这些文案,无需改一行源码。

💡 除了 AST 路线,插件还内置了基于正则的兜底提取器 core-regex-translator.ts,两者互补:AST 管"精准",正则管"覆盖"。提取入口的调度逻辑位于 extract-manager.ts。

总结:Obsidian i18n 的 AST 提取为什么可靠

把整条链路串起来看,Babel AST 字符串提取的原理其实是一条层层设防的流水线:

  1. Babel 容错解析,把压缩代码还原成语法树;
  2. UI 上下文白名单,只从变量赋值、函数调用、对象键名里挑"长得像界面文案"的字符串;
  3. 拒绝/放行双重正则,滤掉 URL、颜色、CSS、变量名等噪音;
  4. 指纹去重,每条译文都有唯一坐标,可追溯、可回滚;
  5. 备份 + 健康检查 + 自动还原,让"改写插件源码"这件事变得可逆。

正是这种"保守提取 + 安全回写"的设计,Obsidian i18n 才能把原本属于程序员的黑活,变成任何用户点三次按钮就能完成的插件汉化。

【免费下载链接】obsidian-i18n项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-i18n

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询