1"""
2babel.messages.plurals
3~~~~~~~~~~~~~~~~~~~~~~
4
5Plural form definitions.
6
7:copyright: (c) 2013-2026 by the Babel Team.
8:license: BSD, see LICENSE for more details.
9"""
10
11from __future__ import annotations
12
13from babel.core import Locale, default_locale
14
15# XXX: remove this file, duplication with babel.plural
16
17
18LC_CTYPE: str | None = default_locale('LC_CTYPE')
19
20# Generated with scripts/dump_plurals_dict.py
21PLURALS: dict[str, tuple[int, str]] = {
22 # Afrikaans
23 'af': (2, '(n != 1)'),
24 # Akan
25 'ak': (2, '(n > 1)'),
26 # Amharic
27 'am': (2, '(n > 1)'),
28 # Aragonese
29 'an': (2, '(n != 1)'),
30 # Arabic
31 'ar': (6, '(n == 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5)'),
32 # Assamese
33 'as': (2, '(n > 1)'),
34 # Asu
35 'asa': (2, '(n != 1)'),
36 # Asturian
37 'ast': (2, '(n != 1)'),
38 # Azerbaijani
39 'az': (2, '(n != 1)'),
40 # Baluchi
41 'bal': (2, '(n != 1)'),
42 # Belarusian
43 'be': (3, 'n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : 2'),
44 # Bemba
45 'bem': (2, '(n != 1)'),
46 # Bena
47 'bez': (2, '(n != 1)'),
48 # Bulgarian
49 'bg': (2, '(n != 1)'),
50 # Bhojpuri
51 'bho': (2, '(n > 1)'),
52 # Anii
53 'blo': (3, '(n == 0 ? 0 : n == 1 ? 1 : 2)'),
54 # Bambara
55 'bm': (1, '0'),
56 # Bangla
57 'bn': (2, '(n > 1)'),
58 # Tibetan
59 'bo': (1, '0'),
60 # Breton
61 'br': (5, 'n % 10 == 1 && n % 100 != 11 && n % 100 != 71 && n % 100 != 91 ? 0 : n % 10 == 2 && n % 100 != 12 && n % 100 != 72 && n % 100 != 92 ? 1 : ((n % 10 == 3 || n % 10 == 4) || n % 10 == 9) && (n % 100 < 10 || n % 100 > 19) && (n % 100 < 70 || n % 100 > 79) && (n % 100 < 90 || n % 100 > 99) ? 2 : n != 0 && n % 1000000 == 0 ? 3 : 4'),
62 # Bodo
63 'brx': (2, '(n != 1)'),
64 # Bosnian
65 'bs': (3, 'n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : 2'),
66 # Catalan
67 'ca': (3, '(n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2)'),
68 # Chechen
69 'ce': (2, '(n != 1)'),
70 # Cebuano
71 'ceb': (2, 'n != 1 && n != 2 && n != 3 && (n % 10 == 4 || n % 10 == 6 || n % 10 == 9)'),
72 # Chiga
73 'cgg': (2, '(n != 1)'),
74 # Cherokee
75 'chr': (2, '(n != 1)'),
76 # Central Kurdish
77 'ckb': (2, '(n != 1)'),
78 # Czech
79 'cs': (3, '(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2)'),
80 # Swampy Cree
81 'csw': (2, '(n > 1)'),
82 # Chuvash
83 'cv': (3, '(n == 0 ? 0 : n == 1 ? 1 : 2)'),
84 # Welsh
85 'cy': (6, '(n == 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n == 3 ? 3 : n == 6 ? 4 : 5)'),
86 # Danish
87 'da': (2, '(n != 1)'),
88 # German
89 'de': (2, '(n != 1)'),
90 # Dogri
91 'doi': (2, '(n > 1)'),
92 # Lower Sorbian
93 'dsb': (4, 'n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : (n % 100 == 3 || n % 100 == 4) ? 2 : 3'),
94 # Divehi
95 'dv': (2, '(n != 1)'),
96 # Dzongkha
97 'dz': (1, '0'),
98 # Ewe
99 'ee': (2, '(n != 1)'),
100 # Greek
101 'el': (2, '(n != 1)'),
102 # English
103 'en': (2, '(n != 1)'),
104 # Esperanto
105 'eo': (2, '(n != 1)'),
106 # Spanish
107 'es': (3, '(n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2)'),
108 # Estonian
109 'et': (2, '(n != 1)'),
110 # Basque
111 'eu': (2, '(n != 1)'),
112 # Persian
113 'fa': (2, '(n > 1)'),
114 # Fula
115 'ff': (2, '(n > 1)'),
116 # Finnish
117 'fi': (2, '(n != 1)'),
118 # Filipino
119 'fil': (2, 'n != 1 && n != 2 && n != 3 && (n % 10 == 4 || n % 10 == 6 || n % 10 == 9)'),
120 # Faroese
121 'fo': (2, '(n != 1)'),
122 # French
123 'fr': (3, '(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2'),
124 # Friulian
125 'fur': (2, '(n != 1)'),
126 # Western Frisian
127 'fy': (2, '(n != 1)'),
128 # Irish
129 'ga': (5, '(n == 1 ? 0 : n == 2 ? 1 : n >= 3 && n <= 6 ? 2 : n >= 7 && n <= 10 ? 3 : 4)'),
130 # Scottish Gaelic
131 'gd': (4, '(n == 1 || n == 11) ? 0 : (n == 2 || n == 12) ? 1 : (n >= 3 && n <= 10 || n >= 13 && n <= 19) ? 2 : 3'),
132 # Galician
133 'gl': (2, '(n != 1)'),
134 # Swiss German
135 'gsw': (2, '(n != 1)'),
136 # Gujarati
137 'gu': (2, '(n > 1)'),
138 # Manx
139 'gv': (4, 'n % 10 == 1 ? 0 : n % 10 == 2 ? 1 : (n % 100 == 0 || n % 100 == 20 || n % 100 == 40 || n % 100 == 60 || n % 100 == 80) ? 2 : 3'),
140 # Hausa
141 'ha': (2, '(n != 1)'),
142 # Hawaiian
143 'haw': (2, '(n != 1)'),
144 # Hebrew
145 'he': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
146 # Hindi
147 'hi': (2, '(n > 1)'),
148 # Hmong Njua
149 'hnj': (1, '0'),
150 # Croatian
151 'hr': (3, 'n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : 2'),
152 # Upper Sorbian
153 'hsb': (4, 'n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : (n % 100 == 3 || n % 100 == 4) ? 2 : 3'),
154 # Hungarian
155 'hu': (2, '(n != 1)'),
156 # Armenian
157 'hy': (2, '(n > 1)'),
158 # Interlingua
159 'ia': (2, '(n != 1)'),
160 # Indonesian
161 'id': (1, '0'),
162 # Interlingue
163 'ie': (2, '(n != 1)'),
164 # Igbo
165 'ig': (1, '0'),
166 # Sichuan Yi
167 'ii': (1, '0'),
168 # Ido
169 'io': (2, '(n != 1)'),
170 # Icelandic
171 'is': (2, '(n % 10 != 1 || n % 100 == 11)'),
172 # Italian
173 'it': (3, '(n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2)'),
174 # Inuktitut
175 'iu': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
176 # Japanese
177 'ja': (1, '0'),
178 # Lojban
179 'jbo': (1, '0'),
180 # Ngomba
181 'jgo': (2, '(n != 1)'),
182 # Machame
183 'jmc': (2, '(n != 1)'),
184 # Javanese
185 'jv': (1, '0'),
186 # Georgian
187 'ka': (2, '(n != 1)'),
188 # Kabyle
189 'kab': (2, '(n > 1)'),
190 # Jju
191 'kaj': (2, '(n != 1)'),
192 # Tyap
193 'kcg': (2, '(n != 1)'),
194 # Makonde
195 'kde': (1, '0'),
196 # Kabuverdianu
197 'kea': (1, '0'),
198 # Kazakh
199 'kk': (2, '(n != 1)'),
200 # Kako
201 'kkj': (2, '(n != 1)'),
202 # Kalaallisut
203 'kl': (2, '(n != 1)'),
204 # Khmer
205 'km': (1, '0'),
206 # Kannada
207 'kn': (2, '(n > 1)'),
208 # Korean
209 'ko': (1, '0'),
210 # Konkani
211 'kok': (2, '(n > 1)'),
212 # Kashmiri
213 'ks': (2, '(n != 1)'),
214 # Shambala
215 'ksb': (2, '(n != 1)'),
216 # Colognian
217 'ksh': (3, '(n == 0 ? 0 : n == 1 ? 1 : 2)'),
218 # Kurdish
219 'ku': (2, '(n != 1)'),
220 # Cornish
221 'kw': (6, 'n == 0 ? 0 : n == 1 ? 1 : (n % 100 == 2 || n % 100 == 22 || n % 100 == 42 || n % 100 == 62 || n % 100 == 82) || n % 1000 == 0 && (n % 100000 >= 1000 && n % 100000 <= 20000 || n % 100000 == 40000 || n % 100000 == 60000 || n % 100000 == 80000) || n != 0 && n % 1000000 == 100000 ? 2 : (n % 100 == 3 || n % 100 == 23 || n % 100 == 43 || n % 100 == 63 || n % 100 == 83) ? 3 : n != 1 && (n % 100 == 1 || n % 100 == 21 || n % 100 == 41 || n % 100 == 61 || n % 100 == 81) ? 4 : 5'),
222 # Kyrgyz
223 'ky': (2, '(n != 1)'),
224 # Langi
225 'lag': (3, '(n == 0 ? 0 : n == 1 ? 1 : 2)'),
226 # Luxembourgish
227 'lb': (2, '(n != 1)'),
228 # Ganda
229 'lg': (2, '(n != 1)'),
230 # Ligurian
231 'lij': (2, '(n != 1)'),
232 # Lakota
233 'lkt': (1, '0'),
234 # Dolomitic Ladin
235 'lld': (3, '(n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2)'),
236 # Lingala
237 'ln': (2, '(n > 1)'),
238 # Lao
239 'lo': (1, '0'),
240 # Lithuanian
241 'lt': (3, 'n % 10 == 1 && (n % 100 < 11 || n % 100 > 19) ? 0 : n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19) ? 1 : 2'),
242 # Latvian
243 'lv': (3, '(n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19 ? 0 : n % 10 == 1 && n % 100 != 11 ? 1 : 2)'),
244 # Masai
245 'mas': (2, '(n != 1)'),
246 # Malagasy
247 'mg': (2, '(n > 1)'),
248 # Metaʼ
249 'mgo': (2, '(n != 1)'),
250 # Macedonian
251 'mk': (2, '(n % 10 != 1 || n % 100 == 11)'),
252 # Malayalam
253 'ml': (2, '(n != 1)'),
254 # Mongolian
255 'mn': (2, '(n != 1)'),
256 # Marathi
257 'mr': (2, '(n != 1)'),
258 # Malay
259 'ms': (1, '0'),
260 # Maltese
261 'mt': (5, '(n == 1 ? 0 : n == 2 ? 1 : n == 0 || n % 100 >= 3 && n % 100 <= 10 ? 2 : n % 100 >= 11 && n % 100 <= 19 ? 3 : 4)'),
262 # Burmese
263 'my': (1, '0'),
264 # Nama
265 'naq': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
266 # Norwegian Bokmål
267 'nb': (2, '(n != 1)'),
268 # North Ndebele
269 'nd': (2, '(n != 1)'),
270 # Nepali
271 'ne': (2, '(n != 1)'),
272 # Dutch
273 'nl': (2, '(n != 1)'),
274 # Norwegian Nynorsk
275 'nn': (2, '(n != 1)'),
276 # Ngiemboon
277 'nnh': (2, '(n != 1)'),
278 # Norwegian
279 'no': (2, '(n != 1)'),
280 # N’Ko
281 'nqo': (1, '0'),
282 # South Ndebele
283 'nr': (2, '(n != 1)'),
284 # Northern Sotho
285 'nso': (2, '(n > 1)'),
286 # Nyanja
287 'ny': (2, '(n != 1)'),
288 # Nyankole
289 'nyn': (2, '(n != 1)'),
290 # Oromo
291 'om': (2, '(n != 1)'),
292 # Odia
293 'or': (2, '(n != 1)'),
294 # Ossetic
295 'os': (2, '(n != 1)'),
296 # Osage
297 'osa': (1, '0'),
298 # Punjabi
299 'pa': (2, '(n > 1)'),
300 # Papiamento
301 'pap': (2, '(n != 1)'),
302 # Nigerian Pidgin
303 'pcm': (2, '(n > 1)'),
304 # Polish
305 'pl': (3, 'n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : 2'),
306 # Prussian
307 'prg': (3, '(n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19 ? 0 : n % 10 == 1 && n % 100 != 11 ? 1 : 2)'),
308 # Pashto
309 'ps': (2, '(n != 1)'),
310 # Portuguese
311 'pt': (3, '(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2'),
312 # European Portuguese
313 'pt_PT': (3, '(n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2)'),
314 # Romansh
315 'rm': (2, '(n != 1)'),
316 # Romanian
317 'ro': (3, '(n == 1 ? 0 : n == 0 || n != 1 && n % 100 >= 1 && n % 100 <= 19 ? 1 : 2)'),
318 # Rombo
319 'rof': (2, '(n != 1)'),
320 # Russian
321 'ru': (3, 'n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : 2'),
322 # Rwa
323 'rwk': (2, '(n != 1)'),
324 # Yakut
325 'sah': (1, '0'),
326 # Samburu
327 'saq': (2, '(n != 1)'),
328 # Santali
329 'sat': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
330 # Sardinian
331 'sc': (2, '(n != 1)'),
332 # Sicilian
333 'scn': (3, '(n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2)'),
334 # Sindhi
335 'sd': (2, '(n != 1)'),
336 # Southern Kurdish
337 'sdh': (2, '(n != 1)'),
338 # Northern Sami
339 'se': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
340 # Sena
341 'seh': (2, '(n != 1)'),
342 # Koyraboro Senni
343 'ses': (1, '0'),
344 # Sango
345 'sg': (1, '0'),
346 # Samogitian
347 'sgs': (4, 'n % 10 == 1 && n % 100 != 11 ? 0 : n == 2 ? 1 : n != 2 && n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19) ? 2 : 3'),
348 # Tachelhit
349 'shi': (3, '(n == 0 || n == 1 ? 0 : n >= 2 && n <= 10 ? 1 : 2)'),
350 # Sinhala
351 'si': (2, '(n > 1)'),
352 # Slovak
353 'sk': (3, '(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2)'),
354 # Slovenian
355 'sl': (4, 'n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : (n % 100 == 3 || n % 100 == 4) ? 2 : 3'),
356 # Southern Sami
357 'sma': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
358 # Lule Sami
359 'smj': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
360 # Inari Sami
361 'smn': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
362 # Skolt Sami
363 'sms': (3, '(n == 1 ? 0 : n == 2 ? 1 : 2)'),
364 # Shona
365 'sn': (2, '(n != 1)'),
366 # Somali
367 'so': (2, '(n != 1)'),
368 # Albanian
369 'sq': (2, '(n != 1)'),
370 # Serbian
371 'sr': (3, 'n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : 2'),
372 # Swati
373 'ss': (2, '(n != 1)'),
374 # Saho
375 'ssy': (2, '(n != 1)'),
376 # Southern Sotho
377 'st': (2, '(n != 1)'),
378 # Sundanese
379 'su': (1, '0'),
380 # Swedish
381 'sv': (2, '(n != 1)'),
382 # Swahili
383 'sw': (2, '(n != 1)'),
384 # Syriac
385 'syr': (2, '(n != 1)'),
386 # Tamil
387 'ta': (2, '(n != 1)'),
388 # Telugu
389 'te': (2, '(n != 1)'),
390 # Teso
391 'teo': (2, '(n != 1)'),
392 # Thai
393 'th': (1, '0'),
394 # Tigrinya
395 'ti': (2, '(n > 1)'),
396 # Tigre
397 'tig': (2, '(n != 1)'),
398 # Turkmen
399 'tk': (2, '(n != 1)'),
400 # Tswana
401 'tn': (2, '(n != 1)'),
402 # Tongan
403 'to': (1, '0'),
404 # Tok Pisin
405 'tpi': (1, '0'),
406 # Turkish
407 'tr': (2, '(n != 1)'),
408 # Tsonga
409 'ts': (2, '(n != 1)'),
410 # Central Atlas Tamazight
411 'tzm': (2, 'n >= 2 && (n < 11 || n > 99)'),
412 # Uyghur
413 'ug': (2, '(n != 1)'),
414 # Ukrainian
415 'uk': (3, 'n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : 2'),
416 # Urdu
417 'ur': (2, '(n != 1)'),
418 # Uzbek
419 'uz': (2, '(n != 1)'),
420 # Venda
421 've': (2, '(n != 1)'),
422 # Venetian
423 'vec': (3, '(n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2)'),
424 # Vietnamese
425 'vi': (1, '0'),
426 # Volapük
427 'vo': (2, '(n != 1)'),
428 # Vunjo
429 'vun': (2, '(n != 1)'),
430 # Walloon
431 'wa': (2, '(n > 1)'),
432 # Walser
433 'wae': (2, '(n != 1)'),
434 # Wolof
435 'wo': (1, '0'),
436 # Xhosa
437 'xh': (2, '(n != 1)'),
438 # Soga
439 'xog': (2, '(n != 1)'),
440 # Yiddish
441 'yi': (2, '(n != 1)'),
442 # Yoruba
443 'yo': (1, '0'),
444 # Cantonese
445 'yue': (1, '0'),
446 # Chinese
447 'zh': (1, '0'),
448 # Zulu
449 'zu': (2, '(n > 1)'),
450} # fmt: skip
451
452DEFAULT_PLURAL: tuple[int, str] = (2, '(n != 1)')
453
454
455class _PluralTuple(tuple):
456 """A tuple with plural information."""
457
458 __slots__ = ()
459
460 @property
461 def num_plurals(self) -> int:
462 """The number of plurals used by the locale."""
463 return self[0]
464
465 @property
466 def plural_expr(self) -> str:
467 """The plural expression used by the locale."""
468 return self[1]
469
470 @property
471 def plural_forms(self) -> str:
472 """The plural expression used by the catalog or locale."""
473 return f'nplurals={self[0]}; plural={self[1]};'
474
475 def __str__(self) -> str:
476 return self.plural_forms
477
478
479def get_plural(locale: Locale | str | None = None) -> _PluralTuple:
480 """A tuple with the information catalogs need to perform proper
481 pluralization. The first item of the tuple is the number of plural
482 forms, the second the plural expression.
483
484 :param locale: the `Locale` object or locale identifier. Defaults to the system character type locale.
485
486 >>> get_plural(locale='en')
487 (2, '(n != 1)')
488 >>> get_plural(locale='ga')
489 (5, '(n == 1 ? 0 : n == 2 ? 1 : n >= 3 && n <= 6 ? 2 : n >= 7 && n <= 10 ? 3 : 4)')
490
491 The object returned is a special tuple with additional members:
492
493 >>> tup = get_plural("ja")
494 >>> tup.num_plurals
495 1
496 >>> tup.plural_expr
497 '0'
498 >>> tup.plural_forms
499 'nplurals=1; plural=0;'
500
501 Converting the tuple into a string prints the plural forms for a
502 gettext catalog:
503
504 >>> str(tup)
505 'nplurals=1; plural=0;'
506 """
507 locale = Locale.parse(locale or LC_CTYPE)
508 try:
509 tup = PLURALS[str(locale)]
510 except KeyError:
511 try:
512 tup = PLURALS[locale.language]
513 except KeyError:
514 tup = DEFAULT_PLURAL
515 return _PluralTuple(tup)