I18n Lens
I18n Lens is an i18n intelligence layer for codebases.
It runs in editors through LSP, in CI through a CLI, and in AI coding workflows through an MCP server. The Zed extension is the first editor integration, not the whole product.
Features | Install | CLI | MCP | Configure | Roadmap
Features
I18n Lens helps you answer the questions that usually require opening translation files by hand:
- What does this key mean?
- Is this key defined?
- Which locales are missing a value?
- Which translation keys are no longer used?
- Do translated placeholders still match the source locale?
Current surfaces:
| Surface | What it does |
|---|---|
| LSP / Zed | Inline translation hints, hover previews, missing-key diagnostics, autocomplete, go to definition, auto reload |
| CLI | Project audits, file checks, terminal / JSON / Markdown output, CI-friendly exit codes |
| MCP | Agent tools for audit data, missing translations, fix suggestions, and placeholder validation |
| Rust library | Reusable scanner, parser, config, audit, and translation store modules |
Install
One-Off CLI
After the npm package is published, you can run I18n Lens without a global install:
npx @i18nlens/cli audit
bunx @i18nlens/cli fix --to-nestedZed Extension
- Open Zed.
- Go to Extensions with
cmd+shift+x. - Search for
I18n Lens. - Install the extension.
The extension launches the i18nlens language server.
The extension checks for updates through GitHub's release page. Before reusing a downloaded server, it checks the executable format, architecture, and file ranges, then sets execute permissions. If an update check or download fails, it tries installed versions from newest to oldest, including intl-lens installs. It skips incomplete files or versions whose permissions cannot be set. If none can be prepared, it returns the original update or download error.
Build from Source
git clone https://github.com/nguyenphutrong/i18nlens.git
cd i18nlens
cargo build --releaseThis builds:
target/release/i18nlenstarget/release/i18nlens-mcp- compatibility aliases:
target/release/intl-lens,target/release/intl-lens-cli,target/release/intl-lens-mcp
Put the binaries on your PATH if you want to run them from other projects.
ln -sf "$(pwd)/target/release/i18nlens" ~/.local/bin/i18nlens
ln -sf "$(pwd)/target/release/i18nlens-mcp" ~/.local/bin/i18nlens-mcpintl-lens, intl-lens-cli, and intl-lens-mcp are still built as compatibility aliases, but the public commands are i18nlens and i18nlens-mcp.
Editor Usage
When you write code like this:
<button>{t("common.actions.submit")}</button>I18n Lens can show the source translation inline, display all locale values on hover, warn when the key is missing, and jump to the translation definition.
Manual Zed configuration example:
{
"lsp": {
"i18nlens": {
"binary": { "path": "i18nlens" }
}
},
"languages": {
"TSX": {
"language_servers": ["typescript-language-server", "i18nlens", "..."]
},
"TypeScript": {
"language_servers": ["typescript-language-server", "i18nlens", "..."]
}
}
}CLI
Run a full audit:
i18nlens auditWrite machine-readable output for CI or another tool:
i18nlens audit --format json --output i18n-report.jsonWrite a Markdown report:
i18nlens audit --format markdown --output i18n-report.mdCheck specific files:
i18nlens check src/components/Checkout.tsx src/pages/Home.tsxInclude AI-ready fix suggestions:
i18nlens audit --suggest-fixes --format jsonPreview and apply missing-key fixes:
i18nlens fix --dry-run
i18nlens fix --add-missing --placeholder "_TODO_"
i18nlens fix --sort-keys
i18nlens fix --to-nested --sort-keys
i18nlens fix --to-flat --sort-keysfix --add-missing currently writes JSON, YAML, PHP, and ARB locale files. fix --sort-keys currently sorts JSON, YAML, and ARB locale files. fix --to-nested and fix --to-flat currently convert JSON and YAML locale files and can be combined with --sort-keys. Other write paths are tracked in ROADMAP.md.
audit and check return a non-zero exit code when I18n Lens finds missing or unused keys. ci uses stricter CI defaults: it fails on missing translations and placeholder mismatches, and it auto-loads .i18nlens-baseline.json when that file exists.
CI policy examples:
i18nlens ci --fail-on missing,placeholder --max-unused 20
i18nlens audit --fail-on missing,unused,placeholder
i18nlens audit --ignore-key-pattern '^legacy\.'
i18nlens ci --ignore-file 'src/generated/**'Baseline flow for projects with existing i18n debt:
i18nlens audit --write-baseline .i18nlens-baseline.json
i18nlens ciGitHub Actions Example
name: i18n
on:
pull_request:
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: nguyenphutrong/i18nlens@v0.1.6
with:
fail-on: missing,placeholder
format: markdown
output: i18n-report.mdThe action installs the matching release binary and runs i18nlens ci.
GitLab CI Example
include:
- local: examples/gitlab-ci.ymlOr copy examples/gitlab-ci.yml into your pipeline and adjust I18NLENS_VERSION.
MCP
Start the MCP server from the project you want to inspect:
i18nlens-mcpAvailable tools:
| Tool | Purpose |
|---|---|
audit_i18n |
Return missing translations, unused keys, placeholder issues, and summary data |
get_missing_translations |
Filter missing keys by locale and optionally include source usage context |
suggest_translation_fixes |
Return file targets and source text for a missing key |
translate_missing_keys |
Return dry-run diffs for caller-provided translations of missing keys |
apply_translation_patch |
Apply or dry-run caller-provided translations; defaults to dry-run |
validate_placeholders |
Check placeholder consistency for one key |
get_translation_context |
Return locale values, missing locales, usage context, and target files for one key |
review_i18n_pr |
Return a structured PR-style i18n review and Markdown comment |
extract_hardcoded_strings |
Return candidate hardcoded user-facing strings from source files |
Available resources:
| Resource | Purpose |
|---|---|
i18nlens://config |
Resolved i18n config |
i18nlens://audit/latest |
Fresh audit report |
i18nlens://translations/index |
Loaded locales and key count |
Example agent workflow:
Run i18nlens audit, list keys missing in Vietnamese, provide translated values, get dry-run diffs, then validate placeholders.Configuration
I18n Lens looks for configuration in this order:
.i18nlens.jsoni18nlens.config.json.intl-lens.jsonintl-lens.config.json.zed/i18n.json
Example:
{
"localePaths": ["src/locales", "public/locales"],
"sourceLocale": "en",
"keyStyle": "auto",
"displayMode": "inlayHints",
"namespaceEnabled": false
}Options:
| Option | Type | Default | Description |
|---|---|---|---|
localePaths |
string[] |
Common locale directories | Translation directories to scan |
sourceLocale |
string |
en |
Primary locale used as the source text |
keyStyle |
nested, flat, auto |
auto |
Translation key structure |
displayMode |
inlayHints, codeLens |
inlayHints |
LSP display mode |
namespaceEnabled |
boolean |
false |
Enables namespace-aware behavior |
functionPatterns |
string[] |
Built-in framework patterns | Custom regex patterns for key detection |
Custom pattern example:
{
"functionPatterns": [
"t\\s*\\(\\s*[\"']([^\"']+)[\"']",
"translate\\s*\\(\\s*[\"']([^\"']+)[\"']"
]
}Supported Frameworks
| Framework | Patterns |
|---|---|
| react-i18next | t("key"), useTranslation(), <Trans i18nKey="key"> |
| i18next | t("key"), i18n.t("key") |
| vue-i18n | $t("key"), $tc("key"), $te("key") |
| react-intl | formatMessage({ id: "key" }) |
| ngx-translate | translateService.instant("key"), translateService.get("key"), ` |
| Transloco | translocoService.translate("key"), selectTranslate("key"), ` |
| Laravel | __("key"), trans("key"), Lang::get("key"), @lang("key") |
| Flutter gen_l10n | AppLocalizations.of(context)!.key |
| easy_localization | 'key'.tr(), tr("key"), context.tr("key") |
| flutter_i18n | FlutterI18n.translate(context, "key"), I18nText("key") |
| GetX | 'key'.tr, 'key'.trParams({}) |
| svelte-i18n | $_("key"), $t("key"), $format("key") |
| sveltekit-i18n | $t("key"), t("key") |
Supported Source Files
- TypeScript / TSX
- JavaScript / JSX
- HTML
- Angular templates
- PHP
- Blade
- Dart / Flutter
- Vue
- Svelte
Supported Translation Formats
| Format | Extensions |
|---|---|
| JSON | .json |
| YAML | .yaml, .yml |
| PHP | .php |
| ARB | .arb |
Directory-per-locale:
locales/
en/
common.json
vi/
common.jsonFlat files:
locales/
en.json
vi.jsonFlutter ARB:
lib/
l10n/
app_en.arb
app_vi.arbDevelopment
cargo test
cargo build
cargo build --release
RUST_LOG=debug ./target/release/i18nlensContributing
Good first areas:
- CLI tests for audit and check workflows
- MCP client compatibility tests
- Auto-fix dry-run implementation
- More translation file formats
- Better key detection with AST or tree-sitter
See ROADMAP.md for the current product direction.
License
MIT (c) Trong Nguyen