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.
Takes no parameters.

io.github.kaeris-ioPublished by GitHub account kaeris-iov0.2.18Updated Nov 3, 2026
Translate app language files into 46 languages and check placeholders, plurals and missing keys.
Local MCP server that audits a repo's locale files and translates them into 46 languages, keeping placeholders and plurals intact.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Follow the launch instructions in the repository.
Lets Claude Desktop, Claude Code, Cursor or any MCP client check your app's locale files and translate them into 46 languages.
only_new, and
with verify=True translates each line back to flag a changed meaning..strings, .xcstrings, .po, ARB, Android XML, CSV, XLIFF,
.properties, .resx, Fluent .ftl, Markdown.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
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.
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:
Commit kaeris.lock alongside your source file so the agent, your teammates and CI all agree on
what is already done.
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.
Claude Desktop — add to claude_desktop_config.json
(macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):
Cursor — Settings → MCP → Add, or .cursor/mcp.json:
Claude Code — one command:
Restart the client; the KAERIS tools appear automatically.
No key is required to try it — the free demo works out of the box.
locales/en.json into German, Ukrainian and Japanese."MIT
Source: README.md at commit 4dd41a4
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.
Takes no parameters.
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 }
pathCompleteness/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
outlangssourcerequiredThe 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 }
outlangrequiredlimitoffsetsourcerequiredBootstrap 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
icuoutkeeplangrequiredtonejob_idsourcerequiredapi_keycontextopenrouter_keyTranslate 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_keycontextstringsrequiredback_langopenrouter_keytarget_languagesrequiredTranslate 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_pathrequired+2 more90% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
pip install kaeris-mcp && claude mcp add kaeris-i18n kaeris-mcppip install kaeris-mcpdocker build -t kaeris-mcp .docker run -i --rm -v "$PWD:/work" -w /work kaeris-mcp{ "mcpServers": { "kaeris-i18n": { "command": "kaeris-mcp", "env": { "KAERIS_API_KEY": "kaerisp_optional" } } }}{ "mcpServers": { "kaeris-i18n": { "command": "kaeris-mcp" } } }claude mcp add kaeris-i18n kaeris-mcp