OmniRoute 国际化(i18n)工程指南:30+ 语言的 UI 与文档翻译、增量管线与自动化 QA
2026/9/10 22:48:06 网站建设 项目流程

OmniRoute 国际化(i18n)工程指南:30+ 语言的 UI 与文档翻译、增量管线与自动化 QA

【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute

本指南基于 OmniRoute 仓库的 i18n 工具链文档(docs/i18n/cs/docs/guides/I18N.md 及其英文主文档 docs/guides/I18N.md),系统梳理 OmniRoute 的多语言体系:从next-intl驱动的仪表盘 UI 翻译、CLI 独立 i18n 层,到基于 LLM 与 Google Translate 的文档自动翻译管线,再到覆盖键位校验、术语一致性、视觉回归的完整 QA 工具链。读完本文,你将掌握如何为 OmniRoute 添加一门新语言、运行增量翻译、校验翻译质量,以及在 CI 中建立防漂移门禁。

快速参考:i18n 常用命令一览

任务命令
增量翻译文档(推荐,基于哈希)npm run i18n:run
仅翻译单个语言npm run i18n:run -- --locale=pt-BR
翻译指定文件npm run i18n:run -- --files=CLAUDE.md,docs/architecture/ARCHITECTURE.md
强制全量重译(昂贵)npm run i18n:run -- --force
预演(不调用 API、不写入)npm run i18n:run:dry
CI 漂移门禁npm run i18n:check
一键新增语言(配置→文档→CLI→站点)npm run i18n:add-locale -- --code=el …
翻译 UI 字符串npm run i18n:sync-ui -- --translate-markers --batch-size=40
校验单个语言环境python3 scripts/i18n/validate_translation.py quick -l cs
检查代码内键位python3 scripts/i18n/check_translations.py
生成静态 QA 报告node scripts/i18n/generate-qa-checklist.mjs
Playwright 视觉 QAnode scripts/i18n/run-visual-qa.mjs

架构概览

数据源(Source of Truth)

OmniRoute 的 i18n 体系分为三块,各有明确的唯一权威:

  • UI 字符串src/i18n/messages/en.json(英文源,约 2800 个键)
  • 语言环境文件src/i18n/messages/{locale}.json
  • 框架next-intl,基于 Cookie 的运行时语言解析
  • 语言注册表config/i18n.json—— 这是唯一声明语言的地方,定义了全部 locale、RTL 集合、别名与排除项;src/i18n/config.ts只是它的类型化适配层(源码注释明确要求"不要在此手维护语言列表")

config/i18n.json的顶层结构(config/i18n.json):

{ "$schema": "./i18n-schema.json", "default": "en", "rtl": ["ar", "fa", "he", "ur"], "uiOnly": ["en"], "docsExcluded": ["en"], "locales": [ { "code": "cs", "label": "CS", "name": "Čeština", "flag": "🇨🇿", ... } ] }

关键字段说明:

  • default:默认语言(en
  • rtl:从右向左排版的语言集合,当前为arfaheur
  • uiOnly/docsExcluded:仅 UI 使用或从文档翻译中排除的语言
  • locales[]:每个条目的codelabelnamenativeenglishflag,以及可选aliases(旧代码别名,如id声明"aliases": ["in"]zh-TW声明["zh-hk", "zh-mo", "zh-hant"]

运行时语言解析流程

仪表盘侧由src/i18n/request.ts驱动(request.ts),完整流程如下:

  1. 用户选择语言 → 写入NEXT_LOCALECookie
  2. 请求时先读NEXT_LOCALECookie,为空则读x-locale请求头,再交给resolveRequestedLocale解析
  3. 解析规则(resolveRequestedLocale.ts):精确匹配 → 大小写不敏感匹配 → 别名匹配(如inidukuk-UA)→ 回退en
  4. 动态 import 加载messages/{locale}.json
  5. 组件通过useTranslations("namespace")t("key")消费

值得注意的细节:request.ts实现了EN 兜底合并。当活跃语言不是英文时,会通过deepMergeFallback深度合并缺失键,并用__MISSING__:前缀哨兵(由scripts/i18n/sync-ui-keys.mjs写入)识别"未翻译"的占位值,从而让英文原文优先兜底(request.ts)。同时还会对新加入的命名空间做整命名空间级别的浅合并,保证新增 UI 在翻译落地前始终以英文显示。

支持的语言环境

当前仓库的 config/i18n.json 共注册 42 个语言环境(含en)。下面按文档表格结构列出全部语言、RTL 标志与 Google Translate 代码:

代码语言RTLGoogle Translate 代码
arالعربيةYesar
azAzərbaycan diliNoaz
bgБългарскиNobg
bnবাংলাNobn
csČeštinaNocs
daDanskNoda
deDeutschNode
enEnglishNoen
esEspañolNoes
faفارسیYesfa
fiSuomiNofi
frFrançaisNofr
guગુજરાતીNogu
heעבריתYesiw
hiहिन्दीNohi
huMagyarNohu
idBahasa IndonesiaNoid(别名in
itItalianoNoit
ja日本語Noja
ko한국어Noko
mrमराठीNomr
msBahasa MelayuNoms
nlNederlandsNonl
noNorskNono
phiFilipinoNotl(别名fil
plPolskiNopl
ptPortuguês (Portugal)Nopt
pt-BRPortuguês (Brasil)Nopt
roRomânăNoro
ruРусскийNoru
skSlovenčinaNosk
svSvenskaNosv
swKiswahiliNosw
taதமிழ்Nota
teతెలుగుNote
thไทยNoth
trTürkçeNotr
uk-UAУкраїнськаNouk(别名uk
urاردوYesur
viTiếng ViệtNovi
zh-CN中文 (简体)Nozh-CN
zh-TW中文 (繁體)Nozh-TW(别名zh-hk等)

注:早期版本文档(如 docs/i18n/cs/docs/guides/I18N.md)记录为 30 种语言;当前仓库的config/i18n.json已扩展至 42 个语言环境,且faur也加入了 RTL 集合。

添加一门新语言

推荐方式:一键add-locale.mjs

从当前仓库的英文主文档看,新增语言已收敛为一条命令(scripts/i18n/add-locale.mjs),会同时更新配置、国旗、仪表盘目录、文档镜像、CLI 目录、README 与索引、语言切换栏,并可选更新站点:

# 需要 .env 中配置 OMNIROUTE_TRANSLATION_API_URL / _API_KEY / _MODEL node scripts/i18n/add-locale.mjs --code=el --english=Greek --native=Ελληνικά --flag=🇬🇷 # 印度语言共用 in.svg 国旗文件 node scripts/i18n/add-locale.mjs --code=kn --english=Kannada --native=ಕನ್ನಡ --flag=🇮🇳 --flag-file=in.svg # 仅预演,不写入 node scripts/i18n/add-locale.mjs --code=el --english=Greek --native=Ελληνικά --flag=🇬🇷 --dry-run

新增后执行校验:

node --import tsx/esm --test tests/unit/i18n-locale-surfaces-parity.test.ts npm run i18n:check-ui-coverage && npm run i18n:check-ratio && npm run check:docs-all && npm run check:cli-i18n

对应的单元测试 tests/unit/i18n-locale-surfaces-parity.test.ts 双向守护"语言表面一致性":配置中声明的文档语言必须有一行索引记录,索引中的每一行必须能映射回配置。

传统手动步骤(旧流程,理解用)

早期文档记录的手动流程(在generate-multilang.mjs时代)包含以下步骤,仍可作为理解内部机制参考:

  1. 注册语言:在src/i18n/config.tsLOCALES数组添加"xx",在LANGUAGES数组添加{ code: "xx", label: "XX", name: "Language Name", flag: "🏳️" }
  2. 加入生成器:在scripts/i18n/generate-multilang.mjsLOCALE_SPECS添加条目(含codegoogleTllabelflaglanguageNamereadmeNamedocsName
  3. 生成初始翻译node scripts/i18n/generate-multilang.mjs messages,从en.json经 Google Translate 生成src/i18n/messages/xx.json
  4. 人工复核:自动翻译只是起点,重点检查技术准确性、语境术语、占位符({count}{value}等)是否妥善处理
  5. 校验python3 scripts/i18n/validate_translation.py quick -l xxpython3 scripts/i18n/validate_translation.py diff common -l xx
  6. 生成翻译文档node scripts/i18n/generate-multilang.mjs docs

重要提醒:generate-multilang.mjs(Google Translate 引擎)在 docs/guides/I18N.md 中已被标记为弃用(计划 v3.10 移除),新流程一律走基于 LLM 的npm run i18n:run。仅readme模式(根 README 多语言变体)暂时没有替代方案。

自动翻译管线

推荐管线:run-translation.mjs(哈希驱动的增量翻译)

当前主推的是 scripts/i18n/run-translation.mjs,它对文档做增量、确定性翻译,背后是任意 OpenAI 兼容的 LLM 端点(典型如 OmniRoute Cloud 的cx/gpt-5.4-mini):

# 增量运行——只动有变化的源文件 npm run i18n:run # 限定单一语言 npm run i18n:run -- --locale=pt-BR # 指定文件(仓库相对路径,逗号分隔) npm run i18n:run -- --files=CLAUDE.md,docs/architecture/ARCHITECTURE.md # 强制全量重译 npm run i18n:run -- --force # 预演 npm run i18n:run:dry # CI 门禁——状态漂移时以非零码退出 npm run i18n:check

状态重建(re-bootstrap)npm run i18n:run -- --adopt可从磁盘上已有的镜像重建.i18n-state.json,全程不调用 API、不写任何.md。适用于"源文件改动但无需重译"(如链接列表、计数)或状态文件丢失的场景;可用--files=…/--locale=…限定子集,加--dry-run预演。--adopt --targets-only则只重新哈希磁盘上的镜像文件,保留全部source_hash,让机械性的镜像重写不再被误报为目标漂移。

后端配置(run-translation.mjs 与 docs/guides/I18N.md 中的环境变量表):

环境变量用途默认值
OMNIROUTE_TRANSLATION_API_URLOpenAI 兼容 base URL(如…/v1必填
OMNIROUTE_TRANSLATION_API_KEYBearer token(不写入日志)必填
OMNIROUTE_TRANSLATION_MODEL模型 ID,如cx/gpt-5.4-mini必填
OMNIROUTE_TRANSLATION_TIMEOUT_MS单请求超时60000
OMNIROUTE_TRANSLATION_CONCURRENCY并发请求数4

脚本内置轻量.env加载器(不依赖 dotenv),已设置的进程环境变量优先。调用 LLM 时使用temperature: 0.15、非流式/chat/completions,对 408/429/5xx 与超时/网络错误各重试一次。

状态跟踪.i18n-state.json(已提交)按"源文件 + 每个语言"记录 SHA-256 哈希。i18n:check(check-translation-drift.mjs)只做状态与磁盘的确定性对比,不调用任何 API,严格模式任一漂移即退出码 1,可加--warn(仅告警,退出 0)或--json(机器可读报告)。

输出形态:每个翻译文件生成顶部# <heading>(<native>)🌐 Languages: …语言栏、---分隔线,再跟翻译正文——这与 scripts/check/check-docs-sync.mjs 对llm.txtCHANGELOG.md镜像的校验规则完全一致。翻译前先用 Prettier 的 markdown 解析器格式化,保证落盘内容与 lint-staged 产物一致,避免哈希漂移。

其他内部机制(可从 run-translation.mjs 源码验证):

  • 分块:正文超过 6000 字符时按顶层##标题拆块,逐块翻译再以空行拼接
  • 术语归一:译文产出后调用normalizeLocaleText(glossary-normalize.mjs)按语言环境的规范术语表做后处理,修正模型"会转字不会转词"的问题(如 zh-TW 输出被大陆用词污染)
  • 系统提示词:要求保留所有 Markdown 语法、不翻译源码/URL/路径/命令/环境变量名,只输出译文本身

遗留引擎一:generate-multilang.mjs(Google Translate)

主自动翻译引擎(已弃用)——使用 Google Translate 免费 API 生成 UI 字符串、README 与文档翻译:

node scripts/i18n/generate-multilang.mjs [messages|readme|docs|all]
模式行为
messagesen.json翻译src/i18n/messages/{locale}.json中缺失的键
readmeREADME.md翻译为根目录的README.{code}.md
docsDOC_SOURCE_FILES翻译到docs/i18n/{locale}/{docName}
all依次执行以上三种模式

实现特性:

  • 文本保护:翻译前遮蔽代码块、行内代码、Markdown 链接/图片(text)、HTML 标签、表格与 ICU 占位符({count}{value}{total}等),翻译后还原
  • 分块批处理:用__OMNIROUTE_I18N_SEPARATOR__分隔符拼接多条字符串以减少 API 调用(单请求上限 1800 字符)
  • 内存缓存:会话内重复字符串不重复调用
  • 重试逻辑:对 429/5xx 指数退避,最多 5 次(300ms × 尝试序号)
  • 超时:单请求 20 秒
  • 跳过已有文件:目标文件已存在则不覆盖

需要注意的行为:docs/i18n/README.md每次运行会被整体重新生成(它是自动生成的语言索引);根目录README.{code}.md仅在不存在时创建(跳过EXISTING_README_CODES中已有的语言);语言栏(🌐 **Languages:** ...)会自动插入/更新到所有翻译文档。

遗留引擎二:i18n_autotranslate.py(LLM 文档翻译)

次级翻译器(已弃用)——使用任意 OpenAI 兼容 LLM API(包括 OmniRoute 自身)翻译docs/i18n/下的 Markdown 文件,质量优于 Google Translate,适合润色或重译:

python3 scripts/i18n/i18n_autotranslate.py \ --api-url http://localhost:20128/v1 \ --api-key sk-your-key \ --model gpt-4o

特性:扫描docs/i18n/中的英文段落;跳过代码块、表格与已翻译内容;以技术翻译系统提示词驱动;支持全部语言。

CLI 的独立 i18n 层

除 Next.js 仪表盘外,omnirouteCLI 拥有独立的 i18n 层(bin/cli/i18n.mjs、bin/cli/locales/),与仪表盘共享config/i18n.json作为语言权威:

  • 所有用户可见字符串经t("module.key", vars)输出
  • 目录文件随包发布 42 个语言环境
  • 任何缺失键回退到en,因此部分翻译也是合法的

语言选择优先级

优先级来源示例
1--lang参数omniroute --lang de status
2OMNIROUTE_LANG环境变量OMNIROUTE_LANG=ja omniroute providers
3LC_ALL系统环境按终端语言自动检测
4LC_MESSAGES系统环境按终端语言自动检测
5LANG系统环境按终端语言自动检测
6回退en

下划线形式(pt_BR)会被规范化为连字符形式(pt-BR);语言代码用/^[a-zA-Z0-9-]+$/校验,拒绝路径穿越

持久化语言偏好与一次性覆盖

# 设置语言并保存到 ~/.omniroute/.env(跨会话持久) omniroute config lang set pt-BR # 查看当前语言 omniroute config lang get # 列出全部可用语言 omniroute config lang list omniroute config lang list --output json # 仅当前命令生效的一次性覆盖(不写环境文件) omniroute --lang de providers list

偏好以原子方式写入~/.omniroute/.env,CLI 引导阶段在任何命令运行前加载。新增 CLI 语言环境的流程为:在config/i18n.json添加条目 → 运行node bin/cli/scripts/generate-locales.mjs生成语言文件 → 翻译键(或留空{}走 en 兜底脚手架)→ PR 至少保证en.jsonpt-BR.json的字符串齐全。

验证与 QA 工具链

validate_translation.py:翻译校验器

将任意语言环境 JSON 与en.json对比并报告问题:

# 快速检查(仅计数) python3 scripts/i18n/validate_translation.py quick -l cs # 输出示例: # Missing: 0 # Untranslated: 0 # Ignored (UNTRANSLATABLE_KEYS): 236 # 按类别查看详细差异 python3 scripts/i18n/validate_translation.py diff common -l cs python3 scripts/i18n/validate_translation.py diff settings -l cs # 导出 CSV python3 scripts/i18n/validate_translation.py csv -l cs > report.csv # 导出 Markdown python3 scripts/i18n/validate_translation.py md -l cs > report.md # 完整报告(默认) python3 scripts/i18n/validate_translation.py -l cs

检测四类问题:

  • 缺失键:存在于en.json但不在语言文件中
  • 多余键:存在于语言文件但不在en.json
  • 未翻译键:语言文件值与英文源相同(排除 allowlist)
  • 占位符不匹配:ICU 占位符在源与译文之间不一致

退出码约定

退出码含义
0正常
1通用错误
2缺失字符串(硬错误)
3未翻译警告(软性)

环境变量:设置TRANSLATION_LANG=cs或使用-l cs参数。

check_translations.py:代码到 JSON 的键位检查

扫描src/**/*.tsxsrc/**/*.ts中的useTranslations()调用,验证所有引用的键都存在于en.json

python3 scripts/i18n/check_translations.py # 基本检查 python3 scripts/i18n/check_translations.py --verbose # 详细输出 python3 scripts/i18n/check_translations.py --fix # 自动补缺失键到 en.json

generate-qa-checklist.mjs:静态分析 QA

扫描 Next.js 页面文件,输出 i18n 风险度量的 Markdown 报告:

node scripts/i18n/generate-qa-checklist.mjs

检查项:固定宽度 class 使用(溢出风险)、方向性 left/right class(RTL 风险)、易裁剪模式、与en.json的语言对齐(缺失/多余键)、重点语言(esfrdejaar)README 的语言选择栏。输出到docs/reports/i18n-qa-checklist-{date}.md

run-visual-qa.mjs:Playwright 视觉回归

对多个语言与视口下的全部仪表盘路由截图并评估页面健康:

# 默认:es, fr, de, ja, ar(英文主文档当前含 zh-CN)@ localhost:20128 node scripts/i18n/run-visual-qa.mjs # 自定义 base URL 与语言 QA_BASE_URL=http://staging.example.com QA_LOCALES=de,fr node scripts/i18n/run-visual-qa.mjs # 自定义路由 QA_ROUTES=/dashboard/settings,/dashboard/providers node scripts/i18n/run-visual-qa.mjs

检测:文本溢出、元素裁剪、RTL 布局错位。输出docs/reports/i18n-visual-qa-{date}.md及 JSON 报告。

术语表:超越键位对齐的语义一致性

键位对齐(check-ui-keys-coverage.mjs)与 ICU 合法性(validate_translation.py)无法发现语义漂移——例如同一个英文概念 "provider" 在中文里被分别译成"提供商"与"提供者"。仓库由此增加了按语言维护的术语层(docs/guides/I18N.md 中的 Terminology Glossary 章节,源自 issue #8038,从 zh-CN 起步)。

术语表文件

  • scripts/i18n/glossary/zh-CN.json(另有 zh-TW、ko):版本化的常见概念表(provider、connection、routing、fallback、quota、context window、reasoning、tool call、cache、circuit breaker 等)。每个概念有canonical规范译法与可选synonyms列表;目录中发现任何同义词即标记为漂移。synonyms为空数组表示"已记录但暂不强制"(目录中仍存在合法混用,规范化是后续工作)
  • scripts/i18n/glossary/protected-terms.json:产品/厂商/模型/协议/CLI/环境变量/标识符名称(OmniRouteOAuthMCPA2ADATA_DIR等)必须原样出现在任何译文值中。它按概念(concept)而非键路径(key path)检查,粒度与untranslatable-keys.json(整键排除)不同

校验入口

# 默认 zh-CN npm run i18n:check-glossary # 指定语言、JSON 报告或非失败报告模式 node scripts/i18n/check-glossary-consistency.mjs --locale=zh-CN node scripts/i18n/check-glossary-consistency.mjs --locale=zh-CN --json node scripts/i18n/check-glossary-consistency.mjs --locale=zh-CN --report

核心函数checkGlossaryConsistency(localeMessages, glossary, protectedTerms)返回{ violations: [...] }:非规范术语产生glossary-synonym违规,被改写的受保护名称产生protected-term-altered违规。已接入 CI 的i18n-glossary-zhcn作业(.github/workflows/ci.yml)。

管理不可翻译键(untranslatable-keys.json)

文件位置:scripts/i18n/untranslatable-keys.json(当前约 236 个键)。

允许保持与英文源完全一致的键名单,用于避免validate_translation.py产生"未翻译"的误报:

{ "description": "Keys that should remain untranslated...", "keys": [ "common.model", "common.oauth", "health.cpu" ] }

适合放入此名单的键类型:

  • 品牌/产品名:landing.brandNamecommon.social-github
  • 技术术语/缩写:health.cpumcpDashboard.pidsettings.ai
  • ICU/格式化字符串:apiManager.modelsCounthealth.millisecondsShort
  • 占位符值:providers.openaiBaseUrlPlaceholdercliTools.baseUrlPlaceholder
  • 协议名:common.httpcommon.oauthproviders.oauth2Label
  • 导航分区:sidebar.primarySectionsidebar.cliSection

新增键只需编辑keys数组并重新运行校验。历史上这份名单从validate_translation.py内联的 Python set 迁移到外部 JSON 文件,便于维护,校验器在运行时加载。

CI 集成

CI 流水线(.github/workflows/ci.yml)在每次 push 与 PR 上守护全部语言:

  1. i18n-matrix作业:动态发现全部语言文件(排除en.json
  2. i18n作业:对每个语言并行运行validate_translation.py quick -l '<lang>'
  3. ci-summary作业:汇总结果到流水线摘要
# i18n-matrix:发现语言 LANGS=$(ls src/i18n/messages/*.json | xargs -n1 basename | sed 's/.json$//' | grep -v '^en$') # i18n:校验每种语言 python3 scripts/i18n/validate_translation.py quick -l '${{ matrix.lang }}'

摘要输出示例:

## 🌍 Translations | Metric | Value | |--------|------| | Languages checked | 30 | | Total untranslated | 0 | ✅ All translations complete

此外还有多条专职 i18n 作业(见 .github/workflows/ci.yml):i18n-ui-coverage(键位覆盖率,阈值 65,跳过草稿 PR)、i18n-glossary-zhcn(术语表)、i18n-translation-ratio(真实翻译占比/占位符比例棘轮)、check-ui-value-drift(陈旧翻译)、check-translation-drift(文档漂移,当前以--warn运行)、CLI i18n 一致性(npm run check:cli-i18n,硬门禁)。

文件结构

config/ └── i18n.json # 唯一语言权威(42 locales、RTL 集、别名、排除项) src/i18n/ ├── config.ts # 语言定义的薄类型化适配层 ├── request.ts # 运行时语言解析(Cookie → 请求头 → en 兜底) ├── resolveRequestedLocale.ts # 无依赖的 locale 解析(含别名) └── messages/ ├── en.json # 英文源(~2800 键) ├── cs.json # 捷克语翻译 ├── de.json # 德语翻译 └── ... # 42 个语言文件 scripts/i18n/ ├── run-translation.mjs # 推荐:哈希增量文档翻译(LLM 后端) ├── check-translation-drift.mjs # 漂移检查(CI 门禁,无 API) ├── add-locale.mjs # 一键新增语言 ├── sync-ui-keys.mjs # UI 键位回填/翻译 ├── check-ui-keys-coverage.mjs # UI 键位覆盖率 ├── check-ui-value-drift.mjs # UI 值漂移 ├── check-translation-ratio.mjs # 真实翻译占比 ├── check-glossary-consistency.mjs # 术语表一致性 ├── glossary/ # zh-CN/zh-TW/ko 术语表 + protected-terms.json ├── generate-multilang.mjs # 弃用:Google Translate 自动翻译 ├── i18n_autotranslate.py # 弃用:LLM 文档翻译器 ├── generate-qa-checklist.mjs # 静态分析 QA ├── run-visual-qa.mjs # Playwright 视觉 QA ├── untranslatable-keys.json # 校验用 allowlist ├── validate_translation.py # 翻译校验器 └── check_translations.py # 代码到 JSON 键位检查 bin/cli/ ├── i18n.mjs # CLI 翻译层 └── locales/ # 42 个 CLI 语言目录 docs/ ├── guides/I18N.md # 本文英文主文档(手写维护) ├── i18n/ # 自动生成的翻译文档镜像(每语言一份) │ ├── README.md # 自动生成的语言索引 │ └── cs/docs/guides/I18N.md # 本文的捷克语版本 └── reports/ # QA 报告 ├── i18n-qa-checklist-*.md └── i18n-visual-qa-*.md .i18n-state.json # 提交的翻译状态(源/目标哈希)

最佳实践

编辑翻译时的守则

  1. 永远先改en.json——它是唯一权威
  2. 运行npm run i18n:sync-ui -- --translate-markers --batch-size=40把新键传播到各语言(旧流程为generate-multilang.mjs messages
  3. 人工复核自动翻译——自动引擎只是起点而非终点
  4. 提交前校验:python3 scripts/i18n/validate_translation.py quick -l <lang>
  5. 若某键应保持英文,更新untranslatable-keys.json

占位符安全

  • ICU 占位符({count}{value}{total}{seconds})必须逐字保留
  • 复数格式({count, plural, one {# model} other {# models}})必须保持结构
  • 校验器会自动检测占位符不匹配

在代码中新增翻译键

// 使用命名空间键 const t = useTranslations("settings"); t("cacheSettings"); // 映射到 JSON 中的 settings.cacheSettings // 运行 check_translations.py 验证键存在 python3 scripts/i18n/check_translations.py --verbose

RTL 注意事项

  • 阿拉伯语(ar)、希伯来语(he),以及当前配置中的波斯语(fa)、乌尔都语(ur)是 RTL 语言
  • 避免硬编码left/rightCSS——使用start/end逻辑属性
  • 视觉 QA(run-visual-qa.mjs)负责捕获 RTL 布局错位

已知问题与历史

in.jsonhi.json修复

生成器最初为印地语使用code: "in"(已弃用的 Google Translate 代码)而非正确的 ISO 639-1hi,产生了孤立的in.json重复文件。已通过把generate-multilang.mjscode: "in"改为code: "hi"并删除孤立文件修复。

遗留in语言的退役(2026-09-02)

in在该修复后以第二个印尼语语言的身份延续了一段时期——config/i18n.json称之为 "Indonesian (Legacy)",而 README 仍标注为印地语。现已从所有表面(配置、目录、docs/i18n/in/、README、索引、基线)移除。id现在声明"aliases": ["in"],因此已保存的NEXT_LOCALE=inOMNIROUTE_LANG=in会自动解析到id(实现见 resolveRequestedLocale.ts)。

docs/i18n/README.md改为手写维护

它过去被generate-multilang.mjs docs整体重新生成,现在不再如此:npm run i18n:add-locale会就地插入新语言的索引行(并更新计数句),其余编辑均手动完成。tests/unit/i18n-locale-surfaces-parity.test.ts双向守护这一约束。

validate_translation.py的忽略计数输出

quick检查现在显示来自untranslatable-keys.json的忽略键数量:

Missing: 0 Untranslated: 0 Ignored (UNTRANSLATABLE_KEYS): <varies per release>

架构示意图

上图为 i18n 管线的总体流程(源码:docs/diagrams/i18n-flow.mmd):从config/i18n.json的语言注册、en.json源字符串,到 LLM 增量翻译、.i18n-state.json状态跟踪,最终产出docs/i18n/{locale}/文档镜像与src/i18n/messages/{locale}.jsonUI 目录,并由 CI 中的校验与 QA 作业闭环守护。

总结

OmniRoute 的 i18n 体系是一个"单一权威 + 双翻译引擎 + 多层校验门禁"的完整工程:config/i18n.json统一声明 42 个语言环境;仪表盘侧next-intl提供 Cookie 级语言解析与 EN 兜底,CLI 侧有独立的--lang/OMNIROUTE_LANG选择链路;文档翻译以哈希驱动的npm run i18n:run增量管线为主,旧 Google Translate 引擎保留但弃用;质量保障由键位校验、术语表一致性、静态 QA、Playwright 视觉回归与 CI 矩阵共同构成。对于任何需要长期维护多语言、多端(Web + CLI)界面的团队,这套"以英文为唯一源、自动化翻译打底、确定性校验兜底"的实践都极具参考价值。

【免费下载链接】OmniRouteNever stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors项目地址: https://gitcode.com/GitHub_Trending/om/OmniRoute

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

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

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

立即咨询