1# -*- coding: utf-8 -*-
2"""
3    babel.messages.plurals
4    ~~~~~~~~~~~~~~~~~~~~~~
5
6    Plural form definitions.
7
8    :copyright: (c) 2013-2021 by the Babel Team.
9    :license: BSD, see LICENSE for more details.
10"""
11
12from babel.core import default_locale, Locale
13from operator import itemgetter
14
15
16# XXX: remove this file, duplication with babel.plural
17
18
19LC_CTYPE = default_locale('LC_CTYPE')
20
21
22PLURALS = {
23    # Afar
24    # 'aa': (),
25    # Abkhazian
26    # 'ab': (),
27    # Avestan
28    # 'ae': (),
29    # Afrikaans - From Pootle's PO's
30    'af': (2, '(n != 1)'),
31    # Akan
32    # 'ak': (),
33    # Amharic
34    # 'am': (),
35    # Aragonese
36    # 'an': (),
37    # Arabic - From Pootle's PO's
38    'ar': (6, '(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=0 && n%100<=2 ? 4 : 5)'),
39    # Assamese
40    # 'as': (),
41    # Avaric
42    # 'av': (),
43    # Aymara
44    # 'ay': (),
45    # Azerbaijani
46    # 'az': (),
47    # Bashkir
48    # 'ba': (),
49    # Belarusian
50    'be': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
51    # Bulgarian - From Pootle's PO's
52    'bg': (2, '(n != 1)'),
53    # Bihari
54    # 'bh': (),
55    # Bislama
56    # 'bi': (),
57    # Bambara
58    # 'bm': (),
59    # Bengali - From Pootle's PO's
60    'bn': (2, '(n != 1)'),
61    # Tibetan - as discussed in private with Andrew West
62    'bo': (1, '0'),
63    # Breton
64    'br': (
65        6,
66        '(n==1 ? 0 : n%10==1 && n%100!=11 && n%100!=71 && n%100!=91 ? 1 : n%10==2 && n%100!=12 && n%100!=72 && '
67        'n%100!=92 ? 2 : (n%10==3 || n%10==4 || n%10==9) && n%100!=13 && n%100!=14 && n%100!=19 && n%100!=73 && '
68        'n%100!=74 && n%100!=79 && n%100!=93 && n%100!=94 && n%100!=99 ? 3 : n%1000000==0 ? 4 : 5)'
69    ),
70    # Bosnian
71    'bs': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
72    # Catalan - From Pootle's PO's
73    'ca': (2, '(n != 1)'),
74    # Chechen
75    # 'ce': (),
76    # Chamorro
77    # 'ch': (),
78    # Corsican
79    # 'co': (),
80    # Cree
81    # 'cr': (),
82    # Czech
83    'cs': (3, '((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)'),
84    # Church Slavic
85    # 'cu': (),
86    # Chuvash
87    'cv': (1, '0'),
88    # Welsh
89    'cy': (5, '(n==1 ? 1 : n==2 ? 2 : n==3 ? 3 : n==6 ? 4 : 0)'),
90    # Danish
91    'da': (2, '(n != 1)'),
92    # German
93    'de': (2, '(n != 1)'),
94    # Divehi
95    # 'dv': (),
96    # Dzongkha
97    'dz': (1, '0'),
98    # Greek
99    'el': (2, '(n != 1)'),
100    # English
101    'en': (2, '(n != 1)'),
102    # Esperanto
103    'eo': (2, '(n != 1)'),
104    # Spanish
105    'es': (2, '(n != 1)'),
106    # Estonian
107    'et': (2, '(n != 1)'),
108    # Basque - From Pootle's PO's
109    'eu': (2, '(n != 1)'),
110    # Persian - From Pootle's PO's
111    'fa': (1, '0'),
112    # Finnish
113    'fi': (2, '(n != 1)'),
114    # French
115    'fr': (2, '(n > 1)'),
116    # Friulian - From Pootle's PO's
117    'fur': (2, '(n > 1)'),
118    # Irish
119    'ga': (5, '(n==1 ? 0 : n==2 ? 1 : n>=3 && n<=6 ? 2 : n>=7 && n<=10 ? 3 : 4)'),
120    # Galician - From Pootle's PO's
121    'gl': (2, '(n != 1)'),
122    # Hausa - From Pootle's PO's
123    'ha': (2, '(n != 1)'),
124    # Hebrew
125    'he': (2, '(n != 1)'),
126    # Hindi - From Pootle's PO's
127    'hi': (2, '(n != 1)'),
128    # Croatian
129    'hr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
130    # Hungarian
131    'hu': (1, '0'),
132    # Armenian - From Pootle's PO's
133    'hy': (1, '0'),
134    # Icelandic - From Pootle's PO's
135    'is': (2, '(n%10==1 && n%100!=11 ? 0 : 1)'),
136    # Italian
137    'it': (2, '(n != 1)'),
138    # Japanese
139    'ja': (1, '0'),
140    # Georgian - From Pootle's PO's
141    'ka': (1, '0'),
142    # Kongo - From Pootle's PO's
143    'kg': (2, '(n != 1)'),
144    # Khmer - From Pootle's PO's
145    'km': (1, '0'),
146    # Korean
147    'ko': (1, '0'),
148    # Kurdish - From Pootle's PO's
149    'ku': (2, '(n != 1)'),
150    # Lao - Another member of the Tai language family, like Thai.
151    'lo': (1, '0'),
152    # Lithuanian
153    'lt': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)'),
154    # Latvian
155    'lv': (3, '(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)'),
156    # Maltese - From Pootle's PO's
157    'mt': (4, '(n==1 ? 0 : n==0 || ( n%100=>1 && n%100<=10) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3)'),
158    # Norwegian Bokmål
159    'nb': (2, '(n != 1)'),
160    # Dutch
161    'nl': (2, '(n != 1)'),
162    # Norwegian Nynorsk
163    'nn': (2, '(n != 1)'),
164    # Norwegian
165    'no': (2, '(n != 1)'),
166    # Punjabi - From Pootle's PO's
167    'pa': (2, '(n != 1)'),
168    # Polish
169    'pl': (3, '(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
170    # Portuguese
171    'pt': (2, '(n != 1)'),
172    # Brazilian
173    'pt_BR': (2, '(n > 1)'),
174    # Romanian - From Pootle's PO's
175    'ro': (3, '(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2)'),
176    # Russian
177    'ru': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
178    # Slovak
179    'sk': (3, '((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)'),
180    # Slovenian
181    'sl': (4, '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)'),
182    # Serbian - From Pootle's PO's
183    'sr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
184    # Southern Sotho - From Pootle's PO's
185    'st': (2, '(n != 1)'),
186    # Swedish
187    'sv': (2, '(n != 1)'),
188    # Thai
189    'th': (1, '0'),
190    # Turkish
191    'tr': (1, '0'),
192    # Ukrainian
193    'uk': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
194    # Venda - From Pootle's PO's
195    've': (2, '(n != 1)'),
196    # Vietnamese - From Pootle's PO's
197    'vi': (1, '0'),
198    # Xhosa - From Pootle's PO's
199    'xh': (2, '(n != 1)'),
200    # Chinese - From Pootle's PO's (modified)
201    'zh': (1, '0'),
202}
203
204
205DEFAULT_PLURAL = (2, '(n != 1)')
206
207
208class _PluralTuple(tuple):
209    """A tuple with plural information."""
210
211    __slots__ = ()
212    num_plurals = property(itemgetter(0), doc="""
213    The number of plurals used by the locale.""")
214    plural_expr = property(itemgetter(1), doc="""
215    The plural expression used by the locale.""")
216    plural_forms = property(lambda x: 'nplurals=%s; plural=%s;' % x, doc="""
217    The plural expression used by the catalog or locale.""")
218
219    def __str__(self):
220        return self.plural_forms
221
222
223def get_plural(locale=LC_CTYPE):
224    """A tuple with the information catalogs need to perform proper
225    pluralization.  The first item of the tuple is the number of plural
226    forms, the second the plural expression.
227
228    >>> get_plural(locale='en')
229    (2, '(n != 1)')
230    >>> get_plural(locale='ga')
231    (5, '(n==1 ? 0 : n==2 ? 1 : n>=3 && n<=6 ? 2 : n>=7 && n<=10 ? 3 : 4)')
232
233    The object returned is a special tuple with additional members:
234
235    >>> tup = get_plural("ja")
236    >>> tup.num_plurals
237    1
238    >>> tup.plural_expr
239    '0'
240    >>> tup.plural_forms
241    'nplurals=1; plural=0;'
242
243    Converting the tuple into a string prints the plural forms for a
244    gettext catalog:
245
246    >>> str(tup)
247    'nplurals=1; plural=0;'
248    """
249    locale = Locale.parse(locale)
250    try:
251        tup = PLURALS[str(locale)]
252    except KeyError:
253        try:
254            tup = PLURALS[locale.language]
255        except KeyError:
256            tup = DEFAULT_PLURAL
257    return _PluralTuple(tup)
258