hl extract scans React Intl descriptors in .ts and .tsx files. It does not scan t('title') or useTranslations. Treat the locale JSON as the source of truth, and fail the pull request when a component key is missing from messages/en-US.json.
Prerequisites
You need:- a Next.js App Router app using
next-intl; - 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. next-intl resolves dotted paths such asfilters.saved.title.
messages/en-US.json:
{name}, {count}, valid plural syntax, and rich-text tag names such as <guidelines>.
Do not set the file’s message format to i18next. next-intl uses ICU
{name} and tags, not {{name}}. Leave the format on Auto or ICU.2. Load catalogs in the app
getTranslations from next-intl/server. Wrap Client Components in NextIntlClientProvider so they inherit the same messages.
3. Map the catalogs
Createi18n.yml:
filters.saved.title. It rewrites string leaves and keeps object structure.
If you split messages into several files per locale, add one mapping per file or merge the files before getRequestConfig loads them.
4. Catch missing keys in the source pull request
Type the English catalog intonext-intl so TypeScript fails when a component calls a missing key:
messages/en-US.json with the component change.
5. Push and review
After the source pull request merges:- ICU arguments such as
{name}and{count}; - plural and select branches, including locale-specific categories;
- rich-text tags such as
<guidelines>; - labels that must fit compact layouts.
one and keep other. hl check reports unreachable_plural_case when a translation keeps a category the locale never selects.
6. Pull and validate translations
Run:hl check reports missing target keys, placeholder mismatches, icu_shape_mismatch, and unreachable_plural_case.
Troubleshooting
A component shows the key instead of copy
Confirmmessages/en-US.json contains the nested path, getRequestConfig imports that file, and useTranslations uses the same namespace.
Content Editor flags <guidelines> as an HTML mismatch
Keep the same tag names in the translation. next-intl maps those names to React at the call site. Do not translate guidelines inside the angle brackets.
Pull writes FormatJS-shaped JSON
That happens when the source catalog is strict FormatJS (defaultMessage per id). next-intl expects nested string leaves. Keep source JSON in the nested shape shown above.
icu_shape_mismatch after a locale-specific plural
Argument names, block types, offsets, and exact matches such as =0 must still match the source. CLDR categories may differ by locale. If hl check reports unreachable_plural_case, delete the unused case from the translation.

