Skip to content

Polish Plural Forms for 1, 2–4 and 5+ in Generated Text

9 min read · updated August 11, 2026

Polish has four plural categories, not three, and the fourth is the one people miss. The boundaries are published as machine-readable rules by the Unicode Consortium; everything below is derived from that rule text rather than from a summary of it.

The rule text, as published

The source is the CLDR supplemental plural data, browsable as Unicode’s language plural rules chart. For Polish cardinals it defines four categories. In CLDR’s notation, n is the absolute value of the number, i is its integer part, and v is the number of visible decimal digits — so v = 0 means “written without a decimal part”.

one   n = 1
few   v = 0 and i % 10 = 2..4 and i % 100 != 12..14
many  v = 0 and i != 1 and i % 10 = 0..1
      or v = 0 and i % 10 = 5..9
      or v = 0 and i % 100 = 12..14
other  everything else  (i.e. v != 0 — any number written with decimals)

Read many carefully. It is not “5 and above”. It contains 0; it contains every integer ending in 0; it contains every integer ending in 1 except 1 itself; and it contains 12, 13, 14 and their multiples of a hundred.

Every boundary, worked

Using plik (file) — plik / pliki / plików:

n     category  form          why
0     many      0 plików      i % 10 = 0
1     one       1 plik        n = 1 exactly
2     few       2 pliki       i % 10 = 2, i % 100 not in 12..14
4     few       4 pliki       i % 10 = 4
5     many      5 plików      i % 10 = 5..9
9     many      9 plików      i % 10 = 5..9
10    many      10 plików     i % 10 = 0
11    many      11 plików     i % 10 = 1 and i != 1
12    many      12 plików     i % 100 = 12..14  (overrides i % 10 = 2)
13    many      13 plików     i % 100 = 12..14
14    many      14 plików     i % 100 = 12..14
15    many      15 plików     i % 10 = 5..9
20    many      20 plików     i % 10 = 0
21    many      21 plików     i % 10 = 1 and i != 1
22    few       22 pliki      i % 10 = 2, i % 100 = 22 not in 12..14
24    few       24 pliki      i % 10 = 4
25    many      25 plików     i % 10 = 5..9
101   many      101 plików    i % 10 = 1 and i != 1
102   few       102 pliki     i % 100 = 2
112   many      112 plików    i % 100 = 12..14
122   few       122 pliki     i % 100 = 22
1000  many      1000 plików   i % 10 = 0

Two boundaries account for nearly every bug. The first is the 12..14 exception, which pulls 12, 13 and 14 out of few and into many while leaving 112–114 there as well but returning 122–124 to few. The second is 21: unlike Russian, Polish does not send compound numbers ending in 1 back to the singular. 21 plików, not 21 plik. That divergence, and the case history that produced it, is in why Slavic languages need more than one plural category.

CLDR is versioned and its plural data does change — a many category was added to Spanish and French after years at two categories, to support compact notation. Polish’s four categories have been stable, but if you are hard-coding a rule rather than calling a library, pin the CLDR version you derived it from and re-check on upgrade. Everything above is the rule text at the time of writing.

What happens to 1,5 and 0,5

This is the category almost every hand-written implementation omits. Any number written with a visible decimal part — v != 0 — falls into other, regardless of its value, and takes the genitive singular:

0,5 pliku      other   (not "0,5 plików")
1,0 pliku      other   (v = 1, so NOT category one, despite i = 1)
1,5 pliku      other
2,5 pliku      other
10,5 pliku     other

Note 1,0 specifically. The rule for one is n = 1 with no v = 0 clause, but CLDR’s n comparison against a literal is only satisfied when the number has no visible fraction digits, which is why a formatted 1,0 lands in other and a bare 1 does not. If you are formatting file sizes, durations, ratings or currency to one decimal place, this is the branch you will hit constantly and the one your test data probably never contains. Test with 0, 1, 2, 5, 12, 21, 22, 112, 122 and 1,5 and you have covered all four branches and every boundary.

Two things CLDR does not encode

CLDR answers exactly one question: which of a language’s message variants does this number select. It is not a model of Polish grammar, and two Polish facts fall outside it.

  • Masculine personal nouns behave differently. Polish distinguishes a masculine-personal (virile) plural from everything else. 2 pliki and 2 koty use the form above, but for a noun denoting male humans the numeral itself inflects and the construction changes: dwaj studenci or dwóch studentów for two students, and from five upward only pięciu studentów. A four-branch plural message with the non-virile forms in it will be wrong for every noun of this class, and no plural-rules library will tell you, because the category selection was correct — it is the noun form that does not fit.
  • Case is not covered. The forms above are for the phrase in subject position. Put the same phrase after a preposition and everything moves again: w 2 plikach, w 5 plikach, bez 2 plików. If your string embeds the count inside a larger sentence, the plural category alone is not enough to choose the noun form, which is the general argument for translating whole sentences rather than nouns.

Where generated Polish goes wrong

Models handle these forms well in running prose, because the numeral and the noun are adjacent and the pattern is overwhelmingly attested. The failures are concentrated in three places, and all three are structural rather than a matter of the model knowing Polish.

  • Localisation files written from an English source. Given an English string with a singular and a plural, a model returns a singular and a plural, because that is what it was given. The resulting Polish file is missing two branches and no later prompting recovers them — the data structure has no slot. Ask for the four forms by name before you ask for a translation.
  • The genitive plural is the irregular one. plikplików is easy because the suffix is visible, but for feminine and neuter nouns the genitive plural is usually a bare stem with no ending at all, sometimes with a vowel inserted to break up the resulting consonant cluster: kobietakobiet, książka książek, oknookien, wiadomośćwiadomości. A form that is produced by deletion rather than by suffixation is exactly the kind a model regularises, so this is the branch to check first.
  • The 21 trap in review. Reviewers test 1, 2 and 5, find all three correct, and ship. The values that break are 12, 21 and 112, and a wrong form at those counts reads as ordinary Polish to anyone skimming. Put those three in the fixture data.

Using it

Do not implement the rule. Call it: ICU4J, ICU4C, Intl.PluralRules in JavaScript, babel.plural in Python and the equivalents elsewhere all read the same CLDR data, so they agree with each other and update together.

const pr = new Intl.PluralRules("pl");
[0, 1, 2, 5, 12, 21, 22, 112, 122].map((n) => [n, pr.select(n)]);
// [[0,"many"],[1,"one"],[2,"few"],[5,"many"],[12,"many"],
//  [21,"many"],[22,"few"],[112,"many"],[122,"few"]]

new Intl.PluralRules("pl").select(1.5);   // "other"

And when you ask a model to produce Polish strings, ask for the four noun forms rather than for translated sentences with numbers in them. A model given “translate: 5 files found” returns one sentence, correct for 5 and wrong for six of the nine test values above. A model given “give the nominative singular, the form after 2–4, the genitive plural, and the genitive singular of plik” returns exactly the four strings your ICU plural message needs.