【免费下载链接】puppyoneContext drive for your AI agents项目地址https://gitcode.com/gh_mirrors/pu/puppyone点击查看免费下载PuppyOne 是一款面向 AI Agent 的桌面工作区Context drive for your AI agents其本地化架构原生支持 8 种语言英文、简体中文、日语、韩语、德语、法语、西班牙语和巴西葡萄牙语。本文带你拆解它如何用一份语言清单驱动 locales/ 目录结构、如何基于 ICU MessageFormat 渲染带参数的界面文案以及 RTL从右到左文字支持是如何设计进去的。一、总体架构一份清单驱动三层代码 PuppyOne 的本地化不是散落在各处的翻译文件而是由三层组成层位置职责语言清单locales/manifest.json声明 8 种语言的元信息是全局唯一事实来源消息目录消息目录表locales/renderer/、locales/native/各语言的翻译文案核心运行时packages/localization/src/core/语言解析、消息格式化、方向RTL/LTR处理主进程Electron和渲染进程React各自实现了一套读取器但都依赖同一份manifest.json保证两侧语言行为一致。二、manifest.json8 种语言是怎么声明的 打开 locales/manifest.json每种语言就是一个描述符包含几个关键字段localeBCP-47 语言标签如zh-Hans、pt-BRlabel该语言的自称日语显示为「日本語」而非 Japanesedirection文字方向ltr或rtlaliases别名映射例如zh-CN、zh-SG都归并到zh-HansmatchLanguage / matchScript系统语言自动匹配策略productionReady是否已正式上线、可被用户选择其中两个细节值得注意中文按文字而非语言匹配。zh-Hans的matchLanguage为false、matchScript为Hans——也就是说系统语言为中文且文字系统为简体时才命中繁体中文用户不会被错误地分配到简体界面。兜底语言被硬编码为英文。清单加载时会校验defaultLocale必须是en且必须productionReady见 packages/localization/src/core/manifest.ts 中的validateManifest函数——这保证任何异常情况下应用永远有可用文案。三、目录结构语言 × 功能模块的二维拆分 渲染进程的翻译文件在 locales/renderer/ 下按语言分目录每个语言目录内再按功能模块拆成 14 个 JSONlocales/ ├── manifest.json # 语言清单 ├── native/ # 原生主进程文案8 个单文件 │ ├── en.json │ └── zh-Hans.json ... └── renderer/ # 渲染进程文案8 个目录 └── en/ ├── agent.json # AI Agent 面板 ├── editor.json # 编辑器 ├── source-control.json # 源码管理 ├── terminal.json # 终端 ├── settings.json # 设置 └── ... 共 14 个模块以英文目录 locales/renderer/en/ 为例模块划分覆盖了 Agent、编辑器、云、终端、源码管理、设置等几乎所有产品面。这种按功能拆文件的做法让翻译团队可以按模块并行工作也让渲染进程能通过动态import按需加载某个语言的目录表见 src/localization/catalog-loaders/en.ts。合并时由mergeCatalogNamespaces把 14 个模块拍平为模块.键名形式的消息 ID如settings.language.selectorLabel并且重名键会直接抛错——把翻译文件冲突问题拦在构建期源码见 packages/localization/src/core/catalog.ts。locales/native/则是主进程侧的文案系统菜单、原生对话框等每种语言一个扁平 JSON例如 locales/native/zh-Hans.json。四、ICU 消息格式文案里怎么带参数 翻译文件不是死字符串而是ICU MessageFormat由intl-messageformat库解析。随便看几条英文文案就知道它的能力native.update.blocker.terminal.label: PuppyOne terminal sessions open ({count}), native.appPreview.run.command: Command: {command}格式化链路在 packages/localization/src/core/message-formatter.ts按语言 消息ID 原文三元组编译并缓存IntlMessageFormat实例避免重复编译调用format(values)填充参数参数值文件路径、分支名等动态内容还会先经过双向隔离下一节讲若 ICU 语法写错导致编译/格式化抛异常诊断信息只上报一次然后尝试英文文案最后回落到此文案不可用占位。这套编译缓存 诊断去重的设计让本地化错误在生产环境是静默降级而非白屏。五、缺失与回退三级兜底策略 ️渲染进程加载目录表时永远成对加载目标语言 英文loadRendererCatalogBundle见 src/localization/loadRendererCatalog.ts。查找顺序是目标语言目录表命中 → 用目标语言的 ICU 上下文格式化未命中 → 回落到英文目录表按英文 ICU 上下文格式化英文也没有 → 返回common.messageUnavailable本地化的此文案不可用提示同时上报missing-message诊断。如果某个语言的目录文件本身加载失败网络/文件异常整个启动流程会整体切到英文状态再启动源码见 src/localization/bootstrap.ts。宁可整屏英文也不出现中英混杂的半截翻译。六、RTL 支持为从右到左预留的完整通路 虽然当前 8 种语言全部是ltr但 RTL 支持不是摆设而是贯穿了整条链路清单层direction字段是描述符的必填项取值只能是ltr/rtl未来新增阿拉伯语或希伯来语只需加一行声明。解析层resolveLocaleState会把方向写入全局LocaleState见 packages/localization/src/core/resolve-locale.ts切换语言时应用到html dir整个界面自动镜像翻转。几何层布局代码通过directionMultiplierrtl时为-1做坐标换算例如 src/components/DesktopCloudShell.tsx 中的方向判断侧栏、抽屉等组件的动画方向和定位都会随之镜像。混合文本层这是最容易被忽视的一点。界面里会插入分支名、文件路径这类恒为 LTR 的动态内容在 RTL 语境下它们会被方向规则撕碎。PuppyOne 用bidiIsolate包裹动态值见 packages/localization/src/core/bidi.tsimport { bidiIsolate } from puppyone/localization; aria-label{t(shell.branch.title, { branch: bidiIsolate(branchLabel) })}它给文本加上 Unicode 双向隔离符U2068 / U2069让分支名在任何文字方向下都保持完整连续——目前该工具已在标题栏分支标签、工作区切换器、项目名等场景普遍使用。七、数字、日期与排序Intl 格式化器也有份 本地化不只是字符串。packages/localization/src/core/formatters.ts 按语言创建并缓存了五类Intl格式化器formatNumber数字含千分位、货币formatDate日期时间formatRelativeTime相对时间3 分钟前formatList列表连接词英语用 A, B and C其他语言语法不同排序器Collator按目标语言的规则排序切换语言后界面上的数字格式、时间表述会自动跟着变无需在业务代码里写任何 if/else。八、用户体验一键切换语言 ⚙️在设置页的语言下拉框src/features/settings/LanguageSetting.tsx中用户可以选择跟随系统或任一语言选系统时应用读取操作系统语言列表经Intl.getCanonicalLocales归一化后按精确命中 → 别名 → 语言匹配 → 文字系统匹配逐级解析packages/localization/src/core/resolve-locale.ts 的resolveSystemLocale。比如系统语言是zh-CN会通过别名命中zh-Hans。选具体语言时偏好持久化存储electron/main/localization/locale-preference-store.mjs重启后仍然生效。九、主进程 × 渲染进程本地化的双进程链路 ┌─ 主进程 (Electron) ─────────────┐ ┌─ 渲染进程 (React) ─────────────────┐ │ locale-resolver.mjs │ │ localeClient.ts / bootstrap.ts │ │ native-catalog-loader.mjs ─────┼──▶│ loadRendererCatalog.ts (动态 import)│ │ desktop-locale-service.mjs │IPC│ LocalizationProvider (React 上下文) │ └────────────────────────────────┘ └─────────────────────────────────────┘主进程electron/main/localization/locale-resolver.mjs 校验清单并解析语言electron/main/localization/native-catalog-loader.mjs 加载原生目录表本地化 IPC 见 electron/main/ipc/localization-ipc.mjs。渲染进程通过 preload 桥getLocalizationBootstrap/setLanguagePreference/onLocaleChanged获取状态浏览器环境Web 预览下自动退化为纯前端方案逻辑见 src/localization/bootstrap.ts。校验兜底仓库还配有本地化一致性检查脚本 scripts/check-localization.mjs 与架构测试 tests/architecture/localization/在 CI 中防止清单、目录文件与代码三者失同步。更完整的背景可阅读归档文档 archive/legacy-desktop-docs/architecture/desktop-localization.md。十、关键路径速查表 用途路径语言清单唯一事实来源locales/manifest.json渲染进程消息按语言/模块locales/renderer/原生菜单与对话框文案locales/native/语言解析与方向状态packages/localization/src/core/resolve-locale.tsICU 消息格式化packages/localization/src/core/message-formatter.ts双向文本隔离packages/localization/src/core/bidi.tsIntl 数字/日期格式化packages/localization/src/core/formatters.ts目录表动态加载src/localization/loadRendererCatalog.ts语言设置界面src/features/settings/LanguageSetting.tsx主进程本地化服务electron/main/localization/desktop-locale-service.mjs结语PuppyOne 的本地化架构可以用一句话概括一份清单定规则两类目录管文案ICU 管语法Intl 管格式方向字段管 RTL。对想给自家桌面应用做多语言支持的团队这套清单驱动 双进程同步 三级回退 双向隔离的做法非常值得参考——它把最棘手的边界情况翻译缺失、ICU 语法错误、混合方向文本全部收敛到了可预测的安全降级上。赞分享【免费下载链接】puppyoneContext drive for your AI agents项目地址https://gitcode.com/gh_mirrors/pu/puppyone点击查看免费下载相关推荐VitePress 国际化i18n完整指南locales 配置、多语言目录结构与 RTL 支持VitePress 国际化i18n完整指南locales 配置、多语言目录结构与 RTL 支持 VitePress 内置了完整的国际化i18n能力只前端文档前后端开发进阶指南5大开源神器助你提升全栈开发效率前后端开发进阶指南5大开源神器助你提升全栈开发效率 本文为您盘点当前最实用的前后端开发工具与框架从现代化的后台管理系统到代码编辑器深度使用、Node.js版前端企业应用认证鉴权从零玩转 scrcpy3 个阶段解锁安卓投屏的所有玩法一款免费开源神器就够了从零玩转 scrcpy3 个阶段解锁安卓投屏的所有玩法一款免费开源神器就够了 在电脑上操控手机这件事很多人的第一反应是装个投屏 App。但真正用过 s音视频创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考