Score your React Intl message files on every push and fail the build when a locale regresses.
React Intl (FormatJS) falls back to the default message or the message id when a translation is missing, so an untranslated id ships without an error. Extraction and compilation steps make gaps easy to miss across locales.
Polylens scans your compiled FormatJS message JSON, scores each locale, and lists every missing message, broken ICU argument, malformed plural and stale string, then fails CI on regression. One curl call, strings stay in your repo.
Locale format: JSON message catalogs (lang/{locale}.json). Point the gate at your compiled message catalog directory.
FormatJS uses the default message or id when a translation is absent. Polylens flags every missing message per locale.
A translator who drops {count} or {name} breaks the formatted output. Polylens diffs every ICU argument.
An ICU plural that loses a branch renders raw syntax. Polylens validates every plural and select block.
A reworded source leaves old translations live. Polylens detects staleness from scan history alone.
name: i18n health
on:
pull_request:
paths: ['lang/**']
jobs:
polylens:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: curl -fsSO https://polylens.sh/polylens-ci.mjs
- run: node polylens-ci.mjs ./lang
env:
POLYLENS_TOKEN: ${{ secrets.POLYLENS_TOKEN }}
FAIL_ON: error
NO_REGRESSION: 'true'Add your project token as the POLYLENS_TOKEN repository secret. A failing gate returns HTTP 422, so the build goes red like any other test.
Add one step to your pipeline that posts your locale files to Polylens. The gate returns HTTP 422 when a language regresses, so the build fails like any other test. No SDK, one curl call, and your strings never leave your repo.
Yes. Missing keys are the first of 13 issue classes Polylens detects, alongside broken placeholders, untranslated copy, malformed plurals, and stale strings. Every missing key is listed per language in the dashboard.
No. React Intl renders your translations at runtime; Polylens is the quality gate that scores the locale files before they ship. They sit on opposite ends of the pipeline and work together.
Wire React Intl (FormatJS) into a CI gate in ten minutes. Free for one project, no card, strings stay in your repo.