Example #1
0
 def test_negotiate(self):
     de_DE = Locale.negotiate(['de_DE', 'en_US'], ['de_DE', 'de_AT'])
     assert (de_DE.language, de_DE.territory) == ('de', 'DE')
     de = Locale.negotiate(['de_DE', 'en_US'], ['en', 'de'])
     assert (de.language, de.territory) == ('de', None)
     nothing = Locale.negotiate(['de_DE', 'de'], ['en_US'])
     assert nothing is None
Example #2
0
def get_metadata(app, docname):
    '''
    Extracts metadata from a document.
    '''
    env = app.builder.env
    language = app.config.language
    locale = Locale.parse(language) if language else Locale.default()
    format_ui_date = partial(
        format_date, format=UIStr.TIMESTAMP_FMT, locale=locale)
    format_short_ui_short = partial(
        format_date, format=UIStr.TIMESTAMP_FMT_SHORT, locale=locale)

    env.blog_metadata[docname] = Metadata()
    metadata = env.blog_metadata[docname]

    # if it's a page
    if docname.startswith("pages/"):
      metadata.is_page = True
      return

    # posts are identified by ($YEAR)/($MONTH)/($DAY) paths
    match = re.match(r"\d{4}/\d{2}/\d{2}/", docname)

    # if not post return
    if not match:
        return

    metadata.is_post = True
    metadata.link = docname
    metadata.date = datetime.datetime.strptime(match.group(), "%Y/%m/%d/")

    # we format date here instead of inside template due to localization issues
    # and Python2 vs Python3 incompatibility
    metadata.formatted_date = format_ui_date(metadata.date)
    metadata.formatted_date_short = format_short_ui_short(metadata.date)
Example #3
0
 def test_value_error(self, Locale):
     """
     If Locale.parse raises a ValueError, return the en-US locale
     object.
     """
     Locale.parse.side_effect = ValueError
     eq_(helpers.current_locale(), Locale.return_value)
     Locale.assert_called_with('en', 'US')
Example #4
0
 def test_unknown_locale(self, Locale):
     """
     If Locale.parse raises an UnknownLocaleError, return the en-US
     locale object.
     """
     Locale.parse.side_effect = UnknownLocaleError('foo')
     eq_(helpers.current_locale(), Locale.return_value)
     Locale.assert_called_with('en', 'US')
Example #5
0
    def negotiate(cls, locale):
        """
        Negotiate proper RBNF rules based on global data
        item `rbnf_locales`

        Caching is not necessary the Locale object does that pretty well
        """
        loc = Locale.negotiate([str(Locale.parse(locale))], get_global('rbnf_locales'))

        print('TL', type(loc))

        return cls(loc)
 def getLocale(self, request):
     ## FIXME: implement request.locale()
     tags = ACCEPT_LANGUAGE.parse(request.environ())
     if tags:
         try:
             return Locale.parse(tags[0], sep='-')
         except UnknownLocaleError, e:
             try:
                 return Locale.parse(tags[0])
             except UnknownLocaleError, e:
                 logger.error('Locale parsing error: %s' % e)
                 return defaultLocale()
Example #7
0
File: util.py Project: AvdN/muntjac
def defaultLocale():
    try:
        lang, _ = locale.getdefaultlocale()
    except Exception:
        lang = None

    if lang is not None:
        return Locale.parse(lang)
    else:
        try:
            return Locale.default()
        except UnknownLocaleError:
            return Locale('en', 'US')
Example #8
0
def get_locale_data():
    language = get_language()
    if not language:
        language = settings.LANGUAGE_CODE
    locale_code = to_locale(language)
    locale = None
    try:
        locale = Locale.parse(locale_code)
    except (ValueError, UnknownLocaleError):
        # Invalid format or unknown locale
        # Fallback to the default language
        language = settings.LANGUAGE_CODE
        locale_code = to_locale(language)
        locale = Locale.parse(locale_code)
    return locale, locale_code
Example #9
0
def babel_date(date, format='long'):
    """
    Format a date properly for the current locale. Format can be one of
    'short', 'medium', 'long', or 'full'.
    """
    locale = Locale.parse(get_language(), sep='-')
    return format_date(date, format, locale)
Example #10
0
def format_list(lst, locale=DEFAULT_LOCALE):
    """ Formats `lst` as a list

    e.g.
    >>> format_list(['apples', 'oranges', 'pears'], 'en')
    u'apples, oranges, and pears'
    >>> format_list(['apples', 'oranges', 'pears'], 'zh')
    u'apples\u3001oranges\u548cpears'

    :param lst: a sequence of items to format in to a list
    :param locale: the locale
    """
    locale = Locale.parse(locale)
    if not lst:
        return ''
    if len(lst) == 1:
        return lst[0]
    if len(lst) == 2:
        return locale.list_patterns['2'].format(*lst)

    result = locale.list_patterns['start'].format(lst[0], lst[1])
    for elem in lst[2:-1]:
        result = locale.list_patterns['middle'].format(result, elem)
    result = locale.list_patterns['end'].format(result, lst[-1])

    return result
Example #11
0
File: dates.py Project: eavae/mlang
def format_date(date=None, format='medium', locale=LC_TIME):
    """Return a date formatted according to the given pattern.

    >>> d = date(2007, 04, 01)
    >>> format_date(d, locale='en_US')
    u'Apr 1, 2007'
    >>> format_date(d, format='full', locale='de_DE')
    u'Sonntag, 1. April 2007'

    If you don't want to use the locale default formats, you can specify a
    custom date pattern:

    >>> format_date(d, "EEE, MMM d, ''yy", locale='en')
    u"Sun, Apr 1, '07"

    :param date: the ``date`` or ``datetime`` object; if `None`, the current
                 date is used
    :param format: one of "full", "long", "medium", or "short", or a custom
                   date/time pattern
    :param locale: a `Locale` object or a locale identifier
    """
    if date is None:
        date = date_.today()
    elif isinstance(date, datetime):
        date = date.date()

    locale = Locale.parse(locale)
    if format in ('full', 'long', 'medium', 'short'):
        format = get_date_format(format, locale=locale)
    pattern = parse_pattern(format)
    return pattern.apply(date, locale)
Example #12
0
def format_scientific(
        number, format=None, locale=LC_NUMERIC, decimal_quantization=True):
    """Return value formatted in scientific notation for a specific locale.

    >>> format_scientific(10000, locale='en_US')
    u'1E4'

    The format pattern can also be specified explicitly:

    >>> format_scientific(1234567, u'##0.##E00', locale='en_US')
    u'1.23E06'

    By default the locale is allowed to truncate and round a high-precision
    number by forcing its format pattern onto the decimal part. You can bypass
    this behavior with the `decimal_quantization` parameter:

    >>> format_scientific(1234.9876, u'#.##E0', locale='en_US')
    u'1.23E3'
    >>> format_scientific(1234.9876, u'#.##E0', locale='en_US', decimal_quantization=False)
    u'1.2349876E3'

    :param number: the number to format
    :param format:
    :param locale: the `Locale` object or locale identifier
    :param decimal_quantization: Truncate and round high-precision numbers to
                                 the format pattern. Defaults to `True`.
    """
    locale = Locale.parse(locale)
    if not format:
        format = locale.scientific_formats.get(format)
    pattern = parse_pattern(format)
    return pattern.apply(
        number, locale, decimal_quantization=decimal_quantization)
Example #13
0
def _format_currency_long_name(
        number, currency, format=None, locale=LC_NUMERIC, currency_digits=True,
        format_type='standard', decimal_quantization=True):
    # Algorithm described here:
    # https://www.unicode.org/reports/tr35/tr35-numbers.html#Currencies
    locale = Locale.parse(locale)
    # Step 1.
    # There are no examples of items with explicit count (0 or 1) in current
    # locale data. So there is no point implementing that.
    # Step 2.

    # Correct number to numeric type, important for looking up plural rules:
    if isinstance(number, string_types):
        number_n = float(number)
    else:
        number_n = number

    # Step 3.
    unit_pattern = get_currency_unit_pattern(currency, count=number_n, locale=locale)

    # Step 4.
    display_name = get_currency_name(currency, count=number_n, locale=locale)

    # Step 5.
    if not format:
        format = locale.decimal_formats.get(format)

    pattern = parse_pattern(format)

    number_part = pattern.apply(
        number, locale, currency=currency, currency_digits=currency_digits,
        decimal_quantization=decimal_quantization)

    return unit_pattern.format(number_part, display_name)
Example #14
0
 def load_translation(self,langs, dirname, domain):
     """Loads the first existing translations for known locale and saves the
     `Lang` object in a global cache for faster lookup on the next request.
 
     :parameters:
         langs : List
             List of languages as returned by `parse_accept_language_header`.
         dirname : String
             Directory of the translations (`tools.I18nTool.mo_dir`).
         domain : String
             Gettext domain of the catalog (`tools.I18nTool.domain`).
 
     :returns: Lang object with two attributes (Lang.trans = the translations
               object, Lang.locale = the corresponding Locale object).
     :rtype: Lang
     :raises: ImproperlyConfigured if no locale where known.
     """
     locale = None
     for lang in langs:
         short = lang[:2].lower()
         try:
             locale = Locale.parse(lang)
             if (domain, short) in _languages:
                 return _languages[(domain, short)]
             trans = Translations.load(dirname, short, domain)
         except (ValueError, UnknownLocaleError):
             continue
         # If the translation was found, exit loop
         if isinstance(trans, Translations):
             break
     if locale is None:
         raise ImproperlyConfigured('Default locale not known.')
     _languages[(domain, short)] = res = Lang(locale, trans)
     return res
Example #15
0
def format_decimal(number, format=None, locale=LC_NUMERIC):
    u"""Return the given decimal number formatted for a specific locale.

    >>> format_decimal(1.2345, locale='en_US')
    u'1.234'
    >>> format_decimal(1.2346, locale='en_US')
    u'1.235'
    >>> format_decimal(-1.2346, locale='en_US')
    u'-1.235'
    >>> format_decimal(1.2345, locale='sv_SE')
    u'1,234'
    >>> format_decimal(1.2345, locale='de')
    u'1,234'

    The appropriate thousands grouping and the decimal separator are used for
    each locale:

    >>> format_decimal(12345.5, locale='en_US')
    u'12,345.5'

    :param number: the number to format
    :param format:
    :param locale: the `Locale` object or locale identifier
    """
    locale = Locale.parse(locale)
    if not format:
        format = locale.decimal_formats.get(format)
    pattern = parse_pattern(format)
    return pattern.apply(number, locale)
Example #16
0
def parse_decimal(string, locale=LC_NUMERIC):
    """Parse localized decimal string into a decimal.

    >>> parse_decimal('1,099.98', locale='en_US')
    Decimal('1099.98')
    >>> parse_decimal('1.099,98', locale='de')
    Decimal('1099.98')

    When the given string cannot be parsed, an exception is raised:

    >>> parse_decimal('2,109,998', locale='de')
    Traceback (most recent call last):
        ...
    NumberFormatError: '2,109,998' is not a valid decimal number

    :param string: the string to parse
    :param locale: the `Locale` object or locale identifier
    :raise NumberFormatError: if the string can not be converted to a
                              decimal number
    """
    locale = Locale.parse(locale)
    try:
        return Decimal(string.replace(get_group_symbol(locale), '')
                       .replace(get_decimal_symbol(locale), '.'))
    except InvalidOperation:
        raise NumberFormatError('%r is not a valid decimal number' % string)
Example #17
0
def format_currency(number, currency, format=None, locale=LC_NUMERIC):
    """Return formatted currency value.

    >>> format_currency(1099.98, 'USD', locale='en_US')
    u'$1,099.98'
    >>> format_currency(1099.98, 'USD', locale='es_CO')
    u'1.099,98\\xa0US$'
    >>> format_currency(1099.98, 'EUR', locale='de_DE')
    u'1.099,98\\xa0\\u20ac'

    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
    :param locale: the `Locale` object or locale identifier
    """
    locale = Locale.parse(locale)
    if not format:
        format = locale.currency_formats.get(format)
    pattern = parse_pattern(format)
    return pattern.apply(number, locale, currency=currency)
Example #18
0
def parse_decimal(string, locale=LC_NUMERIC):
    """Parse localized decimal string into a float.
    
    >>> parse_decimal('1,099.98', locale='en_US')
    1099.98
    >>> parse_decimal('1.099,98', locale='de')
    1099.98
    
    When the given string cannot be parsed, an exception is raised:
    
    >>> parse_decimal('2,109,998', locale='de')
    Traceback (most recent call last):
        ...
    NumberFormatError: '2,109,998' is not a valid decimal number
    
    :param string: the string to parse
    :param locale: the `Locale` object or locale identifier
    :return: the parsed decimal number
    :rtype: `float`
    :raise `NumberFormatError`: if the string can not be converted to a
                                decimal number
    """
    locale = Locale.parse(locale)
    try:
        return float(string.replace(get_group_symbol(locale), "").replace(get_decimal_symbol(locale), "."))
    except ValueError:
        raise NumberFormatError("%r is not a valid decimal number" % string)
Example #19
0
def get_unit_name(measurement_unit, length='long', locale=LC_NUMERIC):
    """
    Get the display name for a measurement unit in the given locale.

    >>> get_unit_name("radian", locale="en")
    'radians'

    Unknown units will raise exceptions:

    >>> get_unit_name("battery", locale="fi")
    Traceback (most recent call last):
        ...
    UnknownUnitError: battery/long is not a known unit/length in fi

    :param measurement_unit: the code of a measurement unit.
                             Known units can be found in the CLDR Unit Validity XML file:
                             http://unicode.org/repos/cldr/tags/latest/common/validity/unit.xml

    :param length: "short", "long" or "narrow"
    :param locale: the `Locale` object or locale identifier
    :return: The unit display name, or None.
    """
    locale = Locale.parse(locale)
    unit = _find_unit_pattern(measurement_unit, locale=locale)
    if not unit:
        raise UnknownUnitError(unit=measurement_unit, locale=locale)
    return locale.unit_display_names.get(unit, {}).get(length)
Example #20
0
def get_currency_unit_pattern(currency, count=None, locale=LC_NUMERIC):
    """
    Return the unit pattern used for long display of a currency value
    for a given locale.
    This is a string containing ``{0}`` where the numeric part
    should be substituted and ``{1}`` where the currency long display
    name should be substituted.

    >>> get_currency_unit_pattern('USD', locale='en_US', count=10)
    u'{0} {1}'

    .. versionadded:: 2.7.0

    :param currency: the currency code.
    :param count: the optional count.  If provided the unit
                  pattern for that number will be returned.
    :param locale: the `Locale` object or locale identifier.
    """
    loc = Locale.parse(locale)
    if count is not None:
        plural_form = loc.plural_form(count)
        try:
            return loc._data['currency_unit_patterns'][plural_form]
        except LookupError:
            # Fall back to 'other'
            pass

    return loc._data['currency_unit_patterns']['other']
Example #21
0
def _babel_locale():
    """Return the current locale in Babel's format."""
    try:
        return Locale.parse(get_language(), sep='-')
    except UnknownLocaleError:
        # Default to en-US
        return Locale('en', 'US')
Example #22
0
 def _language_select(self):
     out = {'automatic': _('automatic')}
     i18n_dir = os.path.join(xdm.APP_PATH, 'i18n')
     # http://stackoverflow.com/questions/800197/get-all-of-the-immediate-subdirectories-in-python
     for language in [name for name in os.listdir(i18n_dir) if os.path.isdir(os.path.join(i18n_dir, name))]:
         out[language] = Locale.parse(language, sep='_').display_name
     return out
Example #23
0
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)
Example #24
0
def format_percent(number, format=None, locale=LC_NUMERIC):
    """Return formatted percent value for a specific locale.
    
    >>> format_percent(0.34, locale='en_US') == u('34%')
    True
    >>> format_percent(25.1234, locale='en_US') == u('2,512%')
    True
    >>> format_percent(25.1234, locale='sv_SE') == u('2\\xa0512\\xa0%')
    True

    The format pattern can also be specified explicitly:
    
    >>> format_percent(25.1234, u('#,##0\u2030'), locale='en_US') == u('25,123\u2030')
    True

    :param number: the percent number to format
    :param format: 
    :param locale: the `Locale` object or locale identifier
    :return: the formatted percent number
    :rtype: `unicode`
    """
    locale = Locale.parse(locale)
    if not format:
        format = locale.percent_formats.get(format)
    pattern = parse_pattern(format)
    return pattern.apply(number, locale)
Example #25
0
def format_currency(number, currency, format=None, locale=LC_NUMERIC):
    """Return formatted currency value.
    
    >>> format_currency(1099.98, 'USD', locale='en_US') == u('$1,099.98')
    True
    >>> format_currency(1099.98, 'USD', locale='es_CO') == u('US$\\xa01.099,98')
    True
    >>> format_currency(1099.98, 'EUR', locale='de_DE') == u('1.099,98\\xa0\\u20ac')
    True
    
    The pattern can also be specified explicitly:
    
    >>> format_currency(1099.98, 'EUR', u('\u00a4\u00a4 #,##0.00'), locale='en_US') == u('EUR 1,099.98')
    True
    
    :param number: the number to format
    :param currency: the currency code
    :param locale: the `Locale` object or locale identifier
    :return: the formatted currency value
    :rtype: `unicode`
    """
    locale = Locale.parse(locale)
    if not format:
        format = locale.currency_formats.get(format)
    pattern = parse_pattern(format)
    return pattern.apply(number, locale, currency=currency)
Example #26
0
def get_locale(lang):
    """Return a babel Locale object for lang. defaults to LANGUAGE_CODE."""
    lang = babel_format_locale_map.get(lang) or lang
    try:
        return Locale.parse(lang, sep='-')
    except (UnknownLocaleError, ValueError):
        return Locale(*settings.LANGUAGE_CODE.split('-'))
Example #27
0
    def __init__(self, locale, locale_dirs):
        """Initialize this translator for the given locale.

        :type locale: :class:`babel.Locale` or ``str``.
        :param locale: The locale to load translations for.
        :type locale_dirs: dict
        :param locale_dirs: A mapping of translation domain names to the
            localedir where they can be found. See :func:`gettext.translation`
            for more details.
        :raises DomainError: If no locale dir has been configured for this
            domain and the fallback is off.
        :raises LanguageError: If no translations could be found for this
            locale in the 'mediadrop' domain and the fallback is off.
        """
        self.locale = locale = Locale.parse(locale)

        # Save configuration required for loading translations
        self._locale_dirs = locale_dirs

        # If the locale is pt_BR, look for both pt_BR and pt translations
        self._languages = [str(locale)]
        if locale.territory:
            self._languages.append(locale.language)

        # Storage for all message catalogs keyed by their domain name
        self._domains = {}

        # Fetch the 'mediadrop' domain immediately & cache a direct ref for perf
        self._mediadrop = self._load_domain(MEDIACORE)
Example #28
0
 def _set_mime_headers(self, headers):
     for name, value in headers:
         name = name.lower()
         if name == 'project-id-version':
             parts = value.split(' ')
             self.project = u' '.join(parts[:-1])
             self.version = parts[-1]
         elif name == 'report-msgid-bugs-to':
             self.msgid_bugs_address = value
         elif name == 'last-translator':
             self.last_translator = value
         elif name == 'language':
             self.locale = Locale.parse(value)
         elif name == 'language-team':
             self.language_team = value
         elif name == 'content-type':
             mimetype, params = parse_header(value)
             if 'charset' in params:
                 self.charset = params['charset'].lower()
         elif name == 'plural-forms':
             _, params = parse_header(' ;' + value)
             self._num_plurals = int(params.get('nplurals', 2))
             self._plural_expr = params.get('plural', '(n != 1)')
         elif name == 'pot-creation-date':
             self.creation_date = _parse_datetime_header(value)
         elif name == 'po-revision-date':
             # Keep the value if it's not the default one
             if 'YEAR' not in value:
                 self.revision_date = _parse_datetime_header(value)
Example #29
0
File: dates.py Project: ENuge/babel
def format_skeleton(skeleton, datetime=None, tzinfo=None, locale=LC_TIME):
    r"""Return a time and/or date formatted according to the given pattern.

    The skeletons are defined in the CLDR data and provide more flexibility
    than the simple short/long/medium formats, but are a bit harder to use.
    The are defined using the date/time symbols without order or punctuation
    and map to a suitable format for the given locale.

    >>> t = datetime(2007, 4, 1, 15, 30)
    >>> format_skeleton('MMMEd', t, locale='fr')
    u'dim. 1 avr.'
    >>> format_skeleton('MMMEd', t, locale='en')
    u'Sun, Apr 1'

    After the skeleton is resolved to a pattern `format_datetime` is called so
    all timezone processing etc is the same as for that.

    :param skeleton: A date time skeleton as defined in the cldr data.
    :param datetime: the ``time`` or ``datetime`` object; if `None`, the current
                 time in UTC is used
    :param tzinfo: the time-zone to apply to the time for display
    :param locale: a `Locale` object or a locale identifier
    """
    locale = Locale.parse(locale)
    format = locale.datetime_skeletons[skeleton]
    return format_datetime(datetime, format, tzinfo, locale)
Example #30
0
 def getGlobalPOTimestamp(self, locale):
     '''
     @see: IPOFileManager.getGlobalPOTimestamp
     '''
     try: locale = Locale.parse(locale)
     except UnknownLocaleError: raise InvalidLocaleError(locale)
     return self._lastModified(locale)
Example #31
0
 def test_decimal_formats(self):
     assert Locale('en', 'US').decimal_formats[None].pattern == '#,##0.###'
Example #32
0
 def test_number_symbols_property(self):
     assert Locale('fr', 'FR').number_symbols['decimal'] == ','
Example #33
0
 def test_currency_symbols_property(self):
     assert Locale('en', 'US').currency_symbols['USD'] == '$'
     assert Locale('es', 'CO').currency_symbols['USD'] == 'US$'
Example #34
0
 def test_currencies_property(self):
     assert Locale('en').currencies['COP'] == 'Colombian Peso'
     assert Locale('de', 'DE').currencies['COP'] == 'Kolumbianischer Peso'
Example #35
0
 def test_variants_property(self):
     assert (Locale(
         'de', 'DE').variants['1901'] == 'Alte deutsche Rechtschreibung')
Example #36
0
def get_timezone_name(dt_or_tzinfo=None,
                      width='long',
                      uncommon=False,
                      locale=LC_TIME):
    r"""Return the localized display name for the given timezone. The timezone
    may be specified using a ``datetime`` or `tzinfo` object.
    
    >>> from pytz import timezone
    >>> dt = time(15, 30, tzinfo=timezone('America/Los_Angeles'))
    >>> get_timezone_name(dt, locale='en_US')
    u'Pacific Standard Time'
    >>> get_timezone_name(dt, width='short', locale='en_US')
    u'PST'
    
    If this function gets passed only a `tzinfo` object and no concrete
    `datetime`,  the returned display name is indenpendent of daylight savings
    time. This can be used for example for selecting timezones, or to set the
    time of events that recur across DST changes:
    
    >>> tz = timezone('America/Los_Angeles')
    >>> get_timezone_name(tz, locale='en_US')
    u'Pacific Time'
    >>> get_timezone_name(tz, 'short', locale='en_US')
    u'PT'
    
    If no localized display name for the timezone is available, and the timezone
    is associated with a country that uses only a single timezone, the name of
    that country is returned, formatted according to the locale:
    
    >>> tz = timezone('Europe/Berlin')
    >>> get_timezone_name(tz, locale='de_DE')
    u'Deutschland'
    >>> get_timezone_name(tz, locale='pt_BR')
    u'Hor\xe1rio Alemanha'
    
    On the other hand, if the country uses multiple timezones, the city is also
    included in the representation:
    
    >>> tz = timezone('America/St_Johns')
    >>> get_timezone_name(tz, locale='de_DE')
    u"Kanada (St. John's)"
    
    The `uncommon` parameter can be set to `True` to enable the use of timezone
    representations that are not commonly used by the requested locale. For
    example, while in frensh the central europian timezone is usually
    abbreviated as "HEC", in Canadian French, this abbreviation is not in
    common use, so a generic name would be chosen by default:
    
    >>> tz = timezone('Europe/Paris')
    >>> get_timezone_name(tz, 'short', locale='fr_CA')
    u'France'
    >>> get_timezone_name(tz, 'short', uncommon=True, locale='fr_CA')
    u'HEC'
    
    :param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines
                         the timezone; if a ``tzinfo`` object is used, the
                         resulting display name will be generic, i.e.
                         independent of daylight savings time; if `None`, the
                         current date in UTC is assumed
    :param width: either "long" or "short"
    :param uncommon: whether even uncommon timezone abbreviations should be used
    :param locale: the `Locale` object, or a locale string
    :return: the timezone display name
    :rtype: `unicode`
    :since: version 0.9
    :see:  `LDML Appendix J: Time Zone Display Names
            <http://www.unicode.org/reports/tr35/#Time_Zone_Fallback>`_
    """
    if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)):
        dt = None
        tzinfo = UTC
    elif isinstance(dt_or_tzinfo, (datetime, time)):
        dt = dt_or_tzinfo
        if dt.tzinfo is not None:
            tzinfo = dt.tzinfo
        else:
            tzinfo = UTC
    else:
        dt = None
        tzinfo = dt_or_tzinfo
    locale = Locale.parse(locale)

    if hasattr(tzinfo, 'zone'):
        zone = tzinfo.zone
    else:
        zone = tzinfo.tzname(dt)

    # Get the canonical time-zone code
    zone = get_global('zone_aliases').get(zone, zone)

    info = locale.time_zones.get(zone, {})
    # Try explicitly translated zone names first
    if width in info:
        if dt is None:
            field = 'generic'
        else:
            dst = tzinfo.dst(dt)
            if dst is None:
                field = 'generic'
            elif dst == 0:
                field = 'standard'
            else:
                field = 'daylight'
        if field in info[width]:
            return info[width][field]

    metazone = get_global('meta_zones').get(zone)
    if metazone:
        metazone_info = locale.meta_zones.get(metazone, {})
        if width in metazone_info and (uncommon
                                       or metazone_info.get('common')):
            if dt is None:
                field = 'generic'
            else:
                field = tzinfo.dst(dt) and 'daylight' or 'standard'
            if field in metazone_info[width]:
                return metazone_info[width][field]

    # If we have a concrete datetime, we assume that the result can't be
    # independent of daylight savings time, so we return the GMT offset
    if dt is not None:
        return get_timezone_gmt(dt, width=width, locale=locale)

    return get_timezone_location(dt_or_tzinfo, locale=locale)
Example #37
0
 def __init__(self, value, locale):
     assert isinstance(value, (date, datetime, time))
     if isinstance(value, (datetime, time)) and value.tzinfo is None:
         value = value.replace(tzinfo=UTC)
     self.value = value
     self.locale = Locale.parse(locale)
Example #38
0
 def test_display_name_property(self):
     assert Locale('en').display_name == 'English'
     assert Locale('en', 'US').display_name == 'English (United States)'
     assert Locale('sv').display_name == 'svenska'
Example #39
0
    def get_data(self):
        """
        Defines some attributes for the Sage notebook localization system.
        It must be overridden if subclassing for another project.
        Mandatory attributes that must be defined by this method:

        :attribute keywords: the file name of this script.
        :attribute method_map: files with localizable messages in the sources.
                                (see
                                `babel.messages.extract.extract_from_dir()
                                documentation)
        :attribute options_map: options for every class of localizable files,
                                (see
                                `babel.messages.extract.extract_from_dir()
                                documentation)
        :attribute charset: charset for `babel.messages.catalog.Catalog`.
        :attribute sort_by_file: message ordering for po and pot files. This
                                 option keeps changes in po and pot files small
                                 when changes in notebook sources are small.
        :attribute width: max line length for po and pot files. This option
                          contributes to keep changes in po and pot files small
                          when changes in notebook sources are small.
        :attribute langs: list of identifiers for available localizations in
                          the notebook.
        :attribute lang_names: localized names of available localizations.
        """
        #: function names surrounding translatable strings
        self.keywords = {
            '_': None,
            'gettext': None,
            'ngettext': (1, 2),
            'ugettext': None,
            'ungettext': (1, 2),
            'dgettext': (2,),
            'dngettext': (2, 3),
            'N_': None,
            'nN_': (1,2),
            'pgettext': ((1, 'c'), 2),
            'npgettext': ((1, 'c'), 2, 3),
            'lazy_gettext': None,
            'lazy_pgettext': ((1, 'c'), 2),
        }
        #: Source files to extract messages
        self.method_map = [
            ('sagewui/*.py', 'python'),
            ('sagewui/blueprints/**.py', 'python'),
            ('sagewui/util/**.py', 'python'),
            ('sagewui/gui/**.py', 'python'),
            ('sagewui/templates/html/**.html', 'jinja2'),
            ('sagewui/templates/js/**.js', 'jinja2')]
        #: Some configuration for each type of file
        opts = {
            'jinja2': {
                'encoding': 'utf-8',
                'extensions': 'jinja2.ext.autoescape,jinja2.ext.with_'},
            'python': {},
            }
        self.options_map = dict((m[0], opts[m[1]]) for m in self.method_map)

        #: Some defaults for babel package
        self.charset = 'utf-8'
        self.sort_by_file = True
        self.width = 76

        #: Available translations in the source tree
        names = os.listdir(self.path.trans)
        self.langs = []
        self.lang_names = []
        for name in names:
            try:
                locale = Locale.parse(name)
            except UnknownLocaleError:
                pass
            else:
                self.langs.append(name)
                self.lang_names.append(locale.display_name)
Example #40
0
def parse_locale_set(codes: List[str]) -> Set[Locale]:
    return {Locale.parse(code) for code in codes}
Example #41
0
def _locale(request):
    """
    Computes a babel.core:Locale() object for this request.
    """
    return Locale.parse(request.locale_name)
Example #42
0
 def test_currency_formats_property(self):
     assert (Locale(
         'en',
         'US').currency_formats['standard'].pattern == u'\xa4#,##0.00')
     assert (Locale('en', 'US').currency_formats['accounting'].pattern ==
             u'\xa4#,##0.00;(\xa4#,##0.00)')
Example #43
0
 def test_percent_formats_property(self):
     assert Locale('en', 'US').percent_formats[None].pattern == '#,##0%'
Example #44
0
def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME):
    """Return a time formatted according to the given pattern.
    
    >>> t = time(15, 30)
    >>> format_time(t, locale='en_US')
    u'3:30:00 PM'
    >>> format_time(t, format='short', locale='de_DE')
    u'15:30'
    
    If you don't want to use the locale default formats, you can specify a
    custom time pattern:
    
    >>> format_time(t, "hh 'o''clock' a", locale='en')
    u"03 o'clock PM"
    
    For any pattern requiring the display of the time-zone, the third-party
    ``pytz`` package is needed to explicitly specify the time-zone:
    
    >>> from pytz import timezone
    >>> t = datetime(2007, 4, 1, 15, 30)
    >>> tzinfo = timezone('Europe/Paris')
    >>> t = tzinfo.localize(t)
    >>> format_time(t, format='full', tzinfo=tzinfo, locale='fr_FR')
    u'15:30:00 HEC'
    >>> format_time(t, "hh 'o''clock' a, zzzz", tzinfo=timezone('US/Eastern'),
    ...             locale='en')
    u"09 o'clock AM, Eastern Daylight Time"
    
    As that example shows, when this function gets passed a
    ``datetime.datetime`` value, the actual time in the formatted string is
    adjusted to the timezone specified by the `tzinfo` parameter. If the
    ``datetime`` is "naive" (i.e. it has no associated timezone information),
    it is assumed to be in UTC.
    
    These timezone calculations are **not** performed if the value is of type
    ``datetime.time``, as without date information there's no way to determine
    what a given time would translate to in a different timezone without
    information about whether daylight savings time is in effect or not. This
    means that time values are left as-is, and the value of the `tzinfo`
    parameter is only used to display the timezone name if needed:
    
    >>> t = time(15, 30)
    >>> format_time(t, format='full', tzinfo=timezone('Europe/Paris'),
    ...             locale='fr_FR')
    u'15:30:00 HEC'
    >>> format_time(t, format='full', tzinfo=timezone('US/Eastern'),
    ...             locale='en_US')
    u'3:30:00 PM ET'
    
    :param time: the ``time`` or ``datetime`` object; if `None`, the current
                 time in UTC is used
    :param format: one of "full", "long", "medium", or "short", or a custom
                   date/time pattern
    :param tzinfo: the time-zone to apply to the time for display
    :param locale: a `Locale` object or a locale identifier
    :rtype: `unicode`
    
    :note: If the pattern contains date fields, an `AttributeError` will be
           raised when trying to apply the formatting. This is also true if
           the value of ``time`` parameter is actually a ``datetime`` object,
           as this function automatically converts that to a ``time``.
    """
    if time is None:
        time = datetime.utcnow()
    elif isinstance(time, (int, long)):
        time = datetime.utcfromtimestamp(time)
    if time.tzinfo is None:
        time = time.replace(tzinfo=UTC)
    if isinstance(time, datetime):
        if tzinfo is not None:
            time = time.astimezone(tzinfo)
            if hasattr(tzinfo, 'localize'):  # pytz
                time = tzinfo.normalize(time)
        time = time.timetz()
    elif tzinfo is not None:
        time = time.replace(tzinfo=tzinfo)

    locale = Locale.parse(locale)
    if format in ('full', 'long', 'medium', 'short'):
        format = get_time_format(format, locale=locale)
    return parse_pattern(format).apply(time, locale)
Example #45
0
def format_list(lst, style='standard', locale=DEFAULT_LOCALE):
    """
    Format the items in `lst` as a list.

    >>> format_list(['apples', 'oranges', 'pears'], locale='en')
    u'apples, oranges, and pears'
    >>> format_list(['apples', 'oranges', 'pears'], locale='zh')
    u'apples\u3001oranges\u548cpears'
    >>> format_list(['omena', 'peruna', 'aplari'], style='or', locale='fi')
    u'omena, peruna tai aplari'

    These styles are defined, but not all are necessarily available in all locales.
    The following text is verbatim from the Unicode TR35-49 spec [1].

    * standard:
      A typical 'and' list for arbitrary placeholders.
      eg. "January, February, and March"
    * standard-short:
      A short version of a 'and' list, suitable for use with short or abbreviated placeholder values.
      eg. "Jan., Feb., and Mar."
    * or:
      A typical 'or' list for arbitrary placeholders.
      eg. "January, February, or March"
    * or-short:
      A short version of an 'or' list.
      eg. "Jan., Feb., or Mar."
    * unit:
      A list suitable for wide units.
      eg. "3 feet, 7 inches"
    * unit-short:
      A list suitable for short units
      eg. "3 ft, 7 in"
    * unit-narrow:
      A list suitable for narrow units, where space on the screen is very limited.
      eg. "3′ 7″"

    [1]: https://www.unicode.org/reports/tr35/tr35-49/tr35-general.html#ListPatterns

    :param lst: a sequence of items to format in to a list
    :param style: the style to format the list with. See above for description.
    :param locale: the locale
    """
    locale = Locale.parse(locale)
    if not lst:
        return ''
    if len(lst) == 1:
        return lst[0]

    if style not in locale.list_patterns:
        raise ValueError(
            'Locale %s does not support list formatting style %r (supported are %s)'
            % (
                locale,
                style,
                list(sorted(locale.list_patterns)),
            ))
    patterns = locale.list_patterns[style]

    if len(lst) == 2:
        return patterns['2'].format(*lst)

    result = patterns['start'].format(lst[0], lst[1])
    for elem in lst[2:-1]:
        result = patterns['middle'].format(result, elem)
    result = patterns['end'].format(result, lst[-1])

    return result
Example #46
0
    def test_2_num_plurals_checkers(self):
        # in this testcase we add an extra msgstr[idx], we should be
        # disregarding it
        for _locale in [p for p in PLURALS if PLURALS[p][0] == 2]:
            if _locale in ['nn', 'no']:
                _locale = 'nn_NO'
                num_plurals = PLURALS[_locale.split('_')[0]][0]
                plural_expr = PLURALS[_locale.split('_')[0]][1]
            else:
                num_plurals = PLURALS[_locale][0]
                plural_expr = PLURALS[_locale][1]
            try:
                locale = Locale(_locale)
                date = format_datetime(datetime.now(LOCALTZ),
                                       'yyyy-MM-dd HH:mmZ',
                                       tzinfo=LOCALTZ,
                                       locale=_locale),
            except UnknownLocaleError:
                # Just an alias? Not what we're testing here, let's continue
                continue
            po_file = (ur"""\
# %(english_name)s translations for TestProject.
# Copyright (C) 2007 FooBar, Inc.
# This file is distributed under the same license as the TestProject
# project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2007.
#
msgid ""
msgstr ""
"Project-Id-Version: TestProject 0.1\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2007-04-01 15:30+0200\n"
"PO-Revision-Date: %(date)s\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: %(locale)s <*****@*****.**>\n"
"Plural-Forms: nplurals=%(num_plurals)s; plural=%(plural_expr)s\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel %(version)s\n"

#. This will be a translator comment,
#. that will include several lines
#: project/file1.py:8
msgid "bar"
msgstr ""

#: project/file2.py:9
msgid "foobar"
msgid_plural "foobars"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""

""" % dict(locale=_locale,
            english_name=locale.english_name,
            version=VERSION,
            year=time.strftime('%Y'),
            date=date,
            num_plurals=num_plurals,
            plural_expr=plural_expr)).encode('utf-8')
            # we should be adding the missing msgstr[0]

            # This test will fail for revisions <= 406 because so far
            # catalog.num_plurals was neglected
            catalog = read_po(StringIO(po_file), _locale)
            message = catalog['foobar']
            checkers.num_plurals(catalog, message)
Example #47
0

COUNTRY_CODES = """
    AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ
    BL BM BN BO BQ BR BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR
    CU CV CW CX CY CZ DE DJ DK DM DO DZ EC EE EG EH ER ES ET FI FJ FK FM FO FR
    GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HM HN HR HT HU
    ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY KZ
    LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ
    MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF
    PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SE SG SH SI
    SJ SK SL SM SN SO SR SS ST SV SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR
    TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS YE YT ZA ZM ZW
""".split()

COUNTRIES = make_sorted_dict(COUNTRY_CODES, Locale('en').territories)

LANGUAGE_CODES_2 = """
    aa af ak am ar as az be bg bm bn bo br bs ca cs cy da de dz ee el en eo es
    et eu fa ff fi fo fr ga gd gl gu gv ha he hi hr hu hy ia id ig ii is it ja
    ka ki kk kl km kn ko ks kw ky lg ln lo lt lu lv mg mk ml mn mr ms mt my nb
    nd ne nl nn nr om or os pa pl ps pt rm rn ro ru rw se sg si sk sl sn so sq
    sr ss st sv sw ta te tg th ti tn to tr ts uk ur uz ve vi vo xh yo zh zu
""".split()

LANGUAGES_2 = make_sorted_dict(LANGUAGE_CODES_2, Locale('en').languages)

LOCALES = {}
LOCALE_EN = LOCALES['en'] = Locale('en')
LOCALE_EN.catalog = Catalog('en')
LOCALE_EN.catalog.plural_func = lambda n: n != 1
Example #48
0
def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME):
    """Return a representation of the given timezone using "location format".
    
    The result depends on both the local display name of the country and the
    city assocaited with the time zone:
    
    >>> from pytz import timezone
    >>> tz = timezone('America/St_Johns')
    >>> get_timezone_location(tz, locale='de_DE')
    u"Kanada (St. John's)"
    >>> tz = timezone('America/Mexico_City')
    >>> get_timezone_location(tz, locale='de_DE')
    u'Mexiko (Mexiko-Stadt)'
    
    If the timezone is associated with a country that uses only a single
    timezone, just the localized country name is returned:
    
    >>> tz = timezone('Europe/Berlin')
    >>> get_timezone_name(tz, locale='de_DE')
    u'Deutschland'
    
    :param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines
                         the timezone; if `None`, the current date and time in
                         UTC is assumed
    :param locale: the `Locale` object, or a locale string
    :return: the localized timezone name using location format
    :rtype: `unicode`
    :since: version 0.9
    """
    if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)):
        dt = None
        tzinfo = UTC
    elif isinstance(dt_or_tzinfo, (datetime, time)):
        dt = dt_or_tzinfo
        if dt.tzinfo is not None:
            tzinfo = dt.tzinfo
        else:
            tzinfo = UTC
    else:
        dt = None
        tzinfo = dt_or_tzinfo
    locale = Locale.parse(locale)

    if hasattr(tzinfo, 'zone'):
        zone = tzinfo.zone
    else:
        zone = tzinfo.tzname(dt or datetime.utcnow())

    # Get the canonical time-zone code
    zone = get_global('zone_aliases').get(zone, zone)

    info = locale.time_zones.get(zone, {})

    # Otherwise, if there is only one timezone for the country, return the
    # localized country name
    region_format = locale.zone_formats['region']
    territory = get_global('zone_territories').get(zone)
    if territory not in locale.territories:
        territory = 'ZZ'  # invalid/unknown
    territory_name = locale.territories[territory]
    if territory and len(get_global('territory_zones').get(territory,
                                                           [])) == 1:
        return region_format % (territory_name)

    # Otherwise, include the city in the output
    fallback_format = locale.zone_formats['fallback']
    if 'city' in info:
        city_name = info['city']
    else:
        metazone = get_global('meta_zones').get(zone)
        metazone_info = locale.meta_zones.get(metazone, {})
        if 'city' in metazone_info:
            city_name = metainfo['city']
        elif '/' in zone:
            city_name = zone.split('/', 1)[1].replace('_', ' ')
        else:
            city_name = zone.replace('_', ' ')

    return region_format % (fallback_format % {
        '0': city_name,
        '1': territory_name
    })
Example #49
0
def format_timedelta(delta,
                     granularity='second',
                     threshold=.85,
                     add_direction=False,
                     format='long',
                     locale=LC_TIME):
    """Return a time delta according to the rules of the given locale.

    >>> format_timedelta(timedelta(weeks=12), locale='en_US')
    u'3 months'
    >>> format_timedelta(timedelta(seconds=1), locale='es')
    u'1 segundo'

    The granularity parameter can be provided to alter the lowest unit
    presented, which defaults to a second.

    >>> format_timedelta(timedelta(hours=3), granularity='day',
    ...                  locale='en_US')
    u'1 day'

    The threshold parameter can be used to determine at which value the
    presentation switches to the next higher unit. A higher threshold factor
    means the presentation will switch later. For example:

    >>> format_timedelta(timedelta(hours=23), threshold=0.9, locale='en_US')
    u'1 day'
    >>> format_timedelta(timedelta(hours=23), threshold=1.1, locale='en_US')
    u'23 hours'

    In addition directional information can be provided that informs
    the user if the date is in the past or in the future:

    >>> format_timedelta(timedelta(hours=1), add_direction=True, locale='en')
    u'in 1 hour'
    >>> format_timedelta(timedelta(hours=-1), add_direction=True, locale='en')
    u'1 hour ago'

    :param delta: a ``timedelta`` object representing the time difference to
                  format, or the delta in seconds as an `int` value
    :param granularity: determines the smallest unit that should be displayed,
                        the value can be one of "year", "month", "week", "day",
                        "hour", "minute" or "second"
    :param threshold: factor that determines at which point the presentation
                      switches to the next higher unit
    :param add_direction: if this flag is set to `True` the return value will
                          include directional information.  For instance a
                          positive timedelta will include the information about
                          it being in the future, a negative will be information
                          about the value being in the past.
    :param format: the format (currently only "long" and "short" are supported,
                   "medium" is deprecated, currently converted to "long" to
                   maintain compatibility)
    :param locale: a `Locale` object or a locale identifier
    """
    if format not in ('short', 'medium', 'long'):
        raise TypeError('Format can only be one of "short" or "medium"')
    if format == 'medium':
        warnings.warn(
            '"medium" value for format param of format_timedelta'
            ' is deprecated. Use "long" instead',
            category=DeprecationWarning)
        format = 'long'
    if isinstance(delta, timedelta):
        seconds = int((delta.days * 86400) + delta.seconds)
    else:
        seconds = delta
    locale = Locale.parse(locale)

    def _iter_patterns(a_unit):
        if add_direction:
            unit_rel_patterns = locale._data['date_fields'][a_unit]
            if seconds >= 0:
                yield unit_rel_patterns['future']
            else:
                yield unit_rel_patterns['past']
        a_unit = 'duration-' + a_unit
        yield locale._data['unit_patterns'].get(a_unit + ':' + format)
        yield locale._data['unit_patterns'].get(a_unit)

    for unit, secs_per_unit in TIMEDELTA_UNITS:
        value = abs(seconds) / secs_per_unit
        if value >= threshold or unit == granularity:
            if unit == granularity and value > 0:
                value = max(1, value)
            value = int(round(value))
            plural_form = locale.plural_form(value)
            pattern = None
            for patterns in _iter_patterns(unit):
                if patterns is not None:
                    pattern = patterns[plural_form]
                    break
            # This really should not happen
            if pattern is None:
                return u''
            return pattern.replace('{0}', str(value))

    return u''
Example #50
0
 def test_territories_property(self):
     assert Locale('es', 'CO').territories['DE'] == 'Alemania'
Example #51
0
def load_i18n(canonical_host, canonical_scheme, project_root, tell_sentry):
    # Load the locales
    localeDir = os.path.join(project_root, 'i18n', 'core')
    locales = LOCALES
    for file in os.listdir(localeDir):
        try:
            parts = file.split(".")
            if not (len(parts) == 2 and parts[1] == "po"):
                continue
            lang = parts[0]
            with open(os.path.join(localeDir, file)) as f:
                l = locales[lang.lower()] = Locale(lang)
                c = l.catalog = read_po(f)
                c.plural_func = get_function_from_rule(c.plural_expr)
                try:
                    l.countries = make_sorted_dict(COUNTRIES, l.territories)
                except KeyError:
                    l.countries = COUNTRIES
                try:
                    l.languages_2 = make_sorted_dict(LANGUAGES_2, l.languages)
                except KeyError:
                    l.languages_2 = LANGUAGES_2
        except Exception as e:
            tell_sentry(e, {}, allow_reraise=True)

    # Prepare a unique and sorted list for use in the language switcher
    percent = lambda l: sum((percent(s) if isinstance(s, tuple) else 1) for s in l if s) / len(l)
    for l in locales.values():
        if l.language == 'en':
            l.completion = 1
            continue
        l.completion = percent([m.string for m in l.catalog if m.id])
    loc_url = canonical_scheme+'://%s.'+canonical_host
    lang_list = sorted(
        (
            (l.completion, l.language, l.language_name.title(), loc_url % l.language)
            for l in set(locales.values()) if l.completion
        ),
        key=lambda t: (-t[0], t[1]),
    )

    # Add aliases
    for k, v in list(locales.items()):
        locales.setdefault(ALIASES.get(k, k), v)
        locales.setdefault(ALIASES_R.get(k, k), v)
    for k, v in list(locales.items()):
        locales.setdefault(k.split('_', 1)[0], v)

    # Patch the locales to look less formal
    locales['fr'].currency_formats[None] = parse_pattern('#,##0.00\u202f\xa4')
    locales['fr'].currency_symbols['USD'] = '$'

    # Load the markdown files
    docs = {}
    heading_re = re.compile(r'^(#+ )', re.M)
    for path in find_files(os.path.join(project_root, 'i18n'), '*.md'):
        d, b = os.path.split(path)
        doc = os.path.basename(d)
        lang = b[:-3]
        with open(path, 'rb') as f:
            md = f.read().decode('utf8')
            if md.startswith('# '):
                md = '\n'.join(md.split('\n')[1:]).strip()
                md = heading_re.sub(r'##\1', md)
            docs.setdefault(doc, {}).__setitem__(lang, markdown.render(md))

    return {'docs': docs, 'lang_list': lang_list, 'locales': locales}
Example #52
0
def format_currency(number,
                    currency,
                    format=None,
                    locale=LC_NUMERIC,
                    currency_digits=True,
                    format_type='standard'):
    u"""Return formatted currency value.

    >>> format_currency(1099.98, 'USD', locale='en_US')
    u'$1,099.98'
    >>> format_currency(1099.98, 'USD', locale='es_CO')
    u'US$\\xa01.099,98'
    >>> format_currency(1099.98, 'EUR', locale='de_DE')
    u'1.099,98\\xa0\\u20ac'

    The format 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'

    Currencies usually have a specific number of decimal digits. This function
    favours that information over the given format:

    >>> format_currency(1099.98, 'JPY', locale='en_US')
    u'\\xa51,100'
    >>> format_currency(1099.98, 'COP', u'#,##0.00', locale='es_ES')
    u'1.100'

    However, the number of decimal digits can be overriden from the currency
    information, by setting the last parameter to ``False``:

    >>> format_currency(1099.98, 'JPY', locale='en_US', currency_digits=False)
    u'\\xa51,099.98'
    >>> format_currency(1099.98, 'COP', u'#,##0.00', locale='es_ES', currency_digits=False)
    u'1.099,98'

    If a format is not specified the type of currency format to use
    from the locale can be specified:

    >>> format_currency(1099.98, 'EUR', locale='en_US', format_type='standard')
    u'\\u20ac1,099.98'

    When the given currency format type is not available, an exception is
    raised:

    >>> format_currency('1099.98', 'EUR', locale='root', format_type='unknown')
    Traceback (most recent call last):
        ...
    UnknownCurrencyFormatError: "'unknown' is not a known currency format type"

    :param number: the number to format
    :param currency: the currency code
    :param format: the format string to use
    :param locale: the `Locale` object or locale identifier
    :param currency_digits: use the currency's number of decimal digits
    :param format_type: the currency format type to use
    """
    locale = Locale.parse(locale)
    if format:
        pattern = parse_pattern(format)
    else:
        try:
            pattern = locale.currency_formats[format_type]
        except KeyError:
            raise UnknownCurrencyFormatError(
                "%r is not a known currency format"
                " type" % format_type)
    if currency_digits:
        precision = get_currency_precision(currency)
        frac = (precision, precision)
    else:
        frac = None
    return pattern.apply(number, locale, currency=currency, force_frac=frac)
Example #53
0
def format_unit(value,
                measurement_unit,
                length='long',
                format=None,
                locale=LC_NUMERIC):
    """Format a value of a given unit.

    Values are formatted according to the locale's usual pluralization rules
    and number formats.

    >>> format_unit(12, 'length-meter', locale='ro_RO')
    u'12 metri'
    >>> format_unit(15.5, 'length-mile', locale='fi_FI')
    u'15,5 mailia'
    >>> format_unit(1200, 'pressure-inch-hg', locale='nb')
    u'1\\xa0200 tommer kvikks\\xf8lv'

    Number formats may be overridden with the ``format`` parameter.

    >>> from babel._compat import Decimal
    >>> format_unit(Decimal("-42.774"), 'temperature-celsius', 'short', format='#.0', locale='fr')
    u'-42,8 \\xb0C'

    The locale's usual pluralization rules are respected.

    >>> format_unit(1, 'length-meter', locale='ro_RO')
    u'1 metru'
    >>> format_unit(0, 'length-picometer', locale='cy')
    u'0 picometr'
    >>> format_unit(2, 'length-picometer', locale='cy')
    u'2 bicometr'
    >>> format_unit(3, 'length-picometer', locale='cy')
    u'3 phicometr'

    >>> format_unit(15, 'length-horse', locale='fi')
    Traceback (most recent call last):
        ...
    UnknownUnitError: length-horse is not a known unit in fi

    .. versionadded:: 2.2.0

    :param value: the value to format. If this is a string, no number formatting will be attempted.
    :param measurement_unit: the code of a measurement unit.
                             Known units can be found in the CLDR Unit Validity XML file:
                             http://unicode.org/repos/cldr/tags/latest/common/validity/unit.xml
    :param length: "short", "long" or "narrow"
    :param format: An optional format, as accepted by `format_decimal`.
    :param locale: the `Locale` object or locale identifier
    """
    locale = Locale.parse(locale)

    q_unit = _find_unit_pattern(measurement_unit, locale=locale)
    if not q_unit:
        raise UnknownUnitError(unit=measurement_unit, locale=locale)
    unit_patterns = locale._data["unit_patterns"][q_unit].get(length, {})

    if isinstance(
            value,
            string_types):  # Assume the value is a preformatted singular.
        formatted_value = value
        plural_form = "one"
    else:
        formatted_value = format_decimal(value, format, locale)
        plural_form = locale.plural_form(value)

    if plural_form in unit_patterns:
        return unit_patterns[plural_form].format(formatted_value)

    # Fall back to a somewhat bad representation.
    # nb: This is marked as no-cover, as the current CLDR seemingly has no way for this to happen.
    return '%s %s' % (  # pragma: no cover
        formatted_value,
        (get_unit_name(measurement_unit, length=length, locale=locale)
         or measurement_unit))
Example #54
0
def get_timezone_name(dt_or_tzinfo=None,
                      width='long',
                      uncommon=False,
                      locale=LC_TIME,
                      zone_variant=None):
    r"""Return the localized display name for the given timezone. The timezone
    may be specified using a ``datetime`` or `tzinfo` object.

    >>> dt = time(15, 30, tzinfo=get_timezone('America/Los_Angeles'))
    >>> get_timezone_name(dt, locale='en_US')
    u'Pacific Standard Time'
    >>> get_timezone_name(dt, width='short', locale='en_US')
    u'PST'

    If this function gets passed only a `tzinfo` object and no concrete
    `datetime`,  the returned display name is indenpendent of daylight savings
    time. This can be used for example for selecting timezones, or to set the
    time of events that recur across DST changes:

    >>> tz = get_timezone('America/Los_Angeles')
    >>> get_timezone_name(tz, locale='en_US')
    u'Pacific Time'
    >>> get_timezone_name(tz, 'short', locale='en_US')
    u'PT'

    If no localized display name for the timezone is available, and the timezone
    is associated with a country that uses only a single timezone, the name of
    that country is returned, formatted according to the locale:

    >>> tz = get_timezone('Europe/Berlin')
    >>> get_timezone_name(tz, locale='de_DE')
    u'Mitteleurop\xe4ische Zeit'
    >>> get_timezone_name(tz, locale='pt_BR')
    u'Hor\xe1rio da Europa Central'

    On the other hand, if the country uses multiple timezones, the city is also
    included in the representation:

    >>> tz = get_timezone('America/St_Johns')
    >>> get_timezone_name(tz, locale='de_DE')
    u'Neufundland-Zeit'

    Note that short format is currently not supported for all timezones and
    all locales.  This is partially because not every timezone has a short
    code in every locale.  In that case it currently falls back to the long
    format.

    For more information see `LDML Appendix J: Time Zone Display Names
    <http://www.unicode.org/reports/tr35/#Time_Zone_Fallback>`_

    .. versionadded:: 0.9

    .. versionchanged:: 1.0
       Added `zone_variant` support.

    :param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines
                         the timezone; if a ``tzinfo`` object is used, the
                         resulting display name will be generic, i.e.
                         independent of daylight savings time; if `None`, the
                         current date in UTC is assumed
    :param width: either "long" or "short"
    :param uncommon: deprecated and ignored
    :param zone_variant: defines the zone variation to return.  By default the
                           variation is defined from the datetime object
                           passed in.  If no datetime object is passed in, the
                           ``'generic'`` variation is assumed.  The following
                           values are valid: ``'generic'``, ``'daylight'`` and
                           ``'standard'``.
    :param locale: the `Locale` object, or a locale string
    """
    if dt_or_tzinfo is None:
        dt = datetime.now()
        tzinfo = LOCALTZ
    elif isinstance(dt_or_tzinfo, string_types):
        dt = None
        tzinfo = get_timezone(dt_or_tzinfo)
    elif isinstance(dt_or_tzinfo, integer_types):
        dt = None
        tzinfo = UTC
    elif isinstance(dt_or_tzinfo, (datetime, time)):
        dt = dt_or_tzinfo
        if dt.tzinfo is not None:
            tzinfo = dt.tzinfo
        else:
            tzinfo = UTC
    else:
        dt = None
        tzinfo = dt_or_tzinfo
    locale = Locale.parse(locale)

    if hasattr(tzinfo, 'zone'):
        zone = tzinfo.zone
    else:
        zone = tzinfo.tzname(dt)

    if zone_variant is None:
        if dt is None:
            zone_variant = 'generic'
        else:
            dst = tzinfo.dst(dt)
            if dst:
                zone_variant = 'daylight'
            else:
                zone_variant = 'standard'
    else:
        if zone_variant not in ('generic', 'standard', 'daylight'):
            raise ValueError('Invalid zone variation')

    # Get the canonical time-zone code
    zone = get_global('zone_aliases').get(zone, zone)

    info = locale.time_zones.get(zone, {})
    # Try explicitly translated zone names first
    if width in info:
        if zone_variant in info[width]:
            return info[width][zone_variant]

    metazone = get_global('meta_zones').get(zone)
    if metazone:
        metazone_info = locale.meta_zones.get(metazone, {})
        if width in metazone_info:
            if zone_variant in metazone_info[width]:
                return metazone_info[width][zone_variant]

    # If we have a concrete datetime, we assume that the result can't be
    # independent of daylight savings time, so we return the GMT offset
    if dt is not None:
        return get_timezone_gmt(dt, width=width, locale=locale)

    return get_timezone_location(dt_or_tzinfo, locale=locale)
Example #55
0
 def test_english_name_property(self):
     assert Locale('de').english_name == 'German'
     assert Locale('de', 'DE').english_name == 'German (Germany)'
Example #56
0
def format_compound_unit(numerator_value,
                         numerator_unit=None,
                         denominator_value=1,
                         denominator_unit=None,
                         length='long',
                         format=None,
                         locale=LC_NUMERIC):
    """
    Format a compound number value, i.e. "kilometers per hour" or similar.

    Both unit specifiers are optional to allow for formatting of arbitrary values still according
    to the locale's general "per" formatting specifier.

    >>> format_compound_unit(7, denominator_value=11, length="short", locale="pt")
    '7/11'

    >>> format_compound_unit(150, "kilometer", denominator_unit="hour", locale="sv")
    '150 kilometer per timme'

    >>> format_compound_unit(150, "kilowatt", denominator_unit="year", locale="fi")
    '150 kilowattia vuodessa'

    >>> format_compound_unit(32.5, "ton", 15, denominator_unit="hour", locale="en")
    '32.5 tons per 15 hours'

    >>> format_compound_unit(160, denominator_unit="square-meter", locale="fr")
    '160 par m\\xe8tre carr\\xe9'

    >>> format_compound_unit(4, "meter", "ratakisko", length="short", locale="fi")
    '4 m/ratakisko'

    >>> format_compound_unit(35, "minute", denominator_unit="fathom", locale="sv")
    '35 minuter per famn'

    >>> from babel.numbers import format_currency
    >>> format_compound_unit(format_currency(35, "JPY", locale="de"), denominator_unit="liter", locale="de")
    '35\\xa0\\xa5 pro Liter'

    See http://www.unicode.org/reports/tr35/tr35-general.html#perUnitPatterns

    :param numerator_value: The numerator value. This may be a string,
                            in which case it is considered preformatted and the unit is ignored.
    :param numerator_unit: The numerator unit. See `format_unit`.
    :param denominator_value: The denominator value. This may be a string,
                              in which case it is considered preformatted and the unit is ignored.
    :param denominator_unit: The denominator unit. See `format_unit`.
    :param length: The formatting length. "short", "long" or "narrow"
    :param format: An optional format, as accepted by `format_decimal`.
    :param locale: the `Locale` object or locale identifier
    :return: A formatted compound value.
    """
    locale = Locale.parse(locale)

    # Look for a specific compound unit first...

    if numerator_unit and denominator_unit and denominator_value == 1:
        compound_unit = _find_compound_unit(numerator_unit,
                                            denominator_unit,
                                            locale=locale)
        if compound_unit:
            return format_unit(numerator_value,
                               compound_unit,
                               length=length,
                               format=format,
                               locale=locale)

    # ... failing that, construct one "by hand".

    if isinstance(numerator_value, string_types):  # Numerator is preformatted
        formatted_numerator = numerator_value
    elif numerator_unit:  # Numerator has unit
        formatted_numerator = format_unit(numerator_value,
                                          numerator_unit,
                                          length=length,
                                          format=format,
                                          locale=locale)
    else:  # Unitless numerator
        formatted_numerator = format_decimal(numerator_value,
                                             format=format,
                                             locale=locale)

    if isinstance(denominator_value,
                  string_types):  # Denominator is preformatted
        formatted_denominator = denominator_value
    elif denominator_unit:  # Denominator has unit
        if denominator_value == 1:  # support perUnitPatterns when the denominator is 1
            denominator_unit = _find_unit_pattern(denominator_unit,
                                                  locale=locale)
            per_pattern = locale._data["unit_patterns"].get(
                denominator_unit, {}).get(length, {}).get("per")
            if per_pattern:
                return per_pattern.format(formatted_numerator)
            # See TR-35's per-unit pattern algorithm, point 3.2.
            # For denominator 1, we replace the value to be formatted with the empty string;
            # this will make `format_unit` return " second" instead of "1 second".
            denominator_value = ""

        formatted_denominator = format_unit(denominator_value,
                                            denominator_unit,
                                            length=length,
                                            format=format,
                                            locale=locale).strip()
    else:  # Bare denominator
        formatted_denominator = format_decimal(denominator_value,
                                               format=format,
                                               locale=locale)

    per_pattern = locale._data["compound_unit_patterns"].get("per", {}).get(
        length, "{0}/{1}")

    return per_pattern.format(formatted_numerator, formatted_denominator)
Example #57
0
 def test_languages_property(self):
     assert Locale('de', 'DE').languages['ja'] == 'Japanisch'
Example #58
0
 def test_scripts_property(self):
     assert Locale('en', 'US').scripts['Hira'] == 'Hiragana'
Example #59
0
 def test_get_display_name(self):
     zh_CN = Locale('zh', 'CN', script='Hans')
     assert zh_CN.get_display_name('en') == 'Chinese (Simplified, China)'
Example #60
0
    def __init__(self, locale: str):
        self.locale = Locale.parse(locale)

        # This attribute can be set to `True` to differentiate multiple
        # locales currently available (supported) for the same language.
        self.use_display_name = False