Escaping Special Characters in ICU Messages

Learn how to escape curly braces, single quotes, and other special characters in ICU MessageFormat patterns. Covers common pitfalls and solutions for apostrophe handling.

Advanced

Detailed Explanation

Escaping Special Characters in ICU Messages

ICU MessageFormat uses curly braces {} and single quotes ' as special syntax characters. When you need these characters as literal text in your messages, you must escape them properly.

The Single Quote Escape

The single quote ' is the escape character in ICU MessageFormat. It has two uses:

1. Escaping Braces

To include literal curly braces in your message:

This is a JSON example: '{ "key": "value" }'

Everything between matched single quotes is treated as literal text. The braces inside will not be parsed as ICU arguments.

2. Literal Single Quote

To include a literal single quote, double it:

It''s a beautiful day!

Output: "It's a beautiful day!"

Common Pitfalls

Pitfall 1: Unmatched Quotes

// BROKEN: The quote before "s" starts escaping
It's {count} o'clock

The parser sees 's {count} o' as quoted text, swallowing the variable. Fix:

It''s {count} o''clock

Pitfall 2: Quotes Around Arguments

// BROKEN: The argument is inside quotes
The value is '{value}'

This outputs the literal text {value} instead of substituting the variable. Fix by closing the quote before the argument:

The value is ''{value}''

Or restructure to avoid quotes adjacent to arguments.

Pitfall 3: HTML in Messages

When ICU messages contain HTML tags, the angle brackets do not need escaping (they are not special in ICU), but curly braces in CSS or JavaScript do:

// OK: HTML tags are fine
Click <b>{buttonLabel}</b> to continue.

// NEEDS ESCAPING: CSS braces
Add this CSS: '.class '{' color: red; '}'

Library-Specific Differences

Important: The escaping behavior of single quotes differs between ICU4J/ICU4C and the JavaScript FormatJS library:

  • ICU4C / ICU4J: A single quote only starts escaping if it is followed by a special character ({, }, #, |). Otherwise it is treated as literal.
  • FormatJS / messageformat.js: More strict -- any single quote is treated as an escape character.

Always test your messages with your specific library to verify behavior.

Best Practices

  1. Avoid apostrophes in source messages when possible -- rephrase "don't" to "do not"
  2. Always use '' for literal quotes -- this is safe in all implementations
  3. Wrap code blocks in quotes: '{ "json": true }'
  4. Test with edge cases: Messages with apostrophes near variables are the most common source of bugs
  5. Document escaping rules for your translation team

Use Case

Developers and translators working with ICU messages that contain apostrophes (like contractions in English or French), code examples, JSON snippets, or mathematical notation with curly braces.

Try It — ICU Message Format Tester

Open full tool