-
Notifications
You must be signed in to change notification settings - Fork 1k
hu‐I18N
🇭🇺 Magyar | 🇺🇸 English | Language Hub
🌐 Languages: 🇺🇸 English · 🇸🇦 ar · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇪🇸 es · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇳 gu · 🇮🇱 he · 🇮🇳 hi · 🇭🇺 hu · 🇮🇩 id · 🇮🇹 it · 🇯🇵 ja · 🇰🇷 ko · 🇮🇳 mr · 🇲🇾 ms · 🇳🇱 nl · 🇳🇴 no · 🇵🇭 phi · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇸🇰 sk · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇻🇳 vi · 🇨🇳 zh-CN
OmniRoute supports 30 languages with full dashboard UI translation, translated documentation, and RTL support for Arabic and Hebrew.
| Task | Command |
|---|---|
| Generate translations | node scripts/i18n/generate-multilang.mjs messages |
| Translate docs (LLM) | python3 scripts/i18n_autotranslate.py --api-url <url> --api-key <key> --model <model> |
| Validate a locale | python3 scripts/validate_translation.py quick -l cs |
| Check code keys | python3 scripts/check_translations.py |
| Generate QA report | node scripts/i18n/generate-qa-checklist.mjs |
| Visual QA (Playwright) | node scripts/i18n/run-visual-qa.mjs |
-
UI strings:
src/i18n/messages/en.json(English source, ~2800 keys) -
Locale files:
src/i18n/messages/{locale}.json(30 translations) -
Framework:
next-intlwith cookie-based locale resolution -
Config:
src/i18n/config.ts— defines all 30 locales, language names, flags
- User selects language →
NEXT_LOCALEcookie set -
src/i18n/request.tsresolves locale: cookie →Accept-Languageheader → fallbacken - Dynamic import loads
messages/{locale}.json - Components use
useTranslations("namespace")andt("key")
| Code | Language | RTL | Google Translate Code |
|---|---|---|---|
ar |
العربية | Yes | ar |
bg |
Български | No | bg |
cs |
Čeština | No | cs |
da |
Dansk | No | da |
de |
Deutsch | No | de |
es |
Español | No | es |
fi |
Suomi | No | fi |
fr |
Français | No | fr |
he |
עברית | Yes | iw |
hi |
हिन्दी | No | hi |
hu |
Magyar | No | hu |
id |
Bahasa Indonesia | No | id |
it |
Italiano | No | it |
ja |
日本語 | No | ja |
ko |
한국어 | No | ko |
ms |
Bahasa Melayu | No | ms |
nl |
Nederlands | No | nl |
no |
Norsk | No | no |
phi |
Filipino | No | tl |
pl |
Polski | No | pl |
pt |
Português (Portugal) | No | pt |
pt-BR |
Português (Brasil) | No | pt |
ro |
Română | No | ro |
ru |
Русский | No | ru |
sk |
Slovenčina | No | sk |
sv |
Svenska | No | sv |
th |
ไทย | No | th |
tr |
Türkçe | No | tr |
uk-UA |
Українська | No | uk |
vi |
Tiếng Việt | No | vi |
zh-CN |
中文 (简体) | No | zh-CN |
Edit src/i18n/config.ts:
// Add to LOCALES array
"xx",
// Add to LANGUAGES array
{ code: "xx", label: "XX", name: "Language Name", flag: "🏳️" },Edit scripts/i18n/generate-multilang.mjs — add entry to LOCALE_SPECS:
{
code: "xx",
googleTl: "xx",
label: "XX",
flag: "🏳️",
languageName: "Language Name",
readmeName: "Language Name",
docsName: "Language Name",
},node scripts/i18n/generate-multilang.mjs messagesThis creates src/i18n/messages/xx.json auto-translated from en.json via Google Translate.
Auto-translations are a starting point. Review manually for:
- Technical accuracy
- Context-appropriate terminology
- Proper handling of placeholders (
{count},{value}, etc.)
python3 scripts/validate_translation.py quick -l xx
python3 scripts/validate_translation.py diff common -l xxnode scripts/i18n/generate-multilang.mjs docsPrimary auto-translation engine — uses Google Translate free API to generate translations for UI strings, READMEs, and documentation.
node scripts/i18n/generate-multilang.mjs [messages|readme|docs|all]| Mode | What it does |
|---|---|
messages |
Translates missing keys in src/i18n/messages/{locale}.json from en.json
|
readme |
Translates README.md into all locales as README.{code}.md in project root |
docs |
Translates DOC_SOURCE_FILES into docs/i18n/{locale}/{docName}
|
all |
Runs all three modes |
Features:
-
Text protection: Masks code blocks (
```), inline code (`), markdown links/images ([text](url)), HTML tags, tables, and ICU placeholders ({count},{value},{total}, etc.) before translation, then restores them -
Chunked batching: Joins multiple strings with
__OMNIROUTE_I18N_SEPARATOR__delimiters to minimize API calls (max 1800 chars per request) - In-memory cache: Avoids redundant API calls for repeated strings within a session
- Retry logic: Exponential backoff (up to 5 attempts with 300ms × attempt delay) for 429/5xx errors
- Timeout: 20 seconds per request
- Skip existing: If target file already exists, it is NOT overwritten
Important behaviors:
-
docs/i18n/README.mdis regenerated each run — it's an auto-generated index of all docs - Root
README.{code}.mdfiles are only created if they don't exist (skips locales inEXISTING_README_CODES) - Language bars (
🌐 **Languages:** ...) are automatically inserted/updated in all translated docs
Secondary translator — uses any OpenAI-compatible LLM API (including OmniRoute itself) to translate existing docs/i18n/ markdown files. Best for polishing or re-translating docs with better quality than Google Translate.
python3 scripts/i18n_autotranslate.py \
--api-url http://localhost:20128/v1 \
--api-key sk-your-key \
--model gpt-4oFeatures:
- Scans
docs/i18n/markdown files for English paragraphs - Skips code blocks, tables, and already-translated content
- Sends paragraphs to LLM with technical translation system prompt
- Supports all 30 languages
Translation validator — compares any locale JSON against en.json and reports issues.
# Quick check (counts only)
python3 scripts/validate_translation.py quick -l cs
# Output:
# Missing: 0
# Untranslated: 0
# Ignored (UNTRANSLATABLE_KEYS): 236
# Detailed diff by category
python3 scripts/validate_translation.py diff common -l cs
python3 scripts/validate_translation.py diff settings -l cs
# Export to CSV
python3 scripts/validate_translation.py csv -l cs > report.csv
# Export to Markdown
python3 scripts/validate_translation.py md -l cs > report.md
# Full report (default)
python3 scripts/validate_translation.py -l csDetects:
-
Missing keys — keys in
en.jsonbut not in locale file -
Extra keys — keys in locale file but not in
en.json - Untranslated keys — keys where locale value equals English source (excluding allowlist)
- Placeholder mismatches — ICU placeholders that don't match between source and translation
Exit codes:
| Code | Meaning |
|---|---|
| 0 | OK |
| 1 | Generic error |
| 2 | Missing strings (hard error) |
| 3 | Untranslated warning (soft) |
Environment: Set TRANSLATION_LANG=cs or use -l cs flag.
Code-to-JSON key checker — scans src/**/*.tsx and src/**/*.ts for useTranslations() calls and verifies all referenced keys exist in en.json.
# Basic check
python3 scripts/check_translations.py
# Verbose output
python3 scripts/check_translations.py --verbose
# Auto-fix (adds missing keys to en.json)
python3 scripts/check_translations.py --fixStatic analysis QA — scans Next.js page files for i18n risk metrics and generates a Markdown report.
node scripts/i18n/generate-qa-checklist.mjsChecks:
- Fixed-width class usage (overflow risk)
- Directional left/right classes (RTL risk)
- Clipping-prone patterns
- Locale parity (missing/extra keys vs
en.json) - README language selector bars in priority locales (
es,fr,de,ja,ar)
Output: docs/reports/i18n-qa-checklist-{date}.md
Visual QA via Playwright — takes screenshots of all dashboard routes in multiple locales and viewports, then evaluates page health.
# Default: es, fr, de, ja, ar on localhost:20128
node scripts/i18n/run-visual-qa.mjs
# Custom base URL and locales
QA_BASE_URL=http://staging.example.com QA_LOCALES=de,fr node scripts/i18n/run-visual-qa.mjs
# Custom routes
QA_ROUTES=/dashboard/settings,/dashboard/providers node scripts/i18n/run-visual-qa.mjsDetects:
- Text overflow
- Element clipping
- RTL layout mismatches
Output: docs/reports/i18n-visual-qa-{date}.md + JSON report
File: scripts/i18n/untranslatable-keys.json
Allowlist of keys that should remain identical to English source. Used by validate_translation.py to avoid false-positive "untranslated" warnings.
{
"description": "Keys that should remain untranslated...",
"keys": [
"common.model",
"common.oauth",
"health.cpu",
...
]
}What belongs here:
- Brand/product names:
landing.brandName,common.social-github - Technical terms/acronyms:
health.cpu,mcpDashboard.pid,settings.ai - ICU/format strings:
apiManager.modelsCount,health.millisecondsShort - Placeholder values:
providers.openaiBaseUrlPlaceholder,cliTools.baseUrlPlaceholder - Protocol names:
common.http,common.oauth,providers.oauth2Label - Navigation sections:
sidebar.primarySection,sidebar.cliSection
To add a key: Edit the keys array in scripts/i18n/untranslatable-keys.json and re-run validation.
The CI pipeline validates all locales on every push and PR:
-
i18n-matrixjob — dynamically discovers all locale files (excludingen.json) -
i18njob — runsvalidate_translation.py quick -l '<lang>'for each locale in parallel -
ci-summaryjob — aggregates results into a dashboard summary
# i18n-matrix: discovers languages
LANGS=$(ls src/i18n/messages/*.json | xargs -n1 basename | sed 's/.json$//' | grep -v '^en$')
# i18n: validates each language
python3 scripts/validate_translation.py quick -l '${{ matrix.lang }}'Dashboard output:
## 🌍 Translations
| Metric | Value |
|--------|------|
| Languages checked | 30 |
| Total untranslated | 0 |
✅ All translations complete
src/i18n/
├── config.ts # Locale definitions (30 locales, RTL config)
├── request.ts # Runtime locale resolution
└── messages/
├── en.json # Source of truth (~2800 keys)
├── cs.json # Czech translation
├── de.json # German translation
└── ... # 30 locale files total
scripts/
├── i18n/
│ ├── generate-multilang.mjs # Auto-translation engine (Google Translate, 888 lines)
│ ├── generate-qa-checklist.mjs # Static analysis QA
│ ├── run-visual-qa.mjs # Playwright visual QA
│ └── untranslatable-keys.json # Allowlist for validation (236 keys)
├── validate_translation.py # Translation validator
├── check_translations.py # Code-to-JSON key checker
└── i18n_autotranslate.py # LLM-based doc translator
.github/workflows/
└── ci.yml # i18n validation in CI matrix
docs/
├── I18N.md # This file — i18n toolchain documentation
├── i18n/
│ ├── README.md # Auto-generated language index
│ ├── cs/ # Czech docs
│ │ └── docs/
│ │ ├── I18N.md # Czech translation of this file
│ │ └── ...
│ ├── de/ # German docs
│ └── ... # 30 locale directories
└── reports/
├── i18n-qa-checklist-*.md # Static analysis reports
└── i18n-visual-qa-*.md # Visual QA reports
-
Always edit
en.jsonfirst — it's the source of truth -
Run
generate-multilang.mjs messagesto propagate new keys to all locales - Review auto-translations — Google Translate is a starting point, not final
-
Validate before committing —
python3 scripts/validate_translation.py quick -l <lang> -
Update
untranslatable-keys.jsonif a key should remain in English
- ICU placeholders (
{count},{value},{total},{seconds}) must be preserved exactly - Plural formats (
{count, plural, one {# model} other {# models}}) must maintain structure - The validator detects placeholder mismatches automatically
// Use namespaced keys
const t = useTranslations("settings");
t("cacheSettings"); // maps to settings.cacheSettings in JSON
// Run check_translations.py to verify keys exist
python3 scripts/check_translations.py --verbose- Arabic (
ar) and Hebrew (he) are RTL locales - Avoid hardcoded
left/rightCSS — usestart/endlogical properties - Visual QA catches RTL layout mismatches via
run-visual-qa.mjs
The generator originally used code: "in" (deprecated Google Translate code) for Hindi instead of the correct ISO 639-1 hi. This created an orphaned in.json duplicate of hi.json. Fixed by changing code: "in" to code: "hi" in generate-multilang.mjs and removing the orphaned file.
The docs/i18n/README.md file is completely regenerated by generate-multilang.mjs docs. Any manual edits will be lost. Use docs/guides/I18N.md (this file) for hand-written documentation that should persist.
The untranslatable-keys.json allowlist was moved from an inline Python set in validate_translation.py to an external JSON file for easier maintenance. The validator loads it at runtime.
The generator originally used code: "in" (deprecated Google Translate code) for Hindi instead of the correct ISO 639-1 hi. This was introduced in upstream commit 952b0b22c by diegosouzapw. Fixed by changing code: "in" to code: "hi" in the LOCALE_SPECS array and removing the orphaned in.json file.
The quick check now displays the count of ignored keys from untranslatable-keys.json:
Missing: 0
Untranslated: 0
Ignored (UNTRANSLATABLE_KEYS): 236
OmniRoute · Website · npm · Docker Hub
- Setup Guide
- User Guide
- Features
- Quick Start (Docker)
- Electron Desktop App
- Termux (Android)
- PWA Guide
- MCP Server
- A2A Server
- Agent Protocols
- OpenCode Plugin
- Webhooks
- Cloud Agents
- Skills
- Memory
- Evals
- Gamification
- Guardrails
- Compliance
- Error Sanitization
- Public Credentials
- Route Guard Tiers
- Stealth Guide
- CLI Token Auth