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