]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
Expanded currency formatting to support full currency names
authorArmin Ronacher <armin.ronacher@active-4.com>
Fri, 5 Jul 2013 18:24:34 +0000 (20:24 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Fri, 5 Jul 2013 18:24:34 +0000 (20:24 +0200)
ChangeLog
babel/core.py
babel/numbers.py
scripts/import_cldr.py

index 31acbf6cd348dce5e6211b4ad7e312e7783f8cd0..74b8e8824409983a3a2eb445bf69b8f0c4639bc8 100644 (file)
--- 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
index 612d8896b04d0ee27cf257851c676ac13d588f7f..f20197be109168dcd8589ba254b500b1802823ec 100644 (file)
@@ -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.
index c8980c7b6587ad1c99845671a8b3c1ed2e2fd333..f3e76a4ca45d7d43bd96c1f63cc22766a3c61265 100644 (file)
@@ -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
index 7cdd114fc07f88bf93dfcbff0a5b0b3b68a9992e..8c9ee8d8663c4277c2fdabcc5b2bd4b259bbe962 100755 (executable)
@@ -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 \