# HG changeset patch # User aronacher # Date 1214903790 0 # Node ID b539ade22791b6e670ce66e9fd82914408f5769f # Parent 8c851093babcc309402e7f7b4ad643f22bb24d6c Added babel.messages.plurals.get_plural which returns a special tuple with the plural information. diff --git a/babel/messages/catalog.py b/babel/messages/catalog.py --- a/babel/messages/catalog.py +++ b/babel/messages/catalog.py @@ -28,7 +28,7 @@ from babel import __version__ as VERSION from babel.core import Locale from babel.dates import format_datetime -from babel.messages.plurals import PLURALS +from babel.messages.plurals import get_plural from babel.util import odict, distinct, LOCALTZ, UTC, FixedOffsetTimezone __all__ = ['Message', 'Catalog', 'TranslationError'] @@ -411,13 +411,10 @@ """) def num_plurals(self): - if not self._num_plurals: + if self._num_plurals is None: num = 2 if self.locale: - if str(self.locale) in PLURALS: - num = PLURALS[str(self.locale)][0] - elif self.locale.language in PLURALS: - num = PLURALS[self.locale.language][0] + num = get_plural(self.locale)[0] self._num_plurals = num return self._num_plurals num_plurals = property(num_plurals, doc="""\ @@ -432,13 +429,10 @@ """) def plural_expr(self): - if not self._plural_expr: + if self._plural_expr is None: expr = '(n != 1)' if self.locale: - if str(self.locale) in PLURALS: - expr = PLURALS[str(self.locale)][1] - elif self.locale.language in PLURALS: - expr = PLURALS[self.locale.language][1] + expr = get_plural(self.locale)[1] self._plural_expr = expr return self._plural_expr plural_expr = property(plural_expr, doc="""\ diff --git a/babel/messages/plurals.py b/babel/messages/plurals.py --- a/babel/messages/plurals.py +++ b/babel/messages/plurals.py @@ -13,6 +13,14 @@ """Plural form definitions.""" + +from operator import itemgetter +from babel.core import default_locale, Locale + + +LC_CTYPE = default_locale('LC_CTYPE') + + PLURALS = { # Afar # 'aa': (), @@ -191,3 +199,58 @@ 'zh_HK': (1, '0'), 'zh_TW': (1, '0'), } + + +DEFAULT_PLURAL = (2, '(n != 1)') + + +class _PluralTuple(tuple): + """A tuple with plural information.""" + + __slots__ = () + num_plurals = property(itemgetter(0), doc=""" + The number of plurals used by the locale.""") + plural_expr = property(itemgetter(1), doc=""" + The plural expression used by the locale.""") + plural_forms = property(lambda x: 'npurals=%s; plural=%s' % x, doc=""" + The plural expression used by the catalog or locale.""") + + def __str__(self): + return self.plural_forms + + +def get_plural(locale=LC_CTYPE): + """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. + + >>> get_plural(locale='en') + (2, '(n != 1)') + >>> get_plural(locale='ga') + (3, '(n==1 ? 0 : n==2 ? 1 : 2)') + + 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 + 'npurals=1; plural=0' + + Converting the tuple into a string prints the plural forms for a + gettext catalog: + + >>> str(tup) + 'npurals=1; plural=0' + """ + locale = Locale.parse(locale) + try: + tup = PLURALS[str(locale)] + except KeyError: + try: + tup = PLURALS[locale.language] + except KeyError: + tup = DEFAULT_PLURAL + return _PluralTuple(tup)