How to pluralise translations

Piko implements Common Locale Data Repository (CLDR) plural rules so a single key handles all plural forms of every supported language. Separate forms with the pipe character (|) and call .Count(n) on the translation. For the basic English case and the Count API see i18n API reference.

Write English-style two-form plurals

{
  "items": "one item|${count} items"
}
T("items").Count(0)  // "0 items"
T("items").Count(1)  // "one item"
T("items").Count(5)  // "5 items"

The first form covers the singular (n == 1). Every other count uses the second form.

Write two-form plurals for French

French treats both 0 and 1 as singular:

{
  "articles": "un article|${count} articles"
}
T("articles").Count(0)  // "un article"
T("articles").Count(1)  // "un article"
T("articles").Count(2)  // "2 articles"

Piko selects the form using the locale's CLDR rules, so the same key produces different output in en and fr without per-language code.

Write Slavic three-form plurals

Russian, Ukrainian, Belarusian, Serbian, Croatian, and Bosnian need three forms based on the last digits:

{
  "apples": "${n} яблоко|${n} яблока|${n} яблок"
}
CLDR categoryFormExample counts
OneFirst1, 21, 31, 101, 121
FewSecond2-4, 22-24, 32-34
ManyThird0, 5-20, 25-30, 100

Write Polish three-form plurals

Polish uses three forms but its rule differs from the rest of the Slavic group. Only 1 is the One form. The example counts above for 21, 31, 101, and 121 fall into the Many form in Polish, not One.

{
  "apples": "${n} jabłko|${n} jabłka|${n} jabłek"
}
CLDR categoryFormExample counts
OneFirst1
FewSecond2-4, 22-24, 32-34
ManyThird0, 5-21, 25-31, 100, 101, 121

Write Arabic six-form plurals

Arabic carries the most categories:

{
  "items": "صفر|واحد|اثنان|قليل|كثير|آخر"
}
CLDR categoryFormExample counts
ZeroFirst0
OneSecond1
TwoThird2
FewFourth3-10
ManyFifth11-99
OtherSixth100+

Write single-form translations for East Asian languages

Chinese, Japanese, Korean, Vietnamese, Thai, Indonesian, and Malay use one form regardless of count. Provide a single string with no pipe separator:

{
  "items": "${count}个项目"
}

Count(n) substitutes ${count} and returns the same string for every value of n.

Escape a literal pipe

A double pipe (||) emits a single literal |:

{
  "options": "Option A || B|Options: ${count}"
}

The first form contains a literal pipe between A and B. The pipe between the two forms still acts as the separator.

See also