KAERIS i18n

io.github.kaeris-io由 GitHub 帳號 kaeris-io 發布v0.2.18更新於 Nov 3, 2026

Translate app language files into 46 languages and check placeholders, plurals and missing keys.

已驗證STDIO僅桌面開發者工具AI 與機器學習

概覽

AI 產生的概覽

本機 MCP 伺服器,用來檢查專案的多語系檔案並翻譯成 46 種語言,保留佔位符與複數形式。

可以做什麼
  • 掃描儲存庫,找出語系檔、來源語言與目標語言,以及所用的 i18n 框架
  • 檢查各目標語系的缺漏鍵、多餘鍵、佔位符不一致、數字漂移、標籤遺失與複數缺漏
  • 列出某個語系中確切缺漏或損壞的鍵及其來源語言文字
  • 列出支援的目標語言
  • 翻譯內嵌的 UI 字串,附品質檢查與可選的回譯驗證
  • 翻譯磁碟上的字串檔,或從來源檔建立全新的語系
適用情境
適合需要讓助理稽核或修正應用程式儲存庫的國際化設定、新增語言,或翻譯 JSON、YAML、.strings、.po、ARB、XLIFF、Fluent 等格式語系檔的情境。
執行需求
透過 stdio 在本機執行,可用 uvx 或 pip 從 PyPI 安裝(也可用 Docker)。免費示範不需金鑰;可選 KAERIS_API_KEY 提高額度,BYOK 方案需 KAERIS_OPENROUTER_KEY。翻譯工具需連網存取 KAERIS API;JSON 檔的掃描與狀態檢查可離線完成。
安裝前請注意
翻譯工具會把來源字串送到 KAERIS 後端,非 JSON 格式還會經其 /api/parse 端點解析。翻譯工具會在來源檔旁寫入檔案,包括 kaeris.lock。README 提到付費方案;免費示範與免費金鑰有單檔與單次執行限制。API 金鑰應放在環境變數中。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 KAERIS i18n,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[KAERIS]

KAERIS MCP server

Lets Claude Desktop, Claude Code, Cursor or any MCP client check your app's locale files and translate them into 46 languages.

[PyPI] [license]

bash
pip install kaeris-mcp && claude mcp add kaeris-i18n kaeris-mcp
  • Three tools work offline with no key: find the locale files in a repo, report missing keys and broken placeholders per language, list the exact keys to fix.
  • Translation keeps placeholders and markup, translates only new keys with only_new, and with verify=True translates each line back to flag a changed meaning.
  • 13 formats: JSON, YAML, .strings, .xcstrings, .po, ARB, Android XML, CSV, XLIFF, .properties, .resx, Fluent .ftl, Markdown.
  • Same engine and kaeris.lock as the CLI, so an agent, a teammate and CI agree on what is already translated.

Plans. No key needed to try it. Free API key: 50k characters per file, 8 languages per run. Pro $19/month with 12M characters, Team/API $79/month with 60M, Lifetime $79 once with your own OpenRouter key. See kaeris.dev/pricing.

Docs · Pricing · Discussions · Status · Security

Tools

ToolWhat it doesCalls the API?
kaeris_scan_repoDiscover a repo's i18n setup: locale files found, base language, target languages, framework guess (i18next/next-intl/vue-i18n/Flutter/Android/iOS/gettext/generic)No
kaeris_statusCompleteness/health per target locale — missing keys, extra keys, placeholder mismatches, plus the quality detectors that gate a merge in CI: number drift, lost inline tags, broken entities/escapes, ICU/CLDR plural gaps (same verdict as kaeris check --json)No
kaeris_list_missing_keysThe exact missing/broken keys (with source text) for one target locale, so an agent knows exactly what to fixNo
kaeris_list_languagesList all supported target languagesYes, free (no quota)
kaeris_translateTranslate inline strings → per-language results, with QA (placeholder-loss & UI-overflow flags; verify=True back-translates to check meaning)Yes
kaeris_translate_fileTranslate a file on disk (JSON/YAML/.strings/.xcstrings/.po/ARB/XML/CSV/XLIFF/.properties/.resx/.ftl/Markdown), optional incremental — reproducible via kaeris.lockYes
kaeris_add_languageBootstrap a brand-new target locale by translating the whole source file into itYes

The first three tools are local-only (no network call, no cost), and kaeris_list_languages is one free API call that counts toward no limit — an agent can use all four freely to audit and understand a repo's i18n before deciding what (if anything) to translate.

Reproducible by design

kaeris_translate_file with only_new=True keeps a kaeris.lock next to your source file — the same lock the CLI writes, so an agent and a human sharing a repo stay in sync. It records a hash of every source string plus the settings that produced it: tone, glossary, app context, and the model. That means:

  • Edit one string — only that string is re-translated; everything else stays byte-for-byte.
  • Change tone, glossary or context — the whole locale is re-translated, never a mix of old and new.
  • Change plan — every tier runs the same model (GPT-6 Luna), so upgrading does not force a re-translation. The lock records the model regardless: the day we change it, the locale is rebuilt in full instead of quietly ending up the work of two models.

Commit kaeris.lock alongside your source file so the agent, your teammates and CI all agree on what is already done.

Install

bash
pip install kaeris-mcp

Or run it with Docker

bash
docker build -t kaeris-mcp .docker run -i --rm -v "$PWD:/work" -w /work kaeris-mcp

The server speaks JSON-RPC over stdin/stdout, so there is no port to expose — -i is what keeps the conversation open. Mount your project at /work and the repo-aware tools (scan_repo, status, list_missing_keys) read it directly; pass -e KAERIS_API_KEY=… to use your KAERIS key.

Configure your client

Claude Desktop — add to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):

json
{  "mcpServers": {    "kaeris-i18n": {      "command": "kaeris-mcp",      "env": {        "KAERIS_API_KEY": "kaerisp_optional"      }    }  }}

Cursor — Settings → MCP → Add, or .cursor/mcp.json:

json
{ "mcpServers": { "kaeris-i18n": { "command": "kaeris-mcp" } } }

Claude Code — one command:

bash
claude mcp add kaeris-i18n kaeris-mcp

Restart the client; the KAERIS tools appear automatically.

Auth & tiers (all optional)

Env varPurpose
KAERIS_API_KEYYour KAERIS key, e.g. the free API key from kaeris.dev/docs/key (50k chars/file, no account) — without one, the free 10k-char demo is used
KAERIS_OPENROUTER_KEYOpenRouter key for Lifetime/BYOK — no monthly volume cap
KAERIS_API_URLOverride the API base URL
KAERIS_NO_UPDATE_CHECKSet to 1 to turn off the once-a-day "new version available" line (stderr only; already off in CI)
KAERIS_NO_CTASet to 1 to drop the pricing link from the error a tool returns when a run is refused on a plan limit

No key is required to try it — the free demo works out of the box.

Example prompts

  • "Translate the strings in locales/en.json into German, Ukrainian and Japanese."
  • "Add French and Spanish translations for these buttons: Save, Cancel, Delete."
  • "Only translate the new keys I added to en.json — don't redo the whole file."
  • "Check this repo's i18n and tell me what's missing or broken." (scans, then reports status — no API call)
  • "We don't have Ukrainian yet — add it." (bootstraps a new locale via translation)

License

MIT

來源:README.md,提交 4dd41a4

工具

7

kaeris_list_languages

List every target language KAERIS can translate into. Returns a mapping of language code → English name (e.g. {"es": "Spanish", ...}). Use the codes with kaeris_translate / kaeris_translate_file.

無需輸入參數。

kaeris_scan_repo

Discover a repo's i18n setup: which locale files exist, what the base (source) language and target languages are, and which framework/convention is in use. Purely local — reads the filesystem, makes no API call. Use this FIRST when asked to "look at/audit/fix this repo's i18n" and you don't already know the source file — it tells you where to point kaeris_status / kaeris_list_missing_keys / kaeris_add_language. Supports i18next/react-i18next (locales/<lang>/*.json), next-intl (messages/<lang>.json), vue-i18n (src/locales/<lang>.json), Flutter ARB (lib/l10n/*.arb), Android (res/values[-<lang>]/strings.xml), iOS (<lang>.lproj/Localizable.strings), gettext (locale/<lang>/LC_MESSAGES/*.po), Xcode String Catalogs (Localizable.xcstrings — one file holding every language, read out of the catalog itself), XLIFF (.xliff/.xlf), Java/Spring .properties, .NET RESX, Mozilla Fluent (.ftl), Markdown/MDX, plus plain <lang>.json/.yaml/.csv files anywhere else. Skips node_modules, .git, build/dist output and other noise; bounded so it's safe on large repos. Args: path: directory to scan (default: current directory). Returns: { "root": "<abs path scanned>", "locale_files": ["locales/en.json", "locales/de.json", ...], "base_lang": "en", # best guess, or null if none found/ambiguous "target_langs": ["de", "fr"], # languages present other than base_lang "framework": "i18next", # best guess, or null if unrecognized "file_count": 2 }

輸入參數path

kaeris_status

Completeness/health check for every target locale against a source file — the "i18n firewall". Works for EVERY supported format: JSON is checked fully offline; other formats (.arb/.strings/.po/.xml/.ftl/…) are parsed by the backend /api/parse endpoint (no translation, no cost). For each target language reports missing keys, extra/stale keys, placeholder mismatches (e.g. "Hello {name}" -> "Bonjour" loses {name}, or "{name}" -> "{nom}" which crashes str.format()/ICU at runtime), and the same quality detectors the CLI firewall gates a merge on: number drift ("Delete 5 files" -> "Delete 50 files"), lost inline tags, broken entities or escapes, missing ICU/CLDR plural categories. Those come back under "faults" (RED — they set ok=false) and "warnings" (YELLOW — advisory). Use this to find out what's broken before deciding whether to call kaeris_list_missing_keys (existing locale, some keys missing/broken) or kaeris_add_language (locale doesn't exist yet at all). Args: source: path to the base-language locale file, e.g. "locales/en.json" or "lib/l10n/app_en.arb" (typically kaeris_scan_repo's base_lang file). langs: target language codes to check, e.g. ["de", "fr"]. If omitted, falls back to kaeris.json's "langs" if present, else auto-discovers sibling <lang> files next to the source. out: directory containing the target locale files (default: source's own directory; each target is expected at "<out>/<lang><source-ext>", e.g. de.json for en.json, de.arb for en.arb). Returns: { "ok": bool, "missing": {lang: [keys]}, "extra": {lang: [keys]}, "placeholder_issues": [{"lang","key","missing","added"}, ...], "faults": [{"lang","key","severity":"error","msg"}, ...], # RED — ok is false "warnings": [{"lang","key"?,"severity":"warn","msg"}, ...], # YELLOW — advisory "missi

輸入參數outlangssource必填

kaeris_list_missing_keys

The exact keys missing or placeholder-broken in ONE target locale, with their source-language text, so an agent knows exactly what to translate/fix. Every supported format works (JSON offline; others via the backend /api/parse, no cost) — use kaeris_add_language or kaeris_translate to actually fill them in. The answer is PAGED: "missing_count" is always the exact total, while "missing" / "missing_values" carry one page of it (default 200 entries, and never more than about 15k tokens' worth). A whole locale file returned in one tool result is not a long answer, it is the end of the agent's session — measured 16.08.2026: a 2 MB source file, the size the product accepts, produced 667 000 tokens in a single reply. When there is a next page, "page.next_offset" says where it starts. Args: source: path to the base-language locale file, e.g. "locales/en.json" or "app_en.arb". lang: the target language code to inspect, e.g. "de". out: directory containing the target locale file (default: source's own directory; expected at "<out>/<lang><source-ext>", e.g. de.json / de.arb). limit: how many missing keys to return in this call (default 200, max 2000). offset: where to start — pass "page.next_offset" from the previous call. Returns: { "lang": "de", "missing_file": bool, "missing_count": 1234, # ALWAYS the exact total "missing": ["<dotted.key>", ...], # one page of them "missing_values": {"<dotted.key>": "<source text>", ...}, # the same page "page": {"total", "returned", "offset", "complete", "next_offset"?, "note"?}, "extra": ["<dotted.key>", ...], "extra_count": 12, "placeholder_issues": [{"key","missing","added"}, ...], "placeholder_issue_count": 3 }

輸入參數outlang必填limitoffsetsource必填

kaeris_add_language

Bootstrap a BRAND-NEW target locale by translating the entire source file into it and writing the result. Use this when kaeris_scan_repo/kaeris_status show a language with no locale file at all yet (in "missing_files"). This CALLS THE TRANSLATION API (same as kaeris_translate_file) — unlike kaeris_scan_repo/kaeris_status/kaeris_list_missing_keys, which are local-only and free. For an EXISTING locale that's just missing a few keys, prefer kaeris_translate_file(..., only_new=True) so you don't re-translate the whole file. Args: source: path to the base-language locale file, e.g. "locales/en.json". lang: the new target language code to create, e.g. "de". out: output directory (default: source file's own directory). tone: "formal" or "casual" to steer register; "" (default) is neutral. icu: True if the source uses ICU MessageFormat (plurals/select), so the model preserves the syntax instead of translating it. keep: optional list of terms to NEVER translate (brand/product names). context: one line about what the app IS, e.g. "a mobile bank for teenagers" or "a wildlife documentary app". The model uses it to pick the right sense of ambiguous strings — "Bank" becomes Ufer in the second and Bank in the first. You are reading the repo, so you know this: pass it. Max 300 chars. api_key / openrouter_key: optional auth overrides. PREFER the KAERIS_API_KEY / KAERIS_OPENROUTER_KEY environment variables: a key passed as a tool argument is written into the conversation transcript and into the MCP client's logs, where it outlives this task. job_id: leave empty to start a translation. If a previous call came back with {"status": "running", "job_id": ...}, pass that id (with the same source/out) to collect the finished result instead of paying for the work twice

輸入參數icuoutkeeplang必填tonejob_idsource必填api_keycontextopenrouter_key

kaeris_translate

Translate a set of UI strings into one or more languages. Format-aware and placeholder-safe: values like "Hello, {name}" keep their placeholders intact. Non-string values are passed through unchanged. Includes Translation QA so you can trust the output: it flags translations that dropped a placeholder or that grew long enough to risk overflowing the UI. With verify=True it also back-translates each result into back_lang so you can check the meaning is right even in a language you can't read. Args: strings: key → source-text pairs, e.g. {"greeting": "Hello", "save": "Save"}. target_languages: language codes from kaeris_list_languages, e.g. ["es", "fr", "ja"]. keep: optional list of terms to NEVER translate — kept verbatim in every language (brand/product names), e.g. ["KAERIS", "GitHub"]. context: one line about what the app IS, e.g. "a mobile bank for teenagers" or "a wildlife documentary app". The model uses it to pick the right sense of ambiguous strings — "Bank" becomes Ufer in the second and Bank in the first. You are reading the repo, so you know this: pass it. Max 300 chars. verify: back-translation and meaning check for your review — back-translates into back_lang and flags lines whose meaning may have changed (uses more tokens). back_lang: language for the verify back-translation (default "en"). tone: "formal" or "casual" to steer register; "" (default) is neutral. icu: True if values may contain ICU MessageFormat (plurals/select) so the model preserves the syntax instead of translating it. reuse: optional {lang: {key: previous_translation}} translation-memory map — strings that are unchanged from a prior run are reused verbatim server-side and only new/changed strings are actually translated. api_key / openrouter_key: optional auth overr

輸入參數icukeeptonereusejob_idverifyapi_keycontextstrings必填back_langopenrouter_keytarget_languages必填

kaeris_translate_file

Translate a strings file on disk and write the results next to it. Supports JSON, YAML, .strings, Xcode String Catalogs (.xcstrings), .po, ARB, Android XML, CSV, XLIFF 1.2, Java/Spring .properties, .NET RESX, Mozilla Fluent (.ftl) and Markdown/MDX — every format the API accepts. With only_new=True (JSON), translates just the keys missing from existing target files and merges. Args: file_path: path to the source file, e.g. "locales/en.json". target_languages: language codes, e.g. ["de", "uk", "zh"]. out_dir: where to write outputs (default: the source file's directory). only_new: reproducible incremental mode — translate only new AND edited keys, tracked via kaeris.lock (a tone/ICU/glossary change re-translates all); unchanged stays stable. JSON and ARB only — for any other format the whole file is translated (and charged), and the result says so in "note". keep: optional list of terms to NEVER translate — kept verbatim in every language (brand/product names), e.g. ["KAERIS", "GitHub"]. context: one line about what the app IS, e.g. "a mobile bank for teenagers" or "a wildlife documentary app". The model uses it to pick the right sense of ambiguous strings — "Bank" becomes Ufer in the second and Bank in the first. You are reading the repo, so you know this: pass it. Max 300 chars. verify: back-translation and meaning check for your review; with only_new the result carries them as "back_translations". back_lang: language for the verify back-translation (default "en"). tone: "formal" or "casual" to steer register; "" (default) is neutral. icu: True if values may contain ICU MessageFormat (plurals/select) so the model preserves the syntax instead of translating it. reuse: optional {lang: {key: previous_translation}} translatio

輸入參數icukeeptonereusejob_idverifyapi_keycontextout_dironly_newback_langfile_path必填另有 2 個

版本歷史

2
  1. v0.2.18最新Nov 1, 2026
  2. v0.2.16Oct 29, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分
  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分