What Is ICU MessageFormat? Plurals, Select, and Placeholders Explained
ICU MessageFormat is the standard syntax for strings that change with a number or a choice — plurals, select, and placeholders. Here is how it works and where the syntax bites.
ICU MessageFormat is a syntax for writing strings that vary based on a number or a category — "1 item" versus "2 items", or gender- and platform-specific phrasing. It comes from the International Components for Unicode (ICU) project, and it is supported across Flutter ARB, iOS .stringsdict / String Catalogs, and i18next. If you localize an app, you will eventually write it.
The problem ICU solves
You cannot translate plurals by gluing a number to a noun. English has two forms ("1 item", "2 items"); Ukrainian has three; Arabic has six. Hard-coding "$count items" produces broken grammar in most of the world. ICU lets one string express every form, and the runtime picks the right one for the active locale and number.
Plural syntax
{count, plural, one {# item} other {# items}}
count— the variable the rule keys off.plural— the message type.one,other— plural categories.#is replaced by the number at runtime.
ICU defines six plural categories — zero, one, two, few, many, and other. Languages use different subsets: English uses only one and other; Ukrainian uses one, few, and other; Arabic uses all six. other is always required — it is the fallback when no other category matches.
Select syntax
select branches on an arbitrary string value rather than a number — most often grammatical gender:
{gender, select, male {He liked this} female {She liked this} other {They liked this}}
Like plural, select requires an other branch.
Where ICU bites
The syntax is unforgiving. A missing brace, a dropped category, or an other branch that got lost in translation produces a string that compiles but renders wrong — or crashes the formatter. The common failure modes are:
- A translator deletes the
otherbranch a language needs. - A required plural category for the target language is missing.
- Braces get unbalanced during editing.
- A placeholder like
{count}survives in the source but vanishes from a translation.
These are hard to catch by reading raw files, because the error is structural, not a typo you can see.
How StringLane works with ICU
StringLane validates ICU MessageFormat as you type. Its validation engine checks that each locale carries the plural categories its language requires, flags malformed or unbalanced syntax, and surfaces missing placeholders — all inline, per cell. When the structure is broken, Fix with AI repairs the ICU skeleton while preserving your translated text, so you do not have to retranslate.
Next steps
- Working with ICU Plurals and Select Forms — write and validate ICU strings hands-on.
- How to Read Validation Badges — what the ICU, Param, and Missing badges mean.
- How to Fix Issues with AI — repair ICU and placeholder errors without retranslating.