资讯动态

AionUi 多语言架构指南:基于 i18next 的国际化实现与源码解析

发布时间:2026/9/11 23:31:35 来源:尧图企业网站定制
AionUi 多语言架构指南基于 i18next 的国际化实现与源码解析【免费下载链接】AionUiOpen-source 24/7 Cowork app for OpenClaw, Hermes, Claude Code, Codex, OpenCode and 20 more CLI Agent | Customize your assistants | Team them upStar if you like it!项目地址: https://gitcode.com/GitHub_Trending/ai/AionUiAionUi桌面端的多语言支持基于 i18next 与 react-i18next 构建本文以 i18n README 为主体骨架结合仓库内真实的初始化代码、语言包目录、类型生成脚本与单元测试系统讲解 AionUi 的语言体系结构、翻译键组织规范、运行时语言切换机制以及 RTL从右到左布局与本地化数字日期格式的处理方式。读完本文你将掌握如何在 AionUi 中定位任意界面文案、添加新翻译、切换默认语言并理解桌面端与 WebUI 之间语言实时同步的底层原理。技术栈与支持的语言AionUi 渲染进程renderer的多语言方案以两个 npm 包为核心i18next负责语言包加载、资源合并、语言切换与插值interpolationreact-i18next为 React 组件提供useTranslationHook将 i18next 实例与组件渲染周期绑定。仓库 README 中提到“中文 (zh-CN) 为默认语言、英文 (en-US)”但对照当前仓库实际配置 i18n-config.json 可知该项目实际上已扩展为13 种支持语言并且以en-US作为参考语言referenceLanguage与兜底语言fallbackLanguage语言BCP 47 标签方向简体中文zh-CNLTR英文en-USLTR日文ja-JPLTR繁体中文zh-TWLTR韩文ko-KRLTR土耳其文tr-TRLTR俄文ru-RULTR乌克兰文uk-UALTR巴西葡萄牙文pt-BRLTR德文de-DELTR西班牙文es-ESLTR法文fr-FRLTR波斯文fa-IRRTL配置文件中还声明了全部翻译模块modules清单common、agentMode、update、login、fileSelection、preview、conversation、settings、messages、mcp、acp、codex、tools、google、cron、guid、agent、team、pet共 19 个业务模块。也就是说翻译资源不是一个大 JSON而是按模块拆分的多份 JSON。文件结构与翻译包组织原 README 描述的文件结构是src/renderer/i18n/而当前仓库中该目录的实际位置与形态如下packages/desktop/src/renderer/services/i18n/ ├── index.ts # i18next 初始化与语言切换核心逻辑 ├── direction.ts # RTL/LTR 文档方向工具 ├── format.ts # 本地化数字、日期、货币、字节大小格式化 ├── list.ts # 本地化名称列表Intl.ListFormat ├── i18n-keys.d.ts # 自动生成的 I18nKey 联合类型勿手改 ├── README.md # 说明文档 └── locales/ ├── en-US/ # 英文语言包参考语言 │ ├── index.ts # 汇总导出本语言全部模块 │ ├── common.json │ ├── conversation.json │ └── ... # 共 19 个模块 JSON ├── zh-CN/ ├── zh-TW/ ├── ja-JP/ ├── ko-KR/ ├── de-DE/ ├── es-ES/ ├── fr-FR/ ├── tr-TR/ ├── ru-RU/ ├── uk-UA/ ├── pt-BR/ └── fa-IR/每个语言目录下都有一套同名同结构的 JSON 文件例如 locales/zh-CN/index.ts 会把该语言目录下的 19 个 JSON 模块统一导入并导出为一个大对象。这种“按模块拆包”的设计有两个好处按需加载配合 i18next 的addResourceBundle切换语言时只加载目标语言包类型化兜底缺失的键可以回退到en-US参考包而不是直接显示裸键名。i18next 初始化原理为什么不用语言检测器i18n/index.ts 是渲染进程 i18n 的初始化入口其初始化代码大致如下import i18n from i18next; import { initReactI18next } from react-i18next; i18n .use(initReactI18next) .init({ resources: initialResources, lng: initialLanguage, fallbackLng: DEFAULT_LANGUAGE, debug: false, interpolation: { escapeValue: false }, }) .catch((error: Error) { console.error(Failed to initialize i18n:, error); });值得注意的源码细节是项目刻意不使用i18next-browser-languagedetector。源码注释明确解释了原因Issue #1176在 WebUI 模式下浏览器 localStorage 的 origin 与 Electron 渲染进程不同语言检测器会读到错误的或缺失的值并回退到navigator.language导致语言不匹配。因此 AionUi 采用了自己的一套“语言提示”链路getInitialLanguage()依次尝试localStorage 提示读取localStorage.getItem(i18nextLng)WebUI 与桌面端共用作为快速提示注入提示读取window.__initialLanguageElectron 主进程注入的配置语言系统语言提示仅在后端启动失败的降级场景下才回退使用navigator.language最终通过normalizeLanguageCode归一到受支持的语言标签否则使用DEFAULT_LANGUAGE。初始语言在模块加载时同步注入resources目的是避免首屏出现“先英文后切换”的 FOUC闪白问题。随后异步执行initLanguage()等待configService.whenReady()后以configService.get(language)为**唯一权威来源single source of truth**进行ensureAndSwitch并将结果写回 localStorage 供下次启动快速命中。桌面端与 WebUI 的实时同步index.ts中注册了两个languageChanged监听器一个负责懒加载新语言的资源包i18n.hasResourceBundle不存在时调用loadLocaleModules再addResourceBundle另一个负责应用文档方向调用applyDocumentDirection(lang)更新html的dir与lang属性。除此之外changeLanguage()还会通过ipcBridge.systemSettings.changeLanguage.invoke()通知主进程用于托盘菜单等主进程侧文案并通过ipcBridge.systemSettings.languageChanged事件广播给其他渲染进程——这正是桌面端与 WebUI 一处切换语言、另一处无需重启即可实时跟随的实现基础ipcBridge.systemSettings.languageChanged.on(async ({ language }) { const normalized normalizeLanguageCode(language); if (i18n.language normalized) return; // 自己触发的变更直接跳过 await ensureAndSwitch(i18n, normalized, loadLocaleModules); localStorage.setItem(i18nextLng, normalized); });在组件中使用翻译原 README 给出的组件用法完全适用于当前仓库通过react-i18next的useTranslationHook 获取t函数用点号路径访问翻译键import { useTranslation } from react-i18next; const MyComponent () { const { t } useTranslation(); return ( div h1{t(common.title)}/h1 p{t(common.description)}/p /div ); };类型安全的翻译键AionUi 更进一步仓库中 i18n-keys.d.ts 是一个自动生成的联合类型文件将en-US参考语言包中的所有翻译键展开为I18nKey类型文件头注释明确标注 “AUTO-GENERATED FILE - DO NOT EDIT”。其生成脚本是 scripts/generate-i18n-types.js核心逻辑为读取 i18n-config.json 中的modules清单递归遍历en-US/{module}.json提取全部叶子键拼成模块名.键路径输出形如conversation.welcome.title | common.send | ...的联合类型若文件内容未变化则跳过写入避免无谓的格式化。借助I18nKey类型t()的入参在编译期即可校验翻译键写错或删除后会直接产生 TypeScript 报错极大降低文案维护成本。切换语言与持久化原 README 中的“切换语言”示例同样成立但在 AionUi 中切换语言不应直接调用裸的i18n.changeLanguage而是推荐使用index.ts导出的changeLanguage()封装它会同步完成三件事export async function changeLanguage(lang: string): Promisevoid { await ensureAndSwitch(i18n, lang, loadLocaleModules); const normalized normalizeLanguageCode(lang); await configService.set(language, normalized); // 持久化到后端配置 if (typeof localStorage ! undefined) { localStorage.setItem(i18nextLng, normalized); // 写回 localStorage 提示 } ipcBridge.systemSettings.changeLanguage.invoke({ language: normalized }).catch(() {}); }ensureAndSwitch定义于 common/config/i18n.ts先检查hasResourceBundle缺失则懒加载并addResourceBundle再去重changeLanguage调用configService.set(language, normalized)把语言写入后端配置保证重启后仍然生效localStorage 与 IPC 通知分别服务 WebUI 快速提示和主进程/其他渲染进程同步。顶层导航栏中的语言切换器语言选择保存在 localStorage下次访问自动应用上次选择即基于此链路实现。同时 README 提醒语言选择会保存在 localStorage 中下次访问时会自动应用上次选择的语言这与getLocalStorageLanguageHint()的读取逻辑完全对应。添加新的翻译步骤在packages/desktop/src/renderer/services/i18n/locales/zh-CN/对应模块 JSON如common.json中添加中文翻译在packages/desktop/src/renderer/services/i18n/locales/en-US/对应模块 JSON 中添加对应的英文翻译en-US 是参考语言与兜底语言必须齐全在组件中使用t(key)获取翻译。翻译键的命名规范原 README 规定的三条命名规范在当前仓库中被严格执行使用点号分隔的层级结构使用小写字母与下划线部分键也使用 camelCase如copySuccess、fileAttach.uploadSuccess但整体遵循小写下划线原则按功能模块分组。对照真实的 locales/zh-CN/common.json 可以看到实际形态{ send: 发送, cancel: 取消, save: 保存, delete: 删除, confirm: 确定, file: 文件, folder: 文件夹, workspace: 项目, settings: 设置, loading: 请稍候... }更复杂的层级示例来自conversation模块例如conversation.welcome.title、conversation.agentError.codes.USER_AGENT_DISCONNECTED.title这类“模块 → 场景 → 错误码 → 字段”的多级结构。兜底合并机制为了让缺少某条翻译的语言不会显示裸键名common/config/i18n.ts 提供了mergeWithFallback(fallback, target)深合并函数递归地把en-US参考包中缺失的键补进目标语言包目标语言已有的键保持优先。getLocaleModules()在渲染进程侧把这一机制与懒加载缓存结合保证任何语言包都“隐含”完整的 en-US 兜底。语言代码规范化normalizeLanguageCode()是语言体系中最核心的工具函数位于 common/config/i18n.ts它把任意“语言提示”归一到受支持的 13 个 BCP 47 标签之一规则包括下划线转连字符zh_CN→zh-CN、de_DE→de-DE基础语言码映射到区域zh→zh-CN、ja→ja-JP、ko→ko-KR、tr→tr-TR、ru→ru-RU、uk→uk-UA、pt→pt-BR、de→de-DE、es→es-ES、fr→fr-FR、fa→fa-IR繁体中文保护zh-HK、zh-MO、zh-Hant及zh-Hant-*一律归到zh-TW绝不降级为简体中文区域变体归一de-AT、de-CH等归到de-DE不支持的语言回退默认it、空字符串等回退到DEFAULT_LANGUAGE。这些规则在单元测试 tests/unit/common/i18n.test.ts 中有完整覆盖例如normalizeLanguageCode(zh_HK) zh-TW、normalizeLanguageCode(de-CH) de-DE、normalizeLanguageCode(it) DEFAULT_LANGUAGE等断言可以作为新增语言映射时修改与验证的参考。RTL 布局与文档方向波斯文fa-IR是 AionUi 唯一从右到左的语言。方向处理集中在 direction.tsisRtlLanguage()判断当前应用语言是否为 RTL内部维护RTL_LANGUAGES new Set([fa-IR])directionForLanguage()返回rtl | ltrapplyDocumentDirection()把dir与lang属性写入document.documentElementdir驱动全应用 CSS 逻辑属性与 flex/grid 的 start/endlang驱动拼写检查、CJK 字形选择与辅助技术读屏。源码注释强调布局方向永远由应用语言决定而不是宿主操作系统这是为了保证界面语言与布局方向不会互相矛盾。另外对于代码块、终端输出、文件路径这类天生 LTR 的内容应在容器上局部设置dirltr而不是与文档级方向对抗。本地化数字、日期与列表仅翻译文案并不够——数字与日期格式同样需要随语言变化。原 README 未覆盖这部分但仓库提供了完整的格式化服务位于 format.tsformatNumber(value, language, options)按应用语言格式化数字德语环境下12.6渲染为12,6formatCurrency(amount, currency, language, options)货币格式化无法渲染的货币代码回退为number codeformatDateTime / formatDate / formatTime时间日期格式化默认复刻toLocaleString()的数值日期加时间formatByteSize / formatByteRate二进制1024字节单位如12.5 MB、1.2 MB/s内部按locale|options键缓存Intl.NumberFormat/Intl.DateTimeFormat实例避免列表渲染中的重复构造开销。其设计动机同样源于源码注释Intl.NumberFormat(undefined, …)与裸toLocaleString()解析的是宿主操作系统的语言环境与用户在 AionUi 内选择的应用语言无关——一台运行英文界面的德语系统桌面曾经会渲染出0,42 $与17.8.2025。因此所有用户可见的数字与日期必须显式传入useTranslation().i18n.language进行格式化。类似的还有 list.ts 中的formatNameList()用Intl.ListFormat按应用语言拼接名称列表中文会用顿号与“和”德语/法语会使用 “und”/“et”波斯文会使用阿拉伯逗号避免硬编码、或,造成的多语言错误。注意事项与最佳实践综合原 README 的“注意事项”与源码实现AionUi 的 i18n 开发约束可归纳为所有用户可见文本都应使用翻译函数不要在组件中硬编码中文或英文文案翻译键应具有描述性按模块.场景.字段层级组织便于维护与检索新增翻译时确保中英文都有对应条目——en-US是参考语言与兜底语言缺失键会从 en-US 回退但显示内容可能不是目标语言不要直接修改i18n-keys.d.ts它由scripts/generate-i18n-types.js自动生成改完 JSON 后应重新运行生成脚本仓库根目录另有 scripts/check-i18n.js 可用于检查语言包一致性不要绕过changeLanguage()直接调用 i18next 裸接口否则会丢失配置持久化、localStorage 提示与 IPC 广播同步数字与日期格式化请走/renderer/services/i18n/format直接使用toLocaleString()系列会错误地依赖宿主系统语言RTL 语言fa-IR的文档方向由应用语言驱动代码块等 LTR 内容局部用dirltr处理。小结AionUi 的国际化体系远比 README 单页描述得完整13 种语言按 19 个业务模块拆包管理以 en-US 为参考语言做深合并兜底初始化阶段刻意绕开浏览器语言检测器改为“localStorage 提示 configService 权威配置 IPC 广播同步”的三层链路兼顾桌面端与 WebUI 的一致性同时用I18nKey联合类型、语言代码规范化、RTL 方向工具与Intl格式化服务把“文案、布局、数字、日期”四大国际化维度全部纳入类型安全与测试保障之中。开发者在 AionUi 中接入或扩展语言时可以从 i18n 目录 与 i18n 配置 入手遵循本文的键规范与注意事项即可平滑落地。【免费下载链接】AionUiOpen-source 24/7 Cowork app for OpenClaw, Hermes, Claude Code, Codex, OpenCode and 20 more CLI Agent | Customize your assistants | Team them upStar if you like it!项目地址: https://gitcode.com/GitHub_Trending/ai/AionUi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价