跳到內容
OmniRoute source

i18n — 國際化指南

OmniRoute 支援 42 種語言,包含完整的儀表板 UI 翻譯、翻譯文件,以及阿拉伯語和希伯來語的 RTL(從右至左)支援。

OmniRoute 使用基於雜湊的增量翻譯器來處理說明文件,後端採用與 OpenAI 相容的 LLM 端點(通常是透過 OmniRoute Cloud 的 cx/gpt-5.4-mini):

Terminal window
# 執行翻譯(增量模式 — 僅處理有變更的來源)
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

唯一真相來源。 config/i18n.json 列出了每個語系(UI + 文件),以及 RTL 集合和 docsExcluded 代碼。執行時期設定檔 src/i18n/config.ts 是該 JSON 的輕量轉接層。

後端。 透過環境變數設定(在 .env 中設定,切勿提交):

變數 用途
OMNIROUTE_TRANSLATION_API_URL 與 OpenAI 相容的基礎 URL,例如 …/v1
OMNIROUTE_TRANSLATION_API_KEY Bearer 令牌(不會記錄在日誌中)
OMNIROUTE_TRANSLATION_MODEL 模型 ID,例如 cx/gpt-5.4-mini
OMNIROUTE_TRANSLATION_TIMEOUT_MS 選用,預設 60000
OMNIROUTE_TRANSLATION_CONCURRENCY 選用,預設 4

狀態追蹤。 .i18n-state.json(已提交)會為每個來源 + 每個語系保留 SHA-256 雜湊值。漂移偵測是自動且確定性的 — i18n:check 不需要 API 呼叫。

輸出格式。 每個翻譯後的檔案會在最上方加入 # <標題>(<語言>) 行、🌐 語言:… 列、--- 分隔線,以及翻譯後的正文。此佈局與 scripts/check/check-docs-sync.mjs 已對 llm.txt 和 CHANGELOG.md 鏡像強制執行的格式一致。

較舊的 Python 腳本(scripts/i18n/i18n_autotranslate.py)和基於 Google 翻譯的產生器(scripts/i18n/generate-multilang.mjs)仍然存在,但附有棄用橫幅。它們將在 v3.10 中移除。generate-multilang.mjs 的 messages 和 readme 模式(UI 字串 + 根目錄 README 變體)尚未由新管線處理,目前仍在使用中。

任務 指令
翻譯文件(LLM) npm run i18n:run(建議使用 — 增量、基於雜湊)
翻譯 UI 字串 node scripts/i18n/generate-multilang.mjs messages
檢查翻譯漂移 npm run i18n:check
驗證語系 python3 scripts/i18n/validate_translation.py quick -l cs
檢查程式碼按鍵 python3 scripts/i18n/check_translations.py
產生 QA 報告 node scripts/i18n/generate-qa-checklist.mjs
視覺 QA(Playwright) node scripts/i18n/run-visual-qa.mjs

增量式基於雜湊的 i18n 管線

來源:diagrams/i18n-flow.mmd

  • UI 字串:src/i18n/messages/en.json(英文來源,約 2800 個按鍵)
  • 語系檔案:src/i18n/messages/{locale}.json(30 種翻譯)
  • 框架:next-intl,搭配基於 Cookie 的語系解析
  • 設定:src/i18n/config.ts — 定義全部 30 個語系、語言名稱、旗標
  1. 使用者選擇語言 → 設定 NEXT_LOCALE Cookie
  2. src/i18n/request.ts 解析語系:Cookie → Accept-Language 標頭 → 備用 en
  3. 動態匯入載入 messages/{locale}.json
  4. 元件使用 useTranslations("namespace") 和 t("key")
代碼 語言 RTL Google 翻譯代碼
ar العربية 是 ar
bg Български 否 bg
cs Čeština 否 cs
da Dansk 否 da
de Deutsch 否 de
es Español 否 es
fi Suomi 否 fi
fr Français 否 fr
he עברית 是 iw
hi हिन्दी 否 hi
hu Magyar 否 hu
id Bahasa Indonesia 否 id
it Italiano 否 it
ja 日本語 否 ja
ko 한국어 否 ko
ms Bahasa Melayu 否 ms
nl Nederlands 否 nl
no Norsk 否 no
phi Filipino 否 tl
pl Polski 否 pl
pt Português (Portugal) 否 pt
pt-BR Português (Brasil) 否 pt
ro Română 否 ro
ru Русский 否 ru
sk Slovenčina 否 sk
sv Svenska 否 sv
th ไทย 否 th
tr Türkçe 否 tr
uk-UA Українська 否 uk
vi Tiếng Việt 否 vi
zh-CN 中文 (简体) 否 zh-CN
zh-TW 中文 (繁體) 否 zh-TW

編輯 src/i18n/config.ts:

// 新增至 LOCALES 陣列
"xx",
// 新增至 LANGUAGES 陣列
{ code: "xx", label: "XX", name: "Language Name", flag: "🏳️" },

編輯 scripts/i18n/generate-multilang.mjs — 在 LOCALE_SPECS 中新增項目:

{
code: "xx",
googleTl: "xx",
label: "XX",
flag: "🏳️",
languageName: "Language Name",
readmeName: "Language Name",
docsName: "Language Name",
},
Terminal window
node scripts/i18n/generate-multilang.mjs messages

這會從 en.json 透過 Google 翻譯自動翻譯,建立 src/i18n/messages/xx.json。

自動翻譯僅是起點。請手動檢查以下項目:

  • 技術準確性
  • 符合語境的術語用法
  • 佔位符號({count}、{value} 等)的正確處理
Terminal window
python3 scripts/i18n/validate_translation.py quick -l xx
python3 scripts/i18n/validate_translation.py diff common -l xx
Terminal window
node scripts/i18n/generate-multilang.mjs docs

主要自動翻譯引擎 — 使用 Google 翻譯免費 API 為 UI 字串、README 和說明文件產生翻譯。

Terminal window
node scripts/i18n/generate-multilang.mjs [messages|readme|docs|all]
模式 功能說明
messages 從 en.json 翻譯 src/i18n/messages/{locale}.json 中遺漏的按鍵
readme 將 README.md 翻譯為專案根目錄下的 README.{code}.md 所有語系版本
docs 將 DOC_SOURCE_FILES 翻譯為 docs/i18n/{locale}/{docName}
all 執行上述三種模式

功能特色:

  • 文字保護:在翻譯前遮罩程式碼區塊(```)、行內程式碼(`)、Markdown 連結/圖片([text](url))、HTML 標籤、表格和 ICU 佔位符號({count}、{value}、{total} 等),翻譯後再還原
  • 分塊批次處理:使用 __OMNIROUTE_I18N_SEPARATOR__ 分隔符號將多個字串連接起來,以減少 API 呼叫次數(每個請求最多 1800 字元)
  • 記憶體快取:避免在單一工作階段內對重複字串進行多餘的 API 呼叫
  • 重試邏輯:針對 429/5xx 錯誤採用指數退避(最多 5 次嘗試,延遲時間為 300ms × 嘗試次數)
  • 超時:每個請求 20 秒
  • 略過現有檔案:若目標檔案已存在,則不會覆寫

重要行為:

  • docs/i18n/README.md 每次執行時都會重新產生 — 這是所有說明的自動產生索引
  • 根目錄的 README.{code}.md 僅在不存在時才會建立(略過 EXISTING_README_CODES 中的語系)
  • 語言列(🌐 **語言:** ...)會自動插入/更新至所有翻譯文件中

次要翻譯器 — 使用任何與 OpenAI 相容的 LLM API(包括 OmniRoute 本身)來翻譯現有的 docs/i18n/ Markdown 檔案。最適合用於潤飾或重新翻譯文件,品質優於 Google 翻譯。

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

功能特色:

  • 掃描 docs/i18n/ 中的 Markdown 檔案以取得英文段落
  • 略過程式碼區塊、表格和已翻譯的內容
  • 將段落發送給 LLM,並附帶技術翻譯系統提示
  • 支援全部 42 種語言

omniroute CLI 有獨立於 Next.js 儀表板之外的 i18n 層。

  • CLI 指令中所有使用者可見的字串均透過 t("module.key", vars)(來自 bin/cli/i18n.mjs)處理
  • 語系目錄是 bin/cli/locales/ 中的 JSON 檔案 — 內建 42 種語言
  • 任何遺漏的按鍵都會自動回退到 en,因此部分翻譯仍然有效
  • 可用語系的唯一真相來源是 config/i18n.json(與儀表板共用)

偵測順序(第一個符合者優先):

優先順序 來源 範例
1 --lang 旗標 omniroute --lang de status
2 OMNIROUTE_LANG 環境變數 OMNIROUTE_LANG=ja omniroute providers
3 LC_ALL 系統環境變數 自動從終端機語系偵測
4 LC_MESSAGES 系統環境變數 自動從終端機語系偵測
5 LANG 系統環境變數 自動從終端機語系偵測
6 備用 en

底線形式的語系代碼(pt_BR)會標準化為連字號形式(pt-BR)。 語系代碼會經由 /^[a-zA-Z0-9-]+$/ 驗證 — 拒絕路徑遍歷攻擊。

Terminal window
# 設定語言並儲存至 ~/.omniroute/.env(跨工作階段持續有效)
omniroute config lang set pt-BR
# 檢視目前語言
omniroute config lang get
# 列出全部 42 種可用語言
omniroute config lang list
# JSON 輸出
omniroute config lang list --output json

儲存的偏好設定會以原子方式寫入 ~/.omniroute/.env,並在 CLI 啟動時、任何指令執行前載入。

Terminal window
# 僅為單一指令覆寫(不持續保留)
omniroute --lang de providers list

注意:--lang 旗標不會寫入環境變數檔案 — 它僅影響當次呼叫。請使用 config lang set 來持續保留設定。

bin/cli/locales/ 中內建 42 個語系檔案。完整翻譯:en、pt-BR。 僅有骨架(所有按鍵回退至 en):bn、gu、he、in、mr、ms、phi、sw、ta、te、ur。 其他 29 個語系均包含 common + program 按鍵的翻譯。

  1. 在 config/i18n.json 中新增語系項目。
  2. 執行 node bin/cli/scripts/generate-locales.mjs — 建立語系檔案。
  3. 翻譯按鍵(或保留為 {} 以使用 en 回退骨架)。
  4. PR 必須將字串新增至 en.json 和 pt-BR.json;其他檔案則盡力而為。

翻譯驗證器 — 將任何語系 JSON 與 en.json 進行比較,並回報問題。

Terminal window
# 快速檢查(僅計數)
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 中沒有的按鍵
  • 未翻譯的按鍵 — 語系值與英文來源相同的按鍵(排除允許清單)
  • 佔位符號不匹配 — 來源與翻譯之間 ICU 佔位符號不一致

結束代碼:

代碼 含義
0 正常
1 一般錯誤
2 遺漏字串(嚴重錯誤)
3 未翻譯警告(軟性錯誤)

環境: 設定 TRANSLATION_LANG=cs 或使用 -l cs 旗標。

程式碼對 JSON 按鍵檢查器 — 掃描 src/**/*.tsx 和 src/**/*.ts 中的 useTranslations() 呼叫,並驗證所有被參考的按鍵都存在於 en.json 中。

Terminal window
# 基本檢查
python3 scripts/i18n/check_translations.py
# 詳細輸出
python3 scripts/i18n/check_translations.py --verbose
# 自動修正(將遺漏的按鍵新增至 en.json)
python3 scripts/i18n/check_translations.py --fix

靜態分析 QA — 掃描 Next.js 頁面檔案中與 i18n 相關的風險指標,並產生 Markdown 報告。

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

檢查項目:

  • 固定寬度類別的使用(溢位風險)
  • 方向性 left/right 類別(RTL 風險)
  • 易裁剪的模式
  • 語系一致性(與 en.json 相比遺漏/多餘的按鍵)
  • 優先語系(es、fr、de、ja、ar)的 README 語言選擇器列

輸出: docs/reports/i18n-qa-checklist-{date}.md

透過 Playwright 進行視覺 QA — 在多個語系和檢視區間對所有儀表板路由進行螢幕截圖,然後評估頁面健康狀況。

Terminal window
# 預設:在 localhost:20128 上使用 es、fr、de、ja、ar
node scripts/i18n/run-visual-qa.mjs
# 自訂基礎 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 報告

檔案: scripts/i18n/untranslatable-keys.json

允許清單,列出應與英文來源保持一致的按鍵。由 validate_translation.py 用來避免「未翻譯」的誤報警告。

{
"description": "應保持不翻譯的按鍵…",
"keys": [
"common.model",
"common.oauth",
"health.cpu",
…
]
}

應歸類於此的項目:

  • 品牌/產品名稱:landing.brandName、common.social-github
  • 技術術語/縮寫:health.cpu、mcpDashboard.pid、settings.ai
  • ICU/格式字串:apiManager.modelsCount、health.millisecondsShort
  • 佔位符號值:providers.openaiBaseUrlPlaceholder、cliTools.baseUrlPlaceholder
  • 協定名稱:common.http、common.oauth、providers.oauth2Label
  • 導航區段:sidebar.primarySection、sidebar.cliSection

若要新增按鍵: 編輯 scripts/i18n/untranslatable-keys.json 中的 keys 陣列,然後重新執行驗證。

GitHub Actions(.github/workflows/ci.yml)

Section titled “GitHub Actions(.github/workflows/ci.yml)”

CI 管線會在每次推送和 PR 時驗證所有語系:

  1. i18n-matrix 任務 — 動態發現所有語系檔案(排除 en.json)
  2. i18n 任務 — 對每個語系平行執行 validate_translation.py quick -l '&lt;lang&gt;'
  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 }}'

儀表板輸出:

## 🌍 翻譯
| 指標 | 數值 |
|--------|------|
| 已檢查語言數 | 30 |
| 未翻譯總數 | 0 |
✅ 所有翻譯皆完整
src/i18n/
├── config.ts # 語系定義(30 個語系、RTL 設定)
├── request.ts # 執行時期語系解析
└── messages/
├── en.json # 唯一真相來源(約 2800 個按鍵)
├── cs.json # 捷克文翻譯
├── de.json # 德文翻譯
└── ... # 共 30 個語系檔案
scripts/
├── i18n/
│ ├── generate-multilang.mjs # 自動翻譯引擎(Google 翻譯,888 行)
│ ├── generate-qa-checklist.mjs # 靜態分析 QA
│ ├── run-visual-qa.mjs # Playwright 視覺 QA
│ └── untranslatable-keys.json # 驗證允許清單(236 個按鍵)
├── validate_translation.py # 翻譯驗證器
├── check_translations.py # 程式碼對 JSON 按鍵檢查器
└── i18n_autotranslate.py # 基於 LLM 的文件翻譯器
.github/workflows/
└── ci.yml # CI 矩陣中的 i18n 驗證
docs/
├── I18N.md # 本檔案 — i18n 工具鏈文件
├── i18n/
│ ├── README.md # 自動產生的語言索引
│ ├── cs/ # 捷克文文件
│ │ └── docs/
│ │ ├── I18N.md # 本檔案的捷克文翻譯
│ │ └── ...
│ ├── de/ # 德文文件
│ └── ... # 30 個語系目錄
└── reports/
├── i18n-qa-checklist-*.md # 靜態分析報告
└── i18n-visual-qa-*.md # 視覺 QA 報告
  1. 始終先編輯 en.json — 這是唯一真相來源
  2. 執行 generate-multilang.mjs messages 以將新按鍵傳播至所有語系
  3. 審查自動翻譯 — Google 翻譯是起點,而非終點
  4. 提交前先驗證 — python3 scripts/i18n/validate_translation.py quick -l &lt;lang&gt;
  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
  • 阿拉伯語(ar)和希伯來語(he)是 RTL 語系
  • 避免硬編碼 left/right CSS — 使用 start/end 邏輯屬性
  • 視覺 QA 透過 run-visual-qa.mjs 捕捉 RTL 佈局不一致

產生器原本使用 code: "in"(已棄用的 Google 翻譯代碼)來表示印度語,而不是正確的 ISO 639-1 hi。這建立了一個孤立的 in.json 檔案作為 hi.json 的重複。修正方式為將 generate-multilang.mjs 中的 code: "in" 改為 code: "hi",並移除孤立的檔案。

⚠️ 稽核備註(2026-05-13): docs/i18n/in/ 目錄仍然存在於磁碟上(是 hi/ 的完整重複)。翻譯產生器不再寫入該目錄,但歷史留存目錄未被清理。確認沒有外部連結參考舊路徑後,可使用 rm -rf docs/i18n/in/ 安全刪除。

docs/i18n/README.md 檔案會由 generate-multilang.mjs docs 完全重新產生。任何手動編輯都會遺失。請使用 docs/guides/I18N.md(本檔案)來存放應保留的手寫文件。

untranslatable-keys.json 允許清單已從 validate_translation.py 中的行內 Python 集合移至外部 JSON 檔案,以便於維護。驗證器會在執行時期載入該檔案。

generate-multilang.mjs 印度語代碼修正

Section titled “generate-multilang.mjs 印度語代碼修正”

產生器原本使用 code: "in"(已棄用的 Google 翻譯代碼)來表示印度語,而不是正確的 ISO 639-1 hi。此問題由 diegosouzapw 在上游提交 952b0b22c 中引入。修正方式為將 LOCALE_SPECS 陣列中的 code: "in" 改為 code: "hi",並移除孤立的 in.json 檔案。

validate_translation.py 忽略計數輸出

Section titled “validate_translation.py 忽略計數輸出”

quick 檢查現在會顯示來自 untranslatable-keys.json 的忽略按鍵計數:

Missing: 0
Untranslated: 0
Ignored (UNTRANSLATABLE_KEYS): <隨版本而異>

OmniRoute 原始碼 (a58000c7685f)

HagiCode

HagiCode 是智慧代理程式開發工作台,結合結構化工作流程、多代理程式執行與 Hero Dungeon 介面,將想法化為交付成果。

以更聰明、更快速且更有趣的智慧代理程式工作流程,打造實用的軟體。

HagiCode 淺色主題介面畫面
  • Smart結構化流程將意圖轉化為從構想到交付的可執行步驟。
  • Efficient多代理程式工作流程讓研究、實作與審查並行進行。
  • FunHero Dungeon 讓長時間的程式協作更直覺、更有參與感。
造訪 HagiCode