Translate

Check translations in GitHub Actions

A translation that drops {name} or skips a key breaks the app at runtime, and review rarely catches it. This workflow runs kaeris check on every pull request and turns the job red. It is offline and free: no API key, no account.

The recipe

The workflow

Save it as .github/workflows/i18n-check.yml. Change source to your base-language file and languages to the locales you ship.

Config.github/workflows/i18n-check.yml
name: i18n check
on: pull_request
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: kaeris-io/kaeris-action@v1
        with:
          mode: check
          source: locales/en.json
          languages: de,fr

Without Python: npx

The npm package kaeris runs the same check on Node 18 or newer; npx fetches it, so there is no install step. It has only check: translating needs the Python package.

Config.github/workflows/i18n-check.yml (steps)
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npx kaeris check --source locales/en.json --langs de,fr

The same without the Action

Plain steps with Python and pip. The log then shows every finding line by line instead of the table the Action prints.

Config.github/workflows/i18n-check.yml (steps)
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install kaeris
      - run: kaeris check --source locales/en.json --langs de,fr --ci

Findings on the exact line of the pull request (optional)

The Action can also write a SARIF report; uploading it turns each finding into an annotation in the diff. Code-scanning uploads are free on public repositories; private ones need GitHub Advanced Security.

Config.github/workflows/i18n-check.yml
name: i18n check
on: pull_request
permissions:
  contents: read
  security-events: write
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: kaeris-io/kaeris-action@v1
        with:
          mode: check
          source: locales/en.json
          languages: de,fr
          sarif-file: kaeris.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: kaeris.sarif

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.

What the job prints

The Action prints a summary table per language and ends with the error line when something is wrong. Left: files that are fine. Right: de.json with {nam} instead of {name} and the checkout key missing.

Files that are fineAction step output
## KAERIS i18n — CI check

Placeholder-loss: **0** (should be 0).

| Language | Status | Missing | Placeholder issues | Translated |
|---|---|---|---|---|
| de | ✓ complete | 0 | 0 | – |
| fr | ✓ complete | 0 | 0 | – |

_Generated from `kaeris check --json` — no fabricated numbers._
step exit=0
--- GITHUB_OUTPUT (without summary body):
missing=0
placeholder-issues=0
changed=false
check-exit-code=0
translate-exit-code=0
A broken translationAction step output
## KAERIS i18n — CI check

Placeholder-loss: **1** (should be 0).
Missing keys remaining: **1**.

| Language | Status | Missing | Placeholder issues | Translated |
|---|---|---|---|---|
| de | ⚠ 1 missing, 1 placeholder issue | 1 | 1 | – |
| fr | ✓ complete | 0 | 0 | – |

_Generated from `kaeris check --json` — no fabricated numbers._
::error::kaeris check found incomplete/broken translations — see the job summary for the language matrix
step exit=1
--- GITHUB_OUTPUT (without summary body):
missing=1
placeholder-issues=1
changed=false
check-exit-code=1
translate-exit-code=0

What the npx step prints

The same project checked with npx: kaeris 0.2.37 from npm, an empty npm cache and CI=true, as on a fresh runner. The first line is npm fetching the package.

Files that are finenpx step output
$ npx kaeris check --source locales/en.json --langs de,fr
npm warn exec The following package was not found and will be installed: [email protected]
✓ de: complete & placeholder-safe
✓ fr: complete & placeholder-safe
✓ all locales complete & placeholder-safe
exit code: 0
A broken translationnpx step output
$ npx kaeris check --source locales/en.json --langs de,fr
npm warn exec The following package was not found and will be installed: [email protected]
✗ 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

  1. Save the workflow

    Create .github/workflows/i18n-check.yml with the workflow above, with your own source and languages.

  2. Open a pull request

    Push a branch that changes a locale file. The job runs on every pull request and goes red on a lost placeholder or a missing key.

  3. Make the check required

    In the repository settings, add the job as a required status check in branch protection. A red job then blocks the merge.

How we checked this

Every command on this page was run before it was written here. What was not run is listed too.

Options worth knowing

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.

Which file formats does it read?

The help of kaeris check lists JSON, ARB, YAML, .strings, .xcstrings, .po, Android XML, CSV, XLIFF, .properties, .resx, Fluent and Markdown as source formats (kaeris 0.2.35 and newer). Guides by format

What makes the job fail?

The exit code of kaeris check: 0 clean, 1 a problem was found, 2 wrong usage or a file it cannot read. A problem the check calls red fails the job; strict makes stale keys fail as well. GitHub Action reference

Keep going

Other recipes: GitLab CI · pre-commit · Make and npm scripts

CLI reference · Check reference · GitHub Action reference · Free check in the browser · Translate in the browser