Skip to main content
This tutorial connects an app that uses Mozilla Fluent .ftl files to Hyperlocalise Platform. You keep message and attribute values in the repository, review them in Platform, and load the approved files with @fluent/bundle or @fluent/react. Hyperlocalise supports a subset of Fluent. Message IDs become keys. Attributes become dotted keys such as login.title. Term definitions (-brand) and term references ({ -brand }) are rejected.

Prerequisites

You need:
  • an app that loads .ftl catalogs with Fluent.js or another Fluent runtime;
  • the Hyperlocalise CLI;
  • a Platform project with en-US as source and fr-FR and de-DE as targets; and
  • HYPERLOCALISE_API_KEY and HYPERLOCALISE_PROJECT_ID in your environment.
The example uses:

1. Keep copy in Fluent

locales/en-US/messages.ftl:
Use those messages from React:
Comments above a message become CAT context. # comments attach to the next message. ## group comments and ### file comments do not.
Do not put -brand = Hyperlocalise or { -brand } in a mapped .ftl file. Hyperlocalise rejects terms so they are not silently dropped. Inline the brand name, or keep terms in a file outside this bucket.

2. Map the catalogs

Create i18n.yml:

3. Load approved files

Wrap the tree in LocalizationProvider when you use @fluent/react.

4. Push and review

After the source pull request merges:
Start generation through a Source upload automation or New Request. In Content Editor, review:
  • variables such as { $name } and { $count };
  • select variants, including the * default;
  • attributes such as login.title;
  • message comments that explain where the copy appears.
Approve the translations before pulling them back. A select pattern stays one value. Translators may change the words inside [one] and *[other]. They must keep the variable names and a default variant.

5. Pull and validate translations

Run:
hl check reports missing target keys and placeholder mismatches on { $name }. Fluent selectors are not ICU plural blocks, so do not expect icu_shape_mismatch or unreachable_plural_case to understand [one] / *[other]. Cover 0, 1, and several items in runtime tests:
Open a translation pull request containing the pulled .ftl files.

Troubleshooting

Upload fails on a term

Remove -brand definitions and { -brand } references from the mapped file. Fluent terms are unsupported.

A new .title attribute disappeared on writeback

Hyperlocalise cannot append a new attribute to a parent that already exists in the target template. Add the attribute to the source and target files together, or start from a target that does not yet contain that parent.

The app shows the message id

Confirm locales/en-US/messages.ftl contains the id, FluentBundle.addResource loaded that file without errors, and Localized uses the same id.

Placeholders are flagged after a natural translation

Restore { $name } exactly, including the dollar sign and spacing your source uses. Do not rewrite Fluent variables to ICU {name}.

Next