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 分