hyperlocalise check on that locale and key.
An icu_shape_mismatch can also reflect the CLI’s strict branch-parity rules,
not just an invalid message. See locale-specific plurals
below before changing a linguistically correct translation.
Find the failing message
From a configured project, run:es-ES:
--file, when needed, selects the configured source file path. See
check for all scope filters.
Understand the finding
One message can produce multiple findings. Fix the underlying message before
changing validation settings.
Restore a renamed argument
Source JSON:name, so renaming it to nombre breaks the contract. Keep the
argument name in the translated message:
defaultMessage rather than replacing the descriptor object.
i18next and mustache catalogs use interpolation instead of ICU. Keep the double
braces and the placeholder name:
{nombre} or {name} is not the same placeholder. Restore
{{name}}. Formats ({{val, number}}), unescape prefixes ({{- html}}), and
nesting calls ($t(help.link)) must also match the source. See
i18next and interpolation placeholders.
Restore a missing plural branch
Source:one branch removed:
count, the plural type, and the structural tokens. Review
offset: values and exact-number branches such as =0 when present. ICU keywords
are syntax, not text to translate. See the FormatJS ICU syntax guide.
The CLI also flags duplicate # tokens within a plural/selectordinal branch.
That is a CLI validation constraint, not a claim that every repeated number is
invalid ICU.
Repair malformed ICU syntax
An unmatched brace or missing requiredother branch can make a message fail to
parse. Compare the whole source and target expression, including nested branches.
Check the source too. The current parity comparison cannot reliably diagnose all
cases when the source itself fails ICU parsing. A clean CLI check is not a substitute
for parsing and rendering messages in your application’s i18n runtime.
For rich-text messages, preserve the tags and values your React Intl components
expect. A tag check can catch structural changes, but it cannot prove that your app
supplies every required rendering function.
Unreal Engine gettext .po catalogs use nameless </> style tags. Hyperlocalise
shows those tags as chips such as UE#0. Keep every chip. {ItemName} inside a
style pair is a separate placeholder. See Unreal Engine rich text in gettext PO.
Validate the repaired message
0, 1, and 2, and any exact-number or nested select branches you use.
Can the CLI repair the translation?
check --fix retranslates fixable entries using your configured provider. Preview
one key first:
--fix.
What if the target language needs different plural categories?
Plural categories depend on the locale. A target may drop or add CLDR categories such asone, few, or many. icu_shape_mismatch still requires matching
argument names, block types, offsets, and exact matches (=0, =1).
unreachable_plural_case flags a category the target locale never selects. Japanese
has no one category, so delete that branch and keep other. Do not remove a
needed grammatical form to silence the check. Cover 0, 1, and several items
in runtime tests.
Prevent repeat failures
- Add descriptions explaining what argument values represent.
- Keep source ICU expressions valid and test their branches.
- Review both language quality and runtime behavior after translation.
- Add GitHub Actions validation to catch regressions.

