267 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			267 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								    babel.messages.plurals
							 | 
						||
| 
								 | 
							
								    ~~~~~~~~~~~~~~~~~~~~~~
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Plural form definitions.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :copyright: (c) 2013-2025 by the Babel Team.
							 | 
						||
| 
								 | 
							
								    :license: BSD, see LICENSE for more details.
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								from __future__ import annotations
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from babel.core import Locale, default_locale
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# XXX: remove this file, duplication with babel.plural
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								LC_CTYPE: str | None = default_locale('LC_CTYPE')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								PLURALS: dict[str, tuple[int, str]] = {
							 | 
						||
| 
								 | 
							
								    # Afar
							 | 
						||
| 
								 | 
							
								    # 'aa': (),
							 | 
						||
| 
								 | 
							
								    # Abkhazian
							 | 
						||
| 
								 | 
							
								    # 'ab': (),
							 | 
						||
| 
								 | 
							
								    # Avestan
							 | 
						||
| 
								 | 
							
								    # 'ae': (),
							 | 
						||
| 
								 | 
							
								    # Afrikaans - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'af': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Akan
							 | 
						||
| 
								 | 
							
								    # 'ak': (),
							 | 
						||
| 
								 | 
							
								    # Amharic
							 | 
						||
| 
								 | 
							
								    # 'am': (),
							 | 
						||
| 
								 | 
							
								    # Aragonese
							 | 
						||
| 
								 | 
							
								    # 'an': (),
							 | 
						||
| 
								 | 
							
								    # Arabic - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    '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)'),
							 | 
						||
| 
								 | 
							
								    # Assamese
							 | 
						||
| 
								 | 
							
								    # 'as': (),
							 | 
						||
| 
								 | 
							
								    # Avaric
							 | 
						||
| 
								 | 
							
								    # 'av': (),
							 | 
						||
| 
								 | 
							
								    # Aymara
							 | 
						||
| 
								 | 
							
								    # 'ay': (),
							 | 
						||
| 
								 | 
							
								    # Azerbaijani
							 | 
						||
| 
								 | 
							
								    # 'az': (),
							 | 
						||
| 
								 | 
							
								    # Bashkir
							 | 
						||
| 
								 | 
							
								    # 'ba': (),
							 | 
						||
| 
								 | 
							
								    # Belarusian
							 | 
						||
| 
								 | 
							
								    'be': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Bulgarian - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'bg': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Bihari
							 | 
						||
| 
								 | 
							
								    # 'bh': (),
							 | 
						||
| 
								 | 
							
								    # Bislama
							 | 
						||
| 
								 | 
							
								    # 'bi': (),
							 | 
						||
| 
								 | 
							
								    # Bambara
							 | 
						||
| 
								 | 
							
								    # 'bm': (),
							 | 
						||
| 
								 | 
							
								    # Bengali - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'bn': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Tibetan - as discussed in private with Andrew West
							 | 
						||
| 
								 | 
							
								    'bo': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Breton
							 | 
						||
| 
								 | 
							
								    'br': (
							 | 
						||
| 
								 | 
							
								        6,
							 | 
						||
| 
								 | 
							
								        '(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 && '
							 | 
						||
| 
								 | 
							
								        '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 && '
							 | 
						||
| 
								 | 
							
								        'n%100!=74 && n%100!=79 && n%100!=93 && n%100!=94 && n%100!=99 ? 3 : n%1000000==0 ? 4 : 5)',
							 | 
						||
| 
								 | 
							
								    ),
							 | 
						||
| 
								 | 
							
								    # Bosnian
							 | 
						||
| 
								 | 
							
								    'bs': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Catalan - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'ca': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Chechen
							 | 
						||
| 
								 | 
							
								    # 'ce': (),
							 | 
						||
| 
								 | 
							
								    # Chamorro
							 | 
						||
| 
								 | 
							
								    # 'ch': (),
							 | 
						||
| 
								 | 
							
								    # Corsican
							 | 
						||
| 
								 | 
							
								    # 'co': (),
							 | 
						||
| 
								 | 
							
								    # Cree
							 | 
						||
| 
								 | 
							
								    # 'cr': (),
							 | 
						||
| 
								 | 
							
								    # Czech
							 | 
						||
| 
								 | 
							
								    'cs': (3, '((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Church Slavic
							 | 
						||
| 
								 | 
							
								    # 'cu': (),
							 | 
						||
| 
								 | 
							
								    # Chuvash
							 | 
						||
| 
								 | 
							
								    'cv': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Welsh
							 | 
						||
| 
								 | 
							
								    'cy': (5, '(n==1 ? 1 : n==2 ? 2 : n==3 ? 3 : n==6 ? 4 : 0)'),
							 | 
						||
| 
								 | 
							
								    # Danish
							 | 
						||
| 
								 | 
							
								    'da': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # German
							 | 
						||
| 
								 | 
							
								    'de': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Divehi
							 | 
						||
| 
								 | 
							
								    # 'dv': (),
							 | 
						||
| 
								 | 
							
								    # Dzongkha
							 | 
						||
| 
								 | 
							
								    'dz': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Greek
							 | 
						||
| 
								 | 
							
								    'el': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # English
							 | 
						||
| 
								 | 
							
								    'en': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Esperanto
							 | 
						||
| 
								 | 
							
								    'eo': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Spanish
							 | 
						||
| 
								 | 
							
								    'es': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Estonian
							 | 
						||
| 
								 | 
							
								    'et': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Basque - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'eu': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Persian - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'fa': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Finnish
							 | 
						||
| 
								 | 
							
								    'fi': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # French
							 | 
						||
| 
								 | 
							
								    'fr': (2, '(n > 1)'),
							 | 
						||
| 
								 | 
							
								    # Friulian - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'fur': (2, '(n > 1)'),
							 | 
						||
| 
								 | 
							
								    # Irish
							 | 
						||
| 
								 | 
							
								    'ga': (5, '(n==1 ? 0 : n==2 ? 1 : n>=3 && n<=6 ? 2 : n>=7 && n<=10 ? 3 : 4)'),
							 | 
						||
| 
								 | 
							
								    # Galician - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'gl': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Hausa - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'ha': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Hebrew
							 | 
						||
| 
								 | 
							
								    'he': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Hindi - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'hi': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Croatian
							 | 
						||
| 
								 | 
							
								    'hr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Hungarian
							 | 
						||
| 
								 | 
							
								    'hu': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Armenian - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'hy': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Icelandic - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'is': (2, '(n%10==1 && n%100!=11 ? 0 : 1)'),
							 | 
						||
| 
								 | 
							
								    # Italian
							 | 
						||
| 
								 | 
							
								    'it': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Japanese
							 | 
						||
| 
								 | 
							
								    'ja': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Georgian - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'ka': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Kongo - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'kg': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Khmer - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'km': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Korean
							 | 
						||
| 
								 | 
							
								    'ko': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Kurdish - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'ku': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Lao - Another member of the Tai language family, like Thai.
							 | 
						||
| 
								 | 
							
								    'lo': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Lithuanian
							 | 
						||
| 
								 | 
							
								    'lt': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Latvian
							 | 
						||
| 
								 | 
							
								    'lv': (3, '(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Maltese - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'mt': (4, '(n==1 ? 0 : n==0 || ( n%100>=1 && n%100<=10) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3)'),
							 | 
						||
| 
								 | 
							
								    # Norwegian Bokmål
							 | 
						||
| 
								 | 
							
								    'nb': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Dutch
							 | 
						||
| 
								 | 
							
								    'nl': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Norwegian Nynorsk
							 | 
						||
| 
								 | 
							
								    'nn': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Norwegian
							 | 
						||
| 
								 | 
							
								    'no': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Punjabi - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'pa': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Polish
							 | 
						||
| 
								 | 
							
								    'pl': (3, '(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Portuguese
							 | 
						||
| 
								 | 
							
								    'pt': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Brazilian
							 | 
						||
| 
								 | 
							
								    'pt_BR': (2, '(n > 1)'),
							 | 
						||
| 
								 | 
							
								    # Romanian - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'ro': (3, '(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Russian
							 | 
						||
| 
								 | 
							
								    'ru': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Slovak
							 | 
						||
| 
								 | 
							
								    'sk': (3, '((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Slovenian
							 | 
						||
| 
								 | 
							
								    'sl': (4, '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)'),
							 | 
						||
| 
								 | 
							
								    # Serbian - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'sr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Southern Sotho - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'st': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Swedish
							 | 
						||
| 
								 | 
							
								    'sv': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Thai
							 | 
						||
| 
								 | 
							
								    'th': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Turkish
							 | 
						||
| 
								 | 
							
								    'tr': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Ukrainian
							 | 
						||
| 
								 | 
							
								    'uk': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
							 | 
						||
| 
								 | 
							
								    # Venda - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    've': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Vietnamese - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'vi': (1, '0'),
							 | 
						||
| 
								 | 
							
								    # Xhosa - From Pootle's PO's
							 | 
						||
| 
								 | 
							
								    'xh': (2, '(n != 1)'),
							 | 
						||
| 
								 | 
							
								    # Chinese - From Pootle's PO's (modified)
							 | 
						||
| 
								 | 
							
								    'zh': (1, '0'),
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DEFAULT_PLURAL: tuple[int, str] = (2, '(n != 1)')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class _PluralTuple(tuple):
							 | 
						||
| 
								 | 
							
								    """A tuple with plural information."""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    __slots__ = ()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @property
							 | 
						||
| 
								 | 
							
								    def num_plurals(self) -> int:
							 | 
						||
| 
								 | 
							
								        """The number of plurals used by the locale."""
							 | 
						||
| 
								 | 
							
								        return self[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @property
							 | 
						||
| 
								 | 
							
								    def plural_expr(self) -> str:
							 | 
						||
| 
								 | 
							
								        """The plural expression used by the locale."""
							 | 
						||
| 
								 | 
							
								        return self[1]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @property
							 | 
						||
| 
								 | 
							
								    def plural_forms(self) -> str:
							 | 
						||
| 
								 | 
							
								        """The plural expression used by the catalog or locale."""
							 | 
						||
| 
								 | 
							
								        return f'nplurals={self[0]}; plural={self[1]};'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __str__(self) -> str:
							 | 
						||
| 
								 | 
							
								        return self.plural_forms
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def get_plural(locale: Locale | str | None = None) -> _PluralTuple:
							 | 
						||
| 
								 | 
							
								    """A tuple with the information catalogs need to perform proper
							 | 
						||
| 
								 | 
							
								    pluralization.  The first item of the tuple is the number of plural
							 | 
						||
| 
								 | 
							
								    forms, the second the plural expression.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :param locale: the `Locale` object or locale identifier. Defaults to the system character type locale.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    >>> get_plural(locale='en')
							 | 
						||
| 
								 | 
							
								    (2, '(n != 1)')
							 | 
						||
| 
								 | 
							
								    >>> get_plural(locale='ga')
							 | 
						||
| 
								 | 
							
								    (5, '(n==1 ? 0 : n==2 ? 1 : n>=3 && n<=6 ? 2 : n>=7 && n<=10 ? 3 : 4)')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The object returned is a special tuple with additional members:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    >>> tup = get_plural("ja")
							 | 
						||
| 
								 | 
							
								    >>> tup.num_plurals
							 | 
						||
| 
								 | 
							
								    1
							 | 
						||
| 
								 | 
							
								    >>> tup.plural_expr
							 | 
						||
| 
								 | 
							
								    '0'
							 | 
						||
| 
								 | 
							
								    >>> tup.plural_forms
							 | 
						||
| 
								 | 
							
								    'nplurals=1; plural=0;'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Converting the tuple into a string prints the plural forms for a
							 | 
						||
| 
								 | 
							
								    gettext catalog:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    >>> str(tup)
							 | 
						||
| 
								 | 
							
								    'nplurals=1; plural=0;'
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    locale = Locale.parse(locale or LC_CTYPE)
							 | 
						||
| 
								 | 
							
								    try:
							 | 
						||
| 
								 | 
							
								        tup = PLURALS[str(locale)]
							 | 
						||
| 
								 | 
							
								    except KeyError:
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            tup = PLURALS[locale.language]
							 | 
						||
| 
								 | 
							
								        except KeyError:
							 | 
						||
| 
								 | 
							
								            tup = DEFAULT_PLURAL
							 | 
						||
| 
								 | 
							
								    return _PluralTuple(tup)
							 |