[3] | 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) |
---|