Check translations from Make or npm scripts
If your project already has a make test or an npm test, add the translation check there. kaeris check exits with 1 when a placeholder or a key is broken, so the whole target fails. It is offline and free: no API key, no account.
The recipe
Makefile
Install the checker once with pip install kaeris. The recipe line starts with a tab. Making test depend on i18n-check runs the check before the tests.
.PHONY: i18n-check test i18n-check: kaeris check --source locales/en.json --langs de,fr --ci test: i18n-check ./run-tests.sh
npm scripts
The script only calls kaeris from your PATH, so the checker is the Python package from pip install kaeris. pretest runs before test and stops it when the check fails.
{
"scripts": {
"i18n:check": "kaeris check --source locales/en.json --langs de,fr --ci",
"pretest": "npm run i18n:check",
"test": "jest"
}
}
What it prints, on real runs
Output of kaeris 0.2.35, captured 27 October 2026. The last line of each box is the exit code the CI job sees.
npm test
Output of npm test with the scripts above (the test script was echo in this run). Left: files that are fine. Right: de.json with {nam} instead of {name} and the checkout key missing; npm stops before test.
$ npm test > [email protected] pretest > npm run i18n:check > [email protected] i18n:check > kaeris check --source locales/en.json --langs de,fr --ci ✓ de: complete & placeholder-safe ✓ fr: complete & placeholder-safe ✓ all locales complete & placeholder-safe > [email protected] test > echo tests would run here tests would run here exit code: 0
$ npm test > [email protected] pretest > npm run i18n:check > [email protected] i18n:check > kaeris check --source locales/en.json --langs de,fr --ci ✗ de: 1 missing key(s): checkout ✗ de: 1 placeholder mismatch(es): greeting: missing ['{name}'], added ['{nam}'] ✗ de: 2 translation fault(s): greeting: lost placeholder {name} greeting: invented placeholder {nam} (not in source) ✓ fr: complete & placeholder-safe ✗ 1 missing key, 1 placeholder mismatch, 2 translation faults exit code: 1
The Makefile recipe line
The same command that the i18n-check target runs, and its exit code.
$ kaeris check --source locales/en.json --langs de,fr --ci ✓ de: complete & placeholder-safe ✓ fr: complete & placeholder-safe ✓ all locales complete & placeholder-safe exit code: 0
$ kaeris check --source locales/en.json --langs de,fr --ci
✗ de: 1 missing key(s): checkout
✗ de: 1 placeholder mismatch(es):
greeting: missing ['{name}'], added ['{nam}']
✗ de: 2 translation fault(s):
greeting: lost placeholder {name}
greeting: invented placeholder {nam} (not in source)
✓ fr: complete & placeholder-safe
✗ 1 missing key, 1 placeholder mismatch, 2 translation faults
exit code: 1
Set it up in three steps
Install the checker
Run
pip install kaerison the machine or in the CI image that runs your tests.Add the target or the script
Add the
i18n-checktarget to the Makefile or thei18n:checkandpretestscripts topackage.json, with your own--sourceand--langs.Run your usual command
make testornpm testnow runs the check first and stops with a non-zero exit code when a translation is broken.
How we checked this
Every command on this page was run before it was written here. What was not run is listed too.
What ran
npm testwith the scripts above, except thattestwas anecho(npm 11.17, Node 24), and kaeris 0.2.35 from PyPI on the PATH. Clean files: exit code 0, tests ran. Brokende.json: exit code 1, tests did not run.What did not run
makeis not installed on the machine where this was checked. The recipe line was run through the shell, which is what make does with it, so the exit code above is real, but the Makefile itself was not run by make.npm
There is no kaeris package on the npm registry yet, so this page does not send you to npm for it. Node projects call the Python package, as above.
Options worth knowing
Fail on stale keys too
--strictalso fails when a translation has keys that the source no longer has.Keep brand names as written
--glossary 'KAERIS,GitHub'fails a target that dropped one of the terms. The same list can live underkeepinkaeris.json.Different file layout
--outis the folder with the translations and--pattern '{lang}/common.json'their file names. Default: the layoutkaeris translatewrites.No flags at all
With a
kaeris.jsonin the project (kaeris initwrites one),kaeris checktakes the source, languages and folder from it.
Questions
Does it need an API key or an account?
No. kaeris check is described in its own help as static, local and no-API, so the job needs no secret. Translating is a separate command that does need a key.
What does the check catch?
A lost or invented placeholder ({name}, %s, {{x}}, ICU plurals), a missing key and a locale file that is not there. The comparison is local and static. What it checks, with every flag
Does it work without Python?
The checker is a Python package, so the machine that runs the check needs Python 3.8 or newer. The package declares no dependencies.
Keep going
Other recipes: GitHub Actions · GitLab CI · pre-commit
CLI reference · Check reference · GitHub Action reference · Free check in the browser · Translate in the browser