Different languages handle pluralization differently. English has two forms (one item / many items), but Russian has four, Arabic has six, and Chinese has none. Entri uses ICU Message Format to express these rules in a single string that works across all languages.
ICU (International Components for Unicode) is the industry standard for complex message formatting. It uses a {variable, type, ...options} syntax embedded in your strings.
Plurals
{count, plural, one {# item} other {# items}}
The # symbol is replaced with the value of count. The categories (one, other) follow CLDR plural rules for each language.
Select
Use select to branch on a non-numeric variable, such as grammatical gender:
{gender, select, male {He liked this} female {She liked this} other {They liked this}}
Ordinals
Use selectordinal for rank-style numbers:
{rank, selectordinal, one {#st place} two {#nd place} few {#rd place} other {#th place}}
CLDR plural categories
The Unicode CLDR defines up to six plural categories per language:
| Category | Meaning |
|---|
zero | Exactly zero (or rule-based zero) |
one | Singular form |
two | Dual form (some languages only) |
few | Small numbers (language-specific) |
many | Large numbers (language-specific) |
other | Default / catch-all (required) |
Not all languages use all categories. The other category is always required as the fallback.
Language examples
English
French
Russian
Arabic
Japanese / Chinese
English uses only one and other.{count, plural,
one {# item found}
other {# items found}
}
| count | Output |
|---|
| 0 | 0 items found |
| 1 | 1 item found |
| 2 | 2 items found |
| 100 | 100 items found |
French treats 0 and 1 as singular (one). Numbers 2 and above use other.{count, plural,
one {# élément trouvé}
other {# éléments trouvés}
}
| count | Output |
|---|
| 0 | 0 élément trouvé |
| 1 | 1 élément trouvé |
| 2 | 2 éléments trouvés |
Russian uses one, few, and other, with complex modulo rules.{count, plural,
one {# товар}
few {# товара}
many {# товаров}
other {# товара}
}
| count | Rule | Output |
|---|
| 1, 21, 31 | one | 1 товар |
| 2–4, 22–24 | few | 2 товара |
| 5–20, 25–30 | many | 5 товаров |
Arabic has the most plural forms: zero, one, two, few, many, and other.{count, plural,
zero {لا عناصر}
one {عنصر واحد}
two {عنصران}
few {# عناصر}
many {# عنصرًا}
other {# عنصر}
}
East Asian languages have no plural distinction — all numbers use other.{count, plural,
other {# 件のアイテム}
}
In Japanese, Chinese, Korean, and similar languages, only the other category is needed.
Nesting: plurals inside select
ICU rules can be nested to handle combinations:
{gender, select,
male {{count, plural, one {He found # result} other {He found # results}}}
female {{count, plural, one {She found # result} other {She found # results}}}
other {{count, plural, one {They found # result} other {They found # results}}}
}
Deeply nested ICU expressions can be difficult for translators to work with. Consider simplifying by splitting into separate keys when nesting goes beyond two levels.
Entri editor support
The Entri translation editor provides dedicated input fields for each plural category required by the target language. Translators never need to write ICU syntax manually — the editor shows the appropriate form fields (e.g., one, few, other for Russian) and assembles the final ICU string automatically.
For AI translation, Entri recognizes ICU plural patterns and generates all required plural forms for the target language in a single operation.
Using ICU in your codebase
ICU is supported by popular i18n libraries:
| Library | Platform | ICU support |
|---|
react-i18next | React | Via i18next-icu plugin |
FormatJS / react-intl | React | Native |
Lingui | React | Native |
vue-i18n | Vue | Native |
Angular i18n | Angular | Native |
Flutter intl | Flutter (ARB) | Native |
ICU message format is stored as a plain string in your locale files. Any format that supports arbitrary string values — json-flat, json-nested, yaml, po, arb — can hold ICU strings without modification. The ICU parsing happens at runtime in your i18n library.
{
"item_count": "{count, plural, one {# item} other {# items}}",
"welcome": "Welcome, {name}!"
}