Wox 插件国际化(i18n)完整指南:从 plugin.json 到多语言代码实现
桌面应用AI 应用插件系统【免费下载链接】WoxA cross-platform launcher that simply works项目地址https://gitcode.com/gh_mirrors/wo/Wox点击查看免费下载导读本文以 Wox 开源仓库中面向插件开发者的国际化指南为骨架系统讲解在 Wox 插件中实现多语言支持的两种翻译定义方式plugin.json内联定义与lang/目录翻译文件、两种代码取值方式GetTranslationAPI 与i18n:前缀隐式翻译并结合 Wox 核心源码plugin/metadata.go、i18n/manager.go、i18n/lang.go、plugin/api.go深入剖析翻译的底层查找优先级、缓存机制与回退策略。读完本文你将能独立为 Wox 插件Node.js 或 Python配置完整的国际化支持并理解 Wox 插件国际化 API 的内部工作原理。一、核心原则Raw String 与手动格式化Wox 插件国际化遵循两条最重要的设计原则理解它们是正确使用一切 API 的前提只返回原始字符串Raw Strings OnlyWox 的 API 只负责从资源plugin.json内联翻译或lang/目录文件中取出原始翻译字符串不做任何额外的参数替换或模板处理。手动格式化Manual Formatting占位符的替换如%s、{name}、{}等必须由插件代码自己完成。Wox 不会替你调用sprintf或.format()。这一设计在 Wox 核心代码中得到印证APIImpl.GetTranslation的实现是直接调用Metadata.translate将键解析为本地化字符串见 plugin/api.go返回的是纯粹的字面量后续的fmt.Sprintf参数拼接由各系统插件自行完成例如 plugin/system/app/app.go 中fmt.Sprintf(a.api.GetTranslation(ctx, plugin_app_open_failed_description), runErr.Error())的写法。记住这两条原则你就不会在插件里写出翻译后占位符没被替换的 bug。二、定义翻译的两种方式方式一在plugin.json中内联定义推荐对于大多数插件字符串数量不多直接在清单文件plugin.json中通过I18n字段定义翻译是最简单的方式。其结构为语言代码 → 键值对的嵌套映射{ Name: i18n:plugin_name, Description: i18n:plugin_desc, I18n: { en_US: { plugin_name: My Plugin, plugin_desc: A useful plugin, hello: Hello }, zh_CN: { plugin_name: 我的插件, plugin_desc: 一个有用的插件, hello: 你好 } } }要点说明Name与Description直接写成i18n:key形式由 Wox 在显示插件名/描述时自动翻译详见下文隐式翻译小节I18n中的键如plugin_name、hello与i18n:前缀后的键一一对应语言代码使用 BCP-47 风格见下文语言代码与支持范围。方式二lang/目录翻译文件当插件包含大量字符串几十甚至上百条时推荐把翻译拆分为独立的语言文件放在插件根目录的lang/目录下my-plugin/ plugin.json lang/ en_US.json zh_CN.jsonen_US.json{ hello: Hello, error: { file: File not found: %s } }需要特别说明的是lang/文件支持嵌套 JSON 结构如error.fileWox 在加载时会将其扁平化为点分隔的键。从源码看Metadata.LoadPluginI18nFromDirectory会遍历插件目录下的lang/*.json只接受文件名与 Wox 支持语言代码一致的文件并通过flattenI18nJSON递归展开嵌套结构{error: {file: ...}}→error.file: ...最后mergeI18n合并进插件的I18n映射见 plugin/metadata.go。这意味着使用lang/目录时代码中可以用error.file这样的点路径键来取到嵌套翻译# 对应 lang/en_US.json 中的 error: { file: File not found: %s } error await api.get_translation(ctx, error.file)三、语言代码与支持范围Wox 核心层维护了一份受支持的语言代码清单。从 i18n/lang.go 看目前支持以下语言语言代码语言en_US英语美国zh_CN简体中文ru_RU俄语pt_BR葡萄牙语巴西ko_KR韩语ja_JP日语两点实践建议插件翻译应至少提供en_USWox 的翻译回退逻辑以en_US作为兜底详见下文查找优先级且元数据名称的英文展示GetNameEn也依赖en_US表如果你的插件用户所在语言不在上述列表中lang/目录中对应文件会被加载逻辑跳过LoadPluginI18nFromDirectory只接受受支持的语言代码文件此时请退回使用en_US键值作为默认文案。四、在代码中获取翻译GetTranslationAPINode.jsWox 的 Node.js 插件 API 提供了GetTranslation(ctx, key)方法返回当前语言的原始翻译字符串类型定义见 wox.plugin.nodejs/types/index.d.tsconst raw await this.api.GetTranslation(ctx, hello); // 返回 Hello 或 你好PythonPython 插件 API 对应的方法为get_translation(ctx, key)实现说明见 wox.plugin.python/src/wox_plugin/api.pyraw await self.api.get_translation(ctx, hello) # 返回 Hello 或 你好值得注意的细节该 API 的语义是未找到翻译时回退返回键本身Falls back to the key if no translation is found这与 Wox 核心层的实现一致——TranslateWox与TranslateI18nMap在找不到任何翻译时都会返回原始键见 i18n/manager.go。因此翻译缺失不会让插件崩溃但会直接暴露原始 key 字符串建议在开发期完整覆盖所有语言。五、字符串格式化关键步骤由于 Wox 只返回原始字符串参数替换必须由插件代码完成。这是插件国际化最容易出错、也最需要统一的环节。Node.js 示例占位符%s// 假设 lang 文件或 I18n 中有: { greet: Hello %s } const raw await this.api.GetTranslation(ctx, greet); const message raw.replace(%s, World); // message Hello WorldPython 示例占位符{}# 假设 lang 文件或 I18n 中有: { greet: Hello {} } raw await self.api.get_translation(ctx, greet) message raw.format(World) # message Hello World多参数与占位符一致性建议保持占位符风格一致同一插件内建议统一使用一种占位符约定如 Python 统一{}、Node.js 统一%s并保证所有语言文件中的占位符数量一致注意语言间词序差异不同语言中参数出现的顺序可能不同例如打开 %s 失败vs Failed to open %s因此占位符不要硬编码在字符串中间以外的位置假设——这也是为什么get_translation返回原始串、由代码拼接的另一个原因你可以针对每种语言写出自然的语序参考 Wox 系统插件的写法它们通常用fmt.SprintfGo配合GetTranslation返回值完成拼接如 plugin/system/app/app.go。六、使用i18n:前缀实现隐式翻译如果你只是想在界面上显示本地化文本如结果项的Title、SubTitle、操作名等最省事的方式是直接使用i18n:前缀——Wox 会在 UI 展示前自动完成翻译无需手动调用GetTranslation。1. 在plugin.json清单中使用用于静态元数据如Name和Description{ Name: i18n:plugin_name, Description: i18n:plugin_desc }Wox 在读取插件元数据时会用Metadata.translate解析这些i18n:前缀的字段GetName/GetDescription均走translate路径见 plugin/metadata.go最终在插件管理界面等处显示本地化后的名称与描述。2. 在代码中使用i18n:前缀可以直接用在几乎所有面向用户展示的字符串字段上例如结果的Title、SubTitle、操作Action名称、Tooltip 等Node.jsreturn [{ Title: i18n:hello, // Wox 自动翻译为 Hello 或 你好 SubTitle: i18n:plugin_desc, // ... }]Pythonreturn [Result( titlei18n:hello, sub_titlei18n:plugin_desc, # ... )]在 Wox 内部这类i18n:前缀字符串会被解析为common.I18nString类型见 common/i18n.go在需要展示的场合统一走翻译管线系统插件中也大量使用这种写法例如Tooltip: i18n:plugin_clipboard_copy_characters见 plugin/system/clipboard/clipboard.go。隐式翻译的适用边界适合静态的、无需参数替换的界面文本Title、SubTitle、按钮名、Tooltip、预览标签等不适合需要动态拼接参数的消息如文件 xxx 未找到——此时应使用GetTranslation拿到原始串后自行格式化。七、底层原理翻译的查找优先级与缓存理解 Wox 核心的翻译管线有助于你判断为什么某些键会命中、某些键会回退。整条链路可以拆成两层。第一层插件级翻译TranslateI18nMap当插件包含I18n映射无论是plugin.json内联还是lang/目录合并而来Metadata.translate首先调用i18n.Manager.TranslateI18nMap见 i18n/manager.go其查找顺序为当前语言在I18n[当前语言代码]中查找键en_US回退若当前语言不是en_US再尝试I18n[en_US]原样返回都找不到则返回原始键含i18n:前缀的原文。第二层Wox 全局翻译TranslateWox若插件级映射没有命中则进入 Wox 自身的全局语言表。TranslateWox见 i18n/manager.go的实现是先去前缀i18n:在当前语言表查找未命中再查内置en_US表enUsLang在 Manager 初始化时即加载见 i18n/manager.go最后仍找不到就返回原始键。因此插件翻译优先于 Wox 全局翻译en_US是两级查找共同的兜底语言缺失键最终原样暴露不会抛错。额外的性能细节翻译结果缓存Metadata.translate内部维护了一个以语言代码 | 原始文本为键的translateCache见 plugin/metadata.go同一插件的同一条文本在同一语言下只会解析一次之后全部命中缓存。这意味着不要担心在查询循环里频繁调用GetTranslation/使用i18n:前缀的性能问题翻译本身是廉价的缓存查找。八、最佳实践清单综合官方指南与源码实现为 Wox 插件落地国际化的推荐实践如下优先内联字符串较少时使用plugin.json的I18n内联定义结构简单、随插件分发、无需额外文件大量字符串再拆文件超过几十条翻译时迁移到lang/目录支持嵌套 JSON键用点路径如error.file始终提供en_US作为插件级与全局级的双重兜底语言也是插件名英文展示GetNameEn的数据来源界面静态文本用i18n:前缀Title、SubTitle、操作名、Tooltip 直接写i18n:key省去手动调用动态文本用GetTranslation 手动格式化先取原始串再在代码中用%s/{}等占位符替换参数注意各语言文件占位符数量与语序的一致性善用回退语义翻译键缺失时 API 返回键本身而非报错调试时若界面上出现i18n:xxx原文说明该键在对应语言下未定义立即补全遵循支持的语言范围目前 Wox 支持en_US、zh_CN、ru_RU、pt_BR、ko_KR、ja_JP超出范围的lang/文件不会被加载。参考阅读插件国际化官方指南原始文档.agents/skills/wox-plugin-creator/references/plugin_i18n.md翻译核心实现wox.core/i18n/manager.go两级查找与回退、wox.core/i18n/lang.go支持语言清单插件元数据与翻译管线wox.core/plugin/metadata.goi18n:前缀解析、lang/目录加载、翻译缓存API 层实现wox.core/plugin/api.goGetTranslation、wox.core/plugin/host/host_websocket.goWebSocket 协议中的GetTranslation方法分发语言 SDKwox.plugin.python/src/wox_plugin/api.pyPython 的get_translation、wox.plugin.nodejs/types/index.d.tsNode.js 的GetTranslation类型系统插件实战范例wox.core/plugin/system/app/app.go、wox.core/plugin/system/clipboard/clipboard.go赞分享桌面应用AI 应用插件系统【免费下载链接】WoxA cross-platform launcher that simply works项目地址https://gitcode.com/gh_mirrors/wo/Wox点击查看免费下载相关推荐Wox 插件规范完全指南从 plugin.json 到国际化与网格布局Wox 插件规范完全指南从 plugin.json 到国际化与网格布局 导读 plugin.json 是 Wox 插件开发的门面与契约它决定了插件能否在目标桌面应用AI 应用插件系统3大理由选择ImageGlass重新定义Windows图像浏览体验3大理由选择ImageGlass重新定义Windows图像浏览体验 在数字图像日益丰富的今天你是否还在忍受缓慢的图片加载、有限的格式支持或是臃肿的专业软件前端桌面应用移动开发别再一格一格手动搭了用 Arnis 一键生成真实世界的 Minecraft 城市别再一格一格手动搭了用 Arnis 一键生成真实世界的 Minecraft 城市 想象一下你在 Minecraft 里打开存档看到的不是随机生成的村庄而桌面应用游戏开发GIS上一篇【亲测免费】 LuaDec51 使用教程下一篇 从JDBC地狱到Scala天堂ScalikeJDBC零样板高效数据库操作指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

InvenTree开源库存管理系统:库存、BOM与出入库一表看清

InvenTree开源库存管理系统:库存、BOM与出入库一表看清

InvenTree开源库存管理系统:库存、BOM与出入库一表看清 【免费下载链接】InvenTree Open Source Inventory Management System 项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree 某个料号被两个产品同时用到,三个人各维护一张库存表&…

2026/10/15 21:24:26 阅读更多 →
awesome-free-saas健身追踪:Vtrack训练打卡与进度统计完整指南

awesome-free-saas健身追踪:Vtrack训练打卡与进度统计完整指南

awesome-free-saas健身追踪:Vtrack训练打卡与进度统计完整指南 【免费下载链接】awesome-free-saas an awesome list of free SaaS (software as a service) for you. 项目地址: https://gitcode.com/GitHub_Trending/awe/awesome-free-saas awesome-free-sa…

2026/11/11 11:46:30 阅读更多 →
fi网页动图制作避坑指南:3个细节省50%预算

fi网页动图制作避坑指南:3个细节省50%预算

fi网页动图制作避坑指南:3个细节省50%预算 备案流程一头雾水,是很多山东甲方在启动官网或电商项目时最头疼的事。很多人以为只要服务器架好就能上线,结果卡在ICP备案上几周,网站迟迟打不开。其实,备案只是表象,背后藏着大量关于服务器配置、域名解析、甚至页面动效制作的隐性成本。今天咱们不聊虚的,直接拆…

2026/9/20 13:35:34 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/10 23:32:01 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/10 23:32:03 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/11 2:31:33 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/10 16:14:15 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/10 12:51:50 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/10 23:32:10 阅读更多 →

日新闻

周新闻

月新闻