Lint translation files for missing keys, broken placeholders, and plural inconsistencies. One command. 9 checks. 32 formats. Zero config.
Translation issues are invisible until users hit them. A missing key shows a raw path like "settings.billing.title" instead of real text. A broken placeholder renders "{price}" as literal text instead of "$9.99". A malformed plural crashes when the count is zero. These bugs slip through code review because nobody diffs 15 locale files manually.
Blank text or key paths shown to users
{price} displays as literal text instead of $9.99
Outdated translations confuse the build system
Runtime crashes when users switch languages
i18n-validate scans all your translation files in one pass. It auto-detects your directory layout and file format, compares every language against the reference, and reports exactly what is wrong and where. No plugins, no configuration, no custom test code.
| Check | Severity | What it catches |
|---|---|---|
| missing-keys | error | Key exists in reference but is absent in a translation |
| extra-keys | error | Key exists in translation but not in the reference |
| placeholders | error | {price}, {{name}}, %s differ between languages |
| plural-structure | error | Plural forms are malformed or missing required categories |
| missing-languages | error | Expected language has no files or directory |
| orphaned-languages | error | Language files exist but are not in the expected list |
| parse-errors | error | File fails to parse (broken JSON, XML, YAML, etc.) |
| empty-values | warning | Key is present but the translation is an empty string |
| untranslated | warning | Translation is identical to the reference language |
i18n-validate v0.1.0 — validating ./locales
Reference: en (2 files: translation.json, apiTester.json)
Languages: de, ja, fr, es, zh-Hans, pt-BR, ko (7 found, 7 expected)
Layout : directory (auto-detected)
Formats : i18next JSON (auto-detected)
────────────────────────────────────────────────
ERRORS (5)
✗ missing-keys │ translation.json
Key "settings.billing.title"
missing in: ja, ko
✗ placeholders │ translation.json
Key "pricing.total" — expected: {price}, {currency}
de: found {price} only — missing {currency}
────────────────────────────────────────────────
WARNINGS (2)
⚠ empty-values │ translation.json
Key "onboarding.step3.hint"
empty in: de, fr
────────────────────────────────────────────────
5 errors, 2 warnings across 7 languages
✗ Validation failedInstall as a global CLI tool using your preferred package manager. The npm package bundles a native Rust binary — no compilation or runtime dependencies required.
npm install -g @i18n-agent/i18n-validatePoint the tool at your locales directory. It auto-detects the reference language, directory layout, and file format. Zero configuration required for most projects.
# Zero-config validation
i18n-validate ./locales
# JSON output for scripting
i18n-validate ./locales --format json | jq '.summary'
# CI/CD with JUnit XML
i18n-validate ./locales --format junit -o i18n-report.xmlAdd translation validation to your pull request pipeline. The tool outputs JUnit XML that integrates with GitHub Actions test reporters, GitLab CI artifacts, and any CI system that supports JUnit.
name: Validate Translations
on:
pull_request:
paths: ['locales/**', 'public/locales/**']
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate translations
run: npx @i18n-agent/i18n-validate ./locales --format junit -o i18n-report.xml
- uses: dorny/test-reporter@v1
if: always()
with:
name: i18n validation
path: i18n-report.xml
reporter: java-junit--strict to also fail on warnings.Powered by i18n-convert, the validator supports 32 i18n file formats out of the box. No format-specific plugins or configuration needed — the tool auto-detects the format from file extensions and content.
Android XML, Xcode String Catalog, iOS Strings, iOS Stringsdict, Flutter ARB, Qt Linguist
Structured JSON, i18next JSON, JSON5, HJSON, YAML (Rails), YAML (Plain), JavaScript, TypeScript, PHP/Laravel, NEON
XLIFF 1.2, XLIFF 2.0, Gettext PO, TMX, .NET RESX, Java Properties
CSV, Excel (.xlsx), TOML, INI, SRT Subtitles, Markdown, Plain Text
For most projects, zero config works. When you need control — override check severity, set expected languages, or exclude WIP languages — create a .i18n-validate.toml file in your project root.
# .i18n-validate.toml
ref = "en"
expect = ["de", "ja", "fr", "es", "zh-Hans", "pt-BR", "ko"]
[checks]
missing-keys = "error"
extra-keys = "error"
placeholders = "error"
empty-values = "warning"
untranslated = "warning"
[languages.ko]
missing-keys = "warning" # Korean is WIP
[languages.ar]
skip = true # Exclude from validationDrop your translation file here
JSON, YAML, PO, XML, CSV, Markdown, Properties
or click to browse
Target languages