hl extract scans React Intl descriptors in .ts and .tsx files. It does not scan .vue templates. 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:- a Vue 3 app using
vue-i18n; - the Hyperlocalise CLI;
- a Cloud 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. vue-i18n resolves dotted paths such asfilters.saved.title.
locales/en-US.json:
zero | one | other) stay one string. Translators may change the prose, but they must keep the | separators and placeholders such as {name} and {n}.
Do not store product copy in SFC
<i18n> blocks for this workflow. Hyperlocalise syncs locale files, not compiled Vue single-file components. If you already use <i18n> blocks, compile them to JSON first and map the JSON files.2. Load catalogs in the app
i18n in main.ts with app.use(i18n).
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
Install@intlify/eslint-plugin-vue-i18n and fail CI when a component calls a key that is missing from the English catalog:
vp lint, npx eslint, or equivalent). The important gate is: new t() / $t() calls cannot merge without a matching English catalog entry.
Commit locales/en-US.json with the component change.
5. Push and review
After the source pull request merges:- pipe plural branches for
0,1, and several items; - placeholders such as
{name}and{n}; - linked messages that start with
@:; - labels that must fit compact Vue layouts; and
- terminology shared with API errors or emails.
6. Pull and validate translations
Run:hl check reports missing target keys and placeholder mismatches. For ICU messages, it also reports icu_shape_mismatch. vue-i18n pipe plurals are one string, so they do not use the ICU shape check; cover those branches in tests instead.
ICU messages in vue-i18n
If your app already uses ICU instead of pipe plurals, store the full message as a single JSON string:hl check can then catch icu_shape_mismatch on the pulled catalogs.
Troubleshooting
A component shows the key instead of copy
Confirmlocales/en-US.json contains the nested path, createI18n loads that file, and the t() call uses the same dotted key.
Nested keys flatten unexpectedly
JSON object keys cannot contain., [, or ]. Use nested objects (filters.saved.title) rather than a key whose name includes a dot.
Pull writes FormatJS-shaped JSON
That happens when the source catalog is strict FormatJS (defaultMessage per id). vue-i18n expects nested string leaves. Keep source JSON in the nested vue-i18n shape shown above.
Linked messages break after translation
A value such as@:filters.saved.title must keep the @: prefix and the target key. Return the segment to review if a translator inlines the English text.

