Skip to main content

Find drift between i18n locale files — missing keys, CLDR-aware plural gaps, empty values. Framework-agnostic, zero dependencies.

Project description

localediff

Find drift between your i18n locale files — before your users do. You add a string to en.json, ship it, and three weeks later notice fr.json and zh.json were never updated. localediff catches that in CI: missing keys, plural forms a language actually needs, and keys that exist but were left blank. Framework-agnostic, zero dependencies.

pip install localediff
localediff ./locales
✗ fr.json
  missing (1): auth.errors.locked
  plural  cart.items — has {other}, missing {one}
  empty   (1): footer.copyright
  extra   (1): legacy.banner

✓ zh.json — in sync

✗ 1 of 2 file(s) drifted — 1 missing, 1 plural gap(s), 1 empty, 1 extra

Why another i18n tool

Most existing tools are tied to one framework, need an account, or are heavy AST-based linters. localediff just reads JSON. It compares structure, so it works for next-intl, react-intl, i18next, vue-i18n, Django/Flask JSON catalogs, or any plain message file — and it ships for both PyPI and npm with identical behavior.

It understands plurals per language

This is the part naive "diff two JSON files" scripts get wrong. English has two plural forms (one, other); Chinese has one (other); Russian has four (one, few, many, other). A file with only items_other is correct for Chinese but broken for French. localediff resolves the required CLDR categories from each target's language, so it flags the real bug without crying wolf on zh.json.

# en base: items_one + items_other
zh.json    items_other only      in sync   (Chinese needs only `other`)
fr.json    items_other only      missing {one}
ru.json    items_one + _other    missing {few, many}

Usage

# Scan a folder. The base defaults to en.json; everything else is checked.
localediff ./locales

# Pick a different base language in the folder.
localediff ./locales --base de

# Compare specific files explicitly.
localediff --base en.json --check fr.json zh.json

# Shorthand: first file is the base.
localediff en.json fr.json zh.json

# Machine-readable output for CI gates.
localediff ./locales --format json

You can also run it as a module: python -m localediff ./locales.

What it checks

Check Meaning
missing a key in the base that the target never translated
plural a pluralized key (key_one, key_other, …) missing a CLDR form the target language requires
empty a key present in the target whose value is a blank string
extra a key in the target the base no longer has

Nested objects are flattened to dot-paths (auth.errors.locked); arrays are indexed (steps.0). Plural keys use the i18next suffix convention (_zero, _one, _two, _few, _many, _other). Unknown languages fall back to parity with the base, so you never get a confidently-wrong result.

Options

--base <file|lang>    base/source locale (a file, or a lang stem in dir mode)
--check <files...>    one or more target locales to compare against the base
--dir <dir>           scan a directory of *.json locales
--lang <code>         force the target language for plural rules
--format text|json    output format (default: text)
--ignore-missing      don't report missing keys
--ignore-extra        don't report extra keys
--ignore-plural       don't report plural gaps
--ignore-empty        don't report empty values
-v, --version
-h, --help

In CI

localediff exits non-zero when anything has drifted:

Exit code Meaning
0 every checked file is in sync
1 one or more files have drift
2 error (file not found, invalid JSON, bad arguments)

Also available for Node

npx localediff ./locales

Same checks, same flags, same exit codes — localediff on npm.

Scope

JSON locale files only (the common case). YAML/.properties/gettext are not supported — parsing them would mean pulling in a dependency, and zero-dep is the point. Convert to JSON, or open an issue to discuss.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

localediff-0.1.0.tar.gz (13.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

localediff-0.1.0-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file localediff-0.1.0.tar.gz.

File metadata

  • Download URL: localediff-0.1.0.tar.gz
  • Upload date:
  • Size: 13.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for localediff-0.1.0.tar.gz
Algorithm Hash digest
SHA256 efdf76c19377de05c91dbb0b92c0a3cd7a926481de897dc854b5fae8ffb67af5
MD5 eda20ec5be1f7f8770073f0c272862fd
BLAKE2b-256 c696fb8124cf2c7c85f92554352cd35d1b022fa2252fb411d0cc8f3cf0347261

See more details on using hashes here.

File details

Details for the file localediff-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: localediff-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for localediff-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 980d099c5687076092e675802dfa3c421b14cfacb80965c20339df139b8f2e0e
MD5 ec46c1da645fc3f8d3696d7e0c4f438f
BLAKE2b-256 b057c8707b216953cf59bc0d9a7003687ff21a1dc9f5d1d72295cdc69985de21

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page