shipglot

icu-syntax

ICU message does not parse, or select options differ from the source.

Default severity: error

What it checks

ICU MessageFormat messages (next-intl, FormatJS, Flutter ARB) must parse: balanced braces, known argument types, an `other` option in every plural and select, matching rich-text tags. A message that fails to parse throws at runtime or renders the raw text. Select options (e.g. male/female/other) are values the code passes, so the translation must keep exactly the source's options.

Example

An ICU plural with a missing closing brace. Config used for both runs:

{
  "sourceLocale": "en",
  "files": [
    {
      "format": "next-intl-json",
      "path": "messages/{locale}.json"
    }
  ]
}

Fails

messages/en.json

{
  "items": "{count, plural, one {# item} other {# items}}"
}

messages/fr.json

{
  "items": "{count, plural, one {# article} other {# articles}"
}

Gate output

  • erroricu-syntaxfr
    items
    invalid ICU message: unclosed argument, expected } at offset 0
    messages/fr.json:2

Passes

messages/en.json

{
  "items": "{count, plural, one {# item} other {# items}}"
}

messages/fr.json

{
  "items": "{count, plural, one {# article} other {# articles}}"
}

Gate output

No icu-syntax finding.

Other checks reported:

  • items
    plural {count} has no 'many' form (used for 1,000,000 and above in fr)
    messages/fr.json:2

Change its severity

{
  "checks": {
    "icu-syntax": "warning"
  }
}

Use "off" to disable it. To hide one finding, add "suppress": ["icu-syntax:items"]; a suppress rule that stops matching is reported so it can be removed.

All checks