Рубрики
Без рубрики

locale – API культурной локализации

Автор оригинала: Doug Hellmann.

Цель:

Форматируйте и анализируйте значения, зависящие от местоположения или языка.

Модуль locale является частью библиотеки поддержки интернационализации и локализации Python. Он предоставляет стандартный способ обработки операций, которые могут зависеть от языка или местонахождения пользователя. Например, он обрабатывает форматирование чисел как валют, сравнивает строки для сортировки и работает с датами. Он не распространяется на перевод (см. Модуль gettext) или кодировку Unicode (см. Модуль кодеков).

Примечание

Изменение языкового стандарта может иметь последствия для всего приложения, поэтому рекомендуется избегать изменения значения в библиотеке и позволить приложению установить его один раз. В примерах этого раздела языковой стандарт изменяется несколько раз в рамках короткой программы, чтобы подчеркнуть различия в настройках различных языковых стандартов. Гораздо более вероятно, что приложение установит языковой стандарт один раз при запуске или при получении веб-запроса и не изменит его.

В этом разделе рассматриваются некоторые высокоуровневые функции модуля locale . Есть и другие, которые относятся к более низкому уровню или относятся к управлению локалью для приложения ( resetlocale () ).

Проверка текущего языкового стандарта

Наиболее распространенный способ позволить пользователю изменить настройки локали для приложения – использовать переменную среды ( LC_ALL , LC_CTYPE , LANG или < code> LANGUAGE , в зависимости от платформы). Затем приложение вызывает setlocale () без жестко запрограммированного значения, и используется значение среды.

locale_env.py

import locale
import os
import pprint

# Default settings based on the user's environment.
locale.setlocale(locale.LC_ALL, '')

print('Environment settings:')
for env_name in ['LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE']:
    print('  {} = {}'.format(
        env_name, os.environ.get(env_name, ''))
    )

# What is the locale?
print('\nLocale from environment:', locale.getlocale())

template  """
Numeric formatting:

  Decimal point      : "{decimal_point}"
  Grouping positions : {grouping}
  Thousands separator: "{thousands_sep}"

Monetary formatting:

  International currency symbol   : "{int_curr_symbol!r}"
  Local currency symbol           : {currency_symbol!r}
  Symbol precedes positive value  : {p_cs_precedes}
  Symbol precedes negative value  : {n_cs_precedes}
  Decimal point                   : "{mon_decimal_point}"
  Digits in fractional values     : {frac_digits}
  Digits in fractional values,
                   international  : {int_frac_digits}
  Grouping positions              : {mon_grouping}
  Thousands separator             : "{mon_thousands_sep}"
  Positive sign                   : "{positive_sign}"
  Positive sign position          : {p_sign_posn}
  Negative sign                   : "{negative_sign}"
  Negative sign position          : {n_sign_posn}

"""

sign_positions  {
    0: 'Surrounded by parentheses',
    1: 'Before value and symbol',
    2: 'After value and symbol',
    3: 'Before value',
    4: 'After value',
    locale.CHAR_MAX: 'Unspecified',
}

info  {}
info.update(locale.localeconv())
info['p_sign_posn']  sign_positions[info['p_sign_posn']]
info['n_sign_posn']  sign_positions[info['n_sign_posn']]

print(template.format(**info))

Метод localeconv () возвращает словарь, содержащий соглашения о локали. Полный список имен и определений значений содержится в документации стандартной библиотеки.

Mac под управлением OS X 10.11.6 со всеми неустановленными переменными дает следующий результат:

$

Environment settings:
  LC_ALL =
  LC_CTYPE =
  LANG =
  LANGUAGE =

Locale from environment: (None, None)

Numeric formatting:

  Decimal point      : "."
  Grouping positions : []
  Thousands separator: ""

Monetary formatting:

  International currency symbol   : "''"
  Local currency symbol           : ''
  Symbol precedes positive value  : 127
  Symbol precedes negative value  : 127
  Decimal point                   : ""
  Digits in fractional values     : 127
  Digits in fractional values,
                   international  : 127
  Grouping positions              : []
  Thousands separator             : ""
  Positive sign                   : ""
  Positive sign position          : Unspecified
  Negative sign                   : ""
  Negative sign position          : Unspecified

Выполнение того же сценария с набором переменных LANG показывает, как меняются языковой стандарт и кодировка по умолчанию.

США ( en_US ):

$

Environment settings:
  LC_ALL = en_US
  LC_CTYPE = en_US
  LANG = en_US
  LANGUAGE =

Locale from environment: ('en_US', 'ISO8859-1')

Numeric formatting:

  Decimal point      : "."
  Grouping positions : [3, 3, 0]
  Thousands separator: ","

Monetary formatting:

  International currency symbol   : "'USD '"
  Local currency symbol           : '$'
  Symbol precedes positive value  : 1
  Symbol precedes negative value  : 1
  Decimal point                   : "."
  Digits in fractional values     : 2
  Digits in fractional values,
                   international  : 2
  Grouping positions              : [3, 3, 0]
  Thousands separator             : ","
  Positive sign                   : ""
  Positive sign position          : Before value and symbol
  Negative sign                   : "-"
  Negative sign position          : Before value and symbol

Франция ( fr_FR ):

$

Environment settings:
  LC_ALL = fr_FR
  LC_CTYPE = fr_FR
  LANG = fr_FR
  LANGUAGE =

Locale from environment: ('fr_FR', 'ISO8859-1')

Numeric formatting:

  Decimal point      : ","
  Grouping positions : [127]
  Thousands separator: ""

Monetary formatting:

  International currency symbol   : "'EUR '"
  Local currency symbol           : 'Eu'
  Symbol precedes positive value  : 0
  Symbol precedes negative value  : 0
  Decimal point                   : ","
  Digits in fractional values     : 2
  Digits in fractional values,
                   international  : 2
  Grouping positions              : [3, 3, 0]
  Thousands separator             : " "
  Positive sign                   : ""
  Positive sign position          : Before value and symbol
  Negative sign                   : "-"
  Negative sign position          : After value and symbol

Испания ( es_ES ):

$

Environment settings:
  LC_ALL = es_ES
  LC_CTYPE = es_ES
  LANG = es_ES
  LANGUAGE =

Locale from environment: ('es_ES', 'ISO8859-1')

Numeric formatting:

  Decimal point      : ","
  Grouping positions : [127]
  Thousands separator: ""

Monetary formatting:

  International currency symbol   : "'EUR '"
  Local currency symbol           : 'Eu'
  Symbol precedes positive value  : 0
  Symbol precedes negative value  : 0
  Decimal point                   : ","
  Digits in fractional values     : 2
  Digits in fractional values,
                   international  : 2
  Grouping positions              : [3, 3, 0]
  Thousands separator             : "."
  Positive sign                   : ""
  Positive sign position          : Before value and symbol
  Negative sign                   : "-"
  Negative sign position          : Before value and symbol

Португалия ( pt_PT ):

$

Environment settings:
  LC_ALL = pt_PT
  LC_CTYPE = pt_PT
  LANG = pt_PT
  LANGUAGE =

Locale from environment: ('pt_PT', 'ISO8859-1')

Numeric formatting:

  Decimal point      : ","
  Grouping positions : []
  Thousands separator: " "

Monetary formatting:

  International currency symbol   : "'EUR '"
  Local currency symbol           : 'Eu'
  Symbol precedes positive value  : 0
  Symbol precedes negative value  : 0
  Decimal point                   : "."
  Digits in fractional values     : 2
  Digits in fractional values,
                   international  : 2
  Grouping positions              : [3, 3, 0]
  Thousands separator             : "."
  Positive sign                   : ""
  Positive sign position          : Before value and symbol
  Negative sign                   : "-"
  Negative sign position          : Before value and symbol

Польша ( pl_PL ):

$

Environment settings:
  LC_ALL = pl_PL
  LC_CTYPE = pl_PL
  LANG = pl_PL
  LANGUAGE =

Locale from environment: ('pl_PL', 'ISO8859-2')

Numeric formatting:

  Decimal point      : ","
  Grouping positions : [3, 3, 0]
  Thousands separator: " "

Monetary formatting:

  International currency symbol   : "'PLN '"
  Local currency symbol           : 'zł'
  Symbol precedes positive value  : 1
  Symbol precedes negative value  : 1
  Decimal point                   : ","
  Digits in fractional values     : 2
  Digits in fractional values,
                   international  : 2
  Grouping positions              : [3, 3, 0]
  Thousands separator             : " "
  Positive sign                   : ""
  Positive sign position          : After value
  Negative sign                   : "-"
  Negative sign position          : After value

Валюта

Предыдущий пример выходных данных показывает, что при изменении локали обновляется настройка символа валюты и символа для отделения целых чисел от десятичных дробей. В этом примере просматривается несколько разных языковых стандартов, чтобы напечатать положительное и отрицательное значение валюты, отформатированное для каждого языкового стандарта.

locale_currency.py

import locale

sample_locales  [
    ('USA', 'en_US'),
    ('France', 'fr_FR'),
    ('Spain', 'es_ES'),
    ('Portugal', 'pt_PT'),
    ('Poland', 'pl_PL'),
]

for name, loc in sample_locales:
    locale.setlocale(locale.LC_ALL, loc)
    print('{:>10}: {:>10}  {:>10}'.format(
        name,
        locale.currency(1234.56),
        locale.currency(-1234.56),
    ))

Результатом является эта небольшая таблица:

$ python3 locale_currency.py

       USA:   $1234.56   -$1234.56
    France: 1234,56 Eu  1234,56 Eu-
     Spain: 1234,56 Eu  -1234,56 Eu
  Portugal: 1234.56 Eu  -1234.56 Eu
    Poland: zł 1234,56  zł 1234,56-

Форматирование чисел

Числа, не относящиеся к валюте, также форматируются по-разному в зависимости от локали. В частности, изменяется символ grouping , используемый для разделения больших чисел на читаемые фрагменты.

locale_grouping.py

import locale

sample_locales  [
    ('USA', 'en_US'),
    ('France', 'fr_FR'),
    ('Spain', 'es_ES'),
    ('Portugal', 'pt_PT'),
    ('Poland', 'pl_PL'),
]

print('{:>10} {:>10} {:>15}'.format(
    'Locale', 'Integer', 'Float')
)
for name, loc in sample_locales:
    locale.setlocale(locale.LC_ALL, loc)

    print('{:>10}'.format(name), end' ')
    print(locale.format_string('%10d', 123456, groupingTrue), end' ')
    print(locale.format_string('%15.2f', 123456.78, groupingTrue))

Чтобы отформатировать числа без символа валюты, используйте format_string () вместо currency () .

$ python3 locale_grouping.py

    Locale    Integer           Float
       USA    123,456      123,456.78
    France     123456       123456,78
     Spain     123456       123456,78
  Portugal     123456       123456,78
    Poland    123 456      123 456,78

Чтобы преобразовать числа в формате локали в нормализованный формат, не зависящий от языкового стандарта, используйте delocalize () .

locale_delocalize.py

import locale

sample_locales  [
    ('USA', 'en_US'),
    ('France', 'fr_FR'),
    ('Spain', 'es_ES'),
    ('Portugal', 'pt_PT'),
    ('Poland', 'pl_PL'),
]

for name, loc in sample_locales:
    locale.setlocale(locale.LC_ALL, loc)
    localized  locale.format_string('%0.2f', 123456.78, groupingTrue)
    delocalized  locale.delocalize(localized)
    print('{:>10}: {:>10}  {:>10}'.format(
        name,
        localized,
        delocalized,
    ))

Знаки пунктуации при группировке удаляются, а десятичный разделитель всегда заменяется . .

$ python3 locale_delocalize.py

       USA: 123,456.78   123456.78
    France:  123456,78   123456.78
     Spain:  123456,78   123456.78
  Portugal:  123456,78   123456.78
    Poland: 123 456,78   123456.78

Разбор чисел

Помимо создания вывода в различных форматах, модуль locale помогает при синтаксическом анализе ввода. Он включает функции atoi () и atof () для преобразования строк в целые числа и значения с плавающей запятой на основе соглашений о числовом форматировании языкового стандарта.

locale_atof.py

import locale

sample_data  [
    ('USA', 'en_US', '1,234.56'),
    ('France', 'fr_FR', '1234,56'),
    ('Spain', 'es_ES', '1234,56'),
    ('Portugal', 'pt_PT', '1234.56'),
    ('Poland', 'pl_PL', '1 234,56'),
]

for name, loc, a in sample_data:
    locale.setlocale(locale.LC_ALL, loc)
    print('{:>10}: {:>9} => {:f}'.format(
        name,
        a,
        locale.atof(a),
    ))

Значения группировки и десятичного разделителя языкового стандарта распознаются анализатором.

$ python3 locale_atof.py

       USA:  1,234.56 => 1234.560000
    France:   1234,56 => 1234.560000
     Spain:   1234,56 => 1234.560000
  Portugal:   1234.56 => 1234.560000
    Poland:  1 234,56 => 1234.560000

Даты и время

Другой важный аспект локализации – форматирование даты и времени.

locale_date.py

import locale
import time

sample_locales  [
    ('USA', 'en_US'),
    ('France', 'fr_FR'),
    ('Spain', 'es_ES'),
    ('Portugal', 'pt_PT'),
    ('Poland', 'pl_PL'),
]

for name, loc in sample_locales:
    locale.setlocale(locale.LC_ALL, loc)
    format  locale.nl_langinfo(locale.D_T_FMT)
    print('{:>10}: {}'.format(name, time.strftime(format)))

В этом примере используется строка форматирования даты для языкового стандарта для печати текущей даты и времени.

$ python3 locale_date.py

       USA: Sun Dec  9 12:20:00 2018
    France: Dim  9 déc 12:20:00 2018
     Spain: dom  9 dic 12:20:00 2018
  Portugal: Dom  9 Dez 12:20:00 2018
    Poland: ndz  9 gru 12:20:00 2018

Смотрите также