.pot template. Hyperlocalise syncs the resulting .po catalogs for translation and review.
Hyperlocalise reads .po and .pot catalogs, including msgctxt, translator comments, and gettext plural forms. Plural strings are one entry per category (one, other, and the extra categories the target language needs). Writeback fills msgstr[n] for that language and updates the catalog header.
Prerequisites
You need:- a backend that uses GNU Gettext-compatible catalogs;
xgettext,msginit, andmsgmerge;- the Hyperlocalise CLI;
- a Platform project with
en-USas source andfr-FRandde-DEas targets; and HYPERLOCALISE_API_KEYandHYPERLOCALISE_PROJECT_IDin your environment.
1. Mark backend messages
The exact API depends on your language. A Python service might use:{name} between source and target.
Add translator comments when your extraction tool supports them:
2. Extract a POT template
Run the command appropriate for your backend. For Python:messages.pot. You can map the .pot file directly. Hyperlocalise reads an empty msgstr as the msgid text. A source-language .po whose msgstr already holds the English text works the same way.
3. Create and update the source PO catalog
Create the English catalog once:msgid as the stable key. A populated msgstr is the source text. An empty msgstr falls back to msgid, which is what a .pot template contains. msgctxt is part of the key (context||msgid). Plural forms use keys such as msgid||one and msgid||other.
4. Map PO catalogs
Createi18n.yml:
5. Check extraction drift
In the source pull request, regenerate the template and update the source PO:xgettext and msgmerge commands in scripts/extract-messages.sh so local and CI extraction agree.
This gate catches messages added in code without an updated catalog.
6. Push and review messages
After merge:- placeholders such as
{name}or%s; - Unreal Engine rich-text tags such as
<Highlight>Ready</>and<img id="Health"/>; - translator comments and source references;
- punctuation produced by the surrounding code;
- terminology shared with API errors and emails; and
- strings that may reach logs instead of end users.
7. Pull and validate PO files
Run:msgfmt validates PO syntax and format strings. Inspect each target header after pull and set runtime-specific Language, encoding, or domain metadata when your framework requires it.
Compile catalogs as part of the build:
.mo files during build or release. Avoid committing them unless your deployment process requires compiled catalogs in git.
8. Test the backend
Open a translation pull request and test:- locale negotiation selects the expected catalog;
- placeholders interpolate without exceptions;
- missing translations follow your intended fallback;
- API responses preserve machine-readable error codes; and
- translated emails or HTML remain escaped correctly.
msgid values.
Troubleshooting
Context variants used to overwrite each other
They no longer do. Eachmsgctxt is part of the key: nav||Open and forum||Open are different strings. The first run after this change translates context-specific and plural strings again, because their keys changed.
A plural file has more msgstr lines than the source
That is expected for languages with more plural categories than the source. Arabic gets six forms. Categories without their own translation are filled from other. The header Plural-Forms line matches the target language.
Empty msgstr became the msgid text
That is the .pot and Crowdin default. Put the real source text in msgstr, or set X-Crowdin-SourceKey: msgstr in the header when an empty msgstr must stay empty.
Unreal Engine rich-text tags look like chips
That is expected. Unreal style tags close with nameless</>. Hyperlocalise shows each recognized tag as a placeholder chip such as UE#0. Keep every chip and translate the words between them. {ItemName} inside a style pair stays a separate placeholder. Downloaded .po files contain the original Unreal markup.
See Unreal Engine rich text in gettext PO for the tag grammar Hyperlocalise recognizes.

