From: Armin Ronacher Date: Fri, 5 Jul 2013 18:24:34 +0000 (+0200) Subject: Expanded currency formatting to support full currency names X-Git-Tag: 1.0~120 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72d681aa0f52eb33c92d0c0d4848597472d350c7;p=thirdparty%2Fbabel.git Expanded currency formatting to support full currency names --- diff --git a/ChangeLog b/ChangeLog index 31acbf6c..74b8e882 100644 --- a/ChangeLog +++ b/ChangeLog @@ -62,6 +62,8 @@ http://svn.edgewall.org/repos/babel/tags/1.0.0/ * added support for get_language_name() on the locale objects. * added support for get_territory_name() on the locale objects. * added support for get_script_name() on the locale objects. + * added pluralization support for currency names and added a '¤¤¤' + pattern for currencies that includes the full name. Version 0.9.6 diff --git a/babel/core.py b/babel/core.py index 612d8896..f20197be 100644 --- a/babel/core.py +++ b/babel/core.py @@ -399,7 +399,10 @@ class Locale(object): @property def currencies(self): - """Mapping of currency codes to translated currency names. + """Mapping of currency codes to translated currency names. This + only returns the generic form of the currency name, not the count + specific one. If an actual number is requested use the + :func:`babel.numbers.get_currency_name` function. >>> Locale('en').currencies['COP'] u'Colombian Peso' @@ -409,6 +412,20 @@ class Locale(object): :type: `dict`""" return self._data['currency_names'] + @property + def currencies_with_pluralization(self): + """Mapping of currency codes to translated currency names. The + value for each currency is a dictionary with the pluralization + strings. + + >>> Locale('de', 'DE').currencies_with_pluralization['COP']['one'] + u'Kolumbianischer Peso' + >>> Locale('de', 'DE').currencies_with_pluralization['COP']['other'] + u'Kolumbianische Pesos' + + :type: `dict`""" + return self._data['currency_names_plural'] + @property def currency_symbols(self): """Mapping of currency codes to symbols. diff --git a/babel/numbers.py b/babel/numbers.py index c8980c7b..f3e76a4c 100644 --- a/babel/numbers.py +++ b/babel/numbers.py @@ -36,24 +36,32 @@ __all__ = ['format_number', 'format_decimal', 'format_currency', LC_NUMERIC = default_locale('LC_NUMERIC') -def get_currency_name(currency, locale=LC_NUMERIC): +def get_currency_name(currency, count=None, locale=LC_NUMERIC): """Return the name used by the locale for the specified currency. - >>> get_currency_name('USD', 'en_US') + >>> get_currency_name('USD', locale='en_US') u'US Dollar' :param currency: the currency code + :param count: the optional count. If provided the currency name + will be pluralized to that number if possible. :param locale: the `Locale` object or locale identifier :return: the currency symbol :rtype: `unicode` :since: version 0.9.4 """ - return Locale.parse(locale).currencies.get(currency, currency) + loc = Locale.parse(locale) + if count is not None: + plural_form = loc.plural_form(count) + plural_names = loc.currencies_with_pluralization + if currency in plural_names: + return plural_names[currency][plural_form] + return loc.currencies.get(currency, currency) def get_currency_symbol(currency, locale=LC_NUMERIC): """Return the symbol used by the locale for the specified currency. - >>> get_currency_symbol('USD', 'en_US') + >>> get_currency_symbol('USD', locale='en_US') u'$' :param currency: the currency code @@ -182,10 +190,15 @@ def format_currency(number, currency, format=None, locale=LC_NUMERIC): >>> format_currency(1099.98, 'EUR', locale='de_DE') u'1.099,98\\xa0\\u20ac' - The pattern can also be specified explicitly: + The pattern can also be specified explicitly. The currency is + placed with the '¤' sign. As the sign gets repeated the format + expands (¤ being the symbol, ¤¤ is the currency abbreviation and + ¤¤¤ is the full name of the currency): >>> format_currency(1099.98, 'EUR', u'\xa4\xa4 #,##0.00', locale='en_US') u'EUR 1,099.98' + >>> format_currency(1099.98, 'EUR', u'#,##0.00 \xa4\xa4\xa4', locale='en_US') + u'1,099.98 euros' :param number: the number to format :param currency: the currency code @@ -412,13 +425,19 @@ def parse_pattern(pattern): if isinstance(pattern, NumberPattern): return pattern + def _match_number(pattern): + rv = number_re.search(pattern) + if rv is None: + raise ValueError('Invalid number pattern %r' % pattern) + return rv.groups() + # Do we have a negative subpattern? if ';' in pattern: pattern, neg_pattern = pattern.split(';', 1) - pos_prefix, number, pos_suffix = number_re.search(pattern).groups() - neg_prefix, _, neg_suffix = number_re.search(neg_pattern).groups() + pos_prefix, number, pos_suffix = _match_number(pattern) + neg_prefix, _, neg_suffix = _match_number(neg_pattern) else: - pos_prefix, number, pos_suffix = number_re.search(pattern).groups() + pos_prefix, number, pos_suffix = _match_number(pattern) neg_prefix = '-' + pos_prefix neg_suffix = pos_suffix if 'E' in number: @@ -568,6 +587,8 @@ class NumberPattern(object): retval = u'%s%s%s' % (self.prefix[is_negative], number, self.suffix[is_negative]) if u'¤' in retval: + retval = retval.replace(u'¤¤¤', + get_currency_name(currency, value, locale)) retval = retval.replace(u'¤¤', currency.upper()) retval = retval.replace(u'¤', get_currency_symbol(currency, locale)) return retval diff --git a/scripts/import_cldr.py b/scripts/import_cldr.py index 7cdd114f..8c9ee8d8 100755 --- a/scripts/import_cldr.py +++ b/scripts/import_cldr.py @@ -504,15 +504,18 @@ def main(): percent_formats[elem.attrib.get('type')] = numbers.parse_pattern(pattern) currency_names = data.setdefault('currency_names', {}) + currency_names_plural = data.setdefault('currency_names_plural', {}) currency_symbols = data.setdefault('currency_symbols', {}) for elem in tree.findall('.//currencies/currency'): code = elem.attrib['type'] - # TODO: support plural rules for currency name selection for name in elem.findall('displayName'): - if ('draft' in name.attrib or 'count' in name.attrib) \ - and code in currency_names: + if ('draft' in name.attrib) and code in currency_names: continue - currency_names[code] = unicode(name.text) + if 'count' in name.attrib: + currency_names_plural.setdefault(code, {})[name.attrib['count']] = \ + unicode(name.text) + else: + currency_names[code] = unicode(name.text) # TODO: support choice patterns for currency symbol selection symbol = elem.find('symbol') if symbol is not None and 'draft' not in symbol.attrib \