formatjs icu message syntax error unexpected token
Covers formatjs ICU unexpected-token parse errors: reproduce with the parser, find the offset, fix quotes and braces. Use it when a message throws at parse time. Not for plural-selection bugs or runtime locale issues.
Fix the formatjs ICU message syntax error on an unexpected token
TL;DR
The ICU parser hit a character it did not expect at a specific offset, so get that offset and look there first. The usual suspects are a stray apostrophe, which starts quoted text in ICU, or a brace that never closes. Fix the character, re-parse, and move on.
The error
SyntaxError: Unexpected token at offset 24
message: "You\u0027ve got {count, plural, one {# message} other {# messages}}"
the doubled quote above is the correct escape, a single quote breaks parsingFix it
Step 1: Reproduce the parse failure with the exact string
node -e "const {parse}=require('@formatjs/icu-messageformat-parser'); parse(process.argv[1])" "You've got {count, plural, one {# message} other {# messages}}"Expected: The parser throws and names the offset.
Step 2: Inspect the character at that offset
node -e "const s=process.argv[1]; const i=24; console.log(JSON.stringify(s.slice(i-6,i+6)))" "You've got {count, plural, one {# message} other {# messages}}"Expected: You see the offending character in context.
Step 3: Fix it: double apostrophes, balance braces
node -e "console.log('write You\u0027\u0027ve for a literal apostrophe in ICU')"Expected: The corrected string parses cleanly.
Step 4: Add the message to your extract lint so it stays fixed
npx formatjs extract 'src/**/*.js' --out-file /tmp/check.json | tail -3Expected: Extraction completes with no syntax errors.
When to use this
- formatjs throws SyntaxError or unexpected token while parsing a message
- A message with apostrophes or quotes fails to parse
When NOT to use this
- The message parses but selects the wrong plural, check locale data
- The error is at runtime in the browser, make sure the parser version matches the runtime
Tool and version compatibility
- @formatjs/icu-messageformat-parser v1/v2, react-intl v5+
- ICU MessageFormat as implemented by formatjs, not Java MessageFormat
Variant phrasings
unexpected token inside a select block
Same approach. Select blocks need an other case, a missing one often reads as an unexpected token at the end.
error only in one locale file
Translators edited the ICU syntax. Diff that locale against the source message and fix the syntax there.
Why it happens
ICU gives special meaning to apostrophes, braces, and the # sign. A translator typing a normal apostrophe accidentally opens a quoted section that never closes, and the parser reports the spot where the grammar stops making sense.
Edge cases
- Smart quotes from word processors are not ICU quotes, normalize to straight quotes first
- The # sign outside a plural case is literal in some versions and an error in others, avoid it
- Argument names are case sensitive, count and Count are different arguments
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_fxBHwFmd-Au2bqNIvu0rGA