{{name}} in Platform, and load the approved files at runtime.
The same placeholder rules apply to other libraries that interpolate with double braces instead of ICU, including mustache, Handlebars, and many Polyglot-style catalogs that already use %{name}.
hl extract scans React Intl descriptors in .ts and .tsx files. It does not scan t('key') calls. Treat the locale JSON as the source of truth, and fail the pull request when components introduce keys that are missing from locales/en-US.json.
Prerequisites
You need:- an app using i18next or a compatible interpolation library;
- the Hyperlocalise CLI;
- a Platform project with
en-USas source andfr-FRandde-DEas targets; and HYPERLOCALISE_API_KEYandHYPERLOCALISE_PROJECT_IDin your environment.
1. Keep copy in locale JSON
Write nested JSON with stable keys. i18next resolves dotted paths such asfilters.saved.title.
locales/en-US.json:
{{name}}, but they must keep the placeholder name, any format ({{val, number}}), unescape prefixes ({{- html}}), and $t(...) nesting calls.
i18next plurals are sibling keys (
count_one, count_other), not one ICU {count, plural, ...} message. Cover 0, 1, and several items in tests. hl check reports placeholder mismatches on each key; it does not apply icu_shape_mismatch to these suffixes.2. Load catalogs in the app
3. Map the catalogs
Createi18n.yml:
filters.saved.title. It rewrites string leaves and keeps object structure.
If you prefer TypeScript locale modules instead of JSON, map .ts files as described in i18n configuration.
4. Catch missing keys in the source pull request
Installi18next ESLint rules or eslint-plugin-i18next and fail CI when a component calls a key that is missing from the English catalog:
locales/en-US.json with the component change.
5. Push and review
After the source pull request merges:- interpolations such as
{{name}},{{count}}, and{{val, number}}; - unescape prefixes such as
{{- html}}; - nesting calls such as
$t(filters.saved.title); - plural sibling keys for
oneandother; and - labels that must fit compact layouts.
6. Pull and validate translations
Run:hl check reports missing target keys and placeholder mismatches. Interpolation libraries do not use ICU plural blocks, so cover _one / _other branches in tests instead of expecting icu_shape_mismatch.
Troubleshooting
A component shows the key instead of copy
Confirmlocales/en-US.json contains the nested path, i18next.init loads that file, and the t() call uses the same dotted key.
Content Editor flags {{name}} as invalid ICU
Hyperlocalise treats mustache and i18next interpolations as placeholders. If a string also contains real ICU ({count, plural, ...}), keep that ICU valid. Do not rewrite {{name}} to {name}; the runtime looks up name through interpolation, not ICU.
Nested $t(...) disappeared after translation
Restore the exact $t(key) call from the source. Nesting is a runtime lookup, not text to translate.
Pull writes FormatJS-shaped JSON
That happens when the source catalog is strict FormatJS (defaultMessage per id). i18next expects nested string leaves. Keep source JSON in the nested shape shown above.

