---
title: "How do I write plural messages in ICU message format?"
description: "Use a plural argument such as `{count, plural, one {# item} other {# items}}`. `#` prints the number formatted for the locale, `=0` matches an exact value, and the branch names are the CLDR plural categories of the target language, with `other` always required."
category: icu-message-format
date: 2026-10-09
canonical: https://localizely.com/i18n-questions/icu-message-format/how-do-i-write-plural-messages-in-icu-message-format/
---

# How do I write plural messages in ICU message format?

Use a `plural` argument. Its branches are named after the CLDR plural categories of the message's language, `#` is replaced by the number formatted for that locale, and the `other` branch is mandatory.

```icu-message-format
{count, plural, =0 {No items} one {# item} other {# items}}
```

In English this prints `No items`, `1 item` and `1,000 items` for 0, 1 and 1000.

Selection happens in two steps. The value is first compared with the exact matches (`=0`, `=1` and so on). If none applies, the locale's plural rules map it to one of the categories `zero`, `one`, `two`, `few`, `many` and `other`, and a category without a branch falls back to `other`. Which categories a language uses differs: English has `one` and `other`, Russian has `one`, `few`, `many` and `other`, Arabic uses all six and Japanese only `other`. The per-language lists are in the [CLDR plural rules chart](https://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html) and on the [language plural rules](/language-plural-rules/) page.

`offset:n` subtracts `n` before the category is chosen and before `#` is printed, while the exact matches still see the original value:

```icu-message-format
{count, plural, offset:1
  =0 {Nobody liked this}
  =1 {You liked this}
  one {You and # other person liked this}
  other {You and # others liked this}}
```

For 3 this prints `You and 2 others liked this`.

Java's `java.text.MessageFormat` has no `plural` type. Its `ChoiceFormat` picks a branch by numeric range and, as its [javadoc](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/text/ChoiceFormat.html) states, "doesn't implement any locale specific behavior", so it cannot produce the Russian or Arabic forms. Use ICU4J's [`com.ibm.icu.text.MessageFormat`](https://unicode-org.github.io/icu-docs/apidoc/released/icu4j/com/ibm/icu/text/MessageFormat.html) (Maven artifact `com.ibm.icu:icu4j`), which takes named arguments in a map:

```java
import com.ibm.icu.text.MessageFormat;
import java.util.Locale;
import java.util.Map;

String pattern = "{count, plural, one {# файл} few {# файла} many {# файлов} other {# файла}}";
MessageFormat format = new MessageFormat(pattern, Locale.forLanguageTag("ru"));
String text = format.format(Map.of("count", 21)); // "21 файл"
```

Translators must write the categories of their own language instead of copying the source branches. An English `one`/`other` message translated into Polish needs `one`, `few`, `many` and `other`; with `few` missing, 2 would print the `other` form. The [ICU message format for translators](/icu-message-format-for-translators/) page explains this from the translator's side, and the [ICU message editor](/icu-message-editor/) shows which branch a value selects in a given language.

Source: https://localizely.com/i18n-questions/icu-message-format/how-do-i-write-plural-messages-in-icu-message-format/
