16.2. locale — 本地人文接口 | 国际化和本地化 |《python 3 标准库实例教程》| python 技术论坛-江南app体育官方入口

未匹配的标注

目的:处理依赖于用户语言与位置的格式与值解析。

locale 模块是 python 的国际化和本地化支持库的一部分。他提供了一种标准方式用于处理依赖于用户语言与位置的相关操作。举个例子:将数字格式化为货币、排序中的字符串比较、处理时间和日期。但这个模块并不包括翻译(参见  模块)和 unicode 编码(参见  模块)相关的函数。

注解

改变地区设置会产生应用级别的影响,所以最佳实践是避免改变库中的值,而让应用自己设置一次。在本章的例子里,我们通过一个小程序多次改变地区设置,以便突出不同地区设置对程序的影响。更常见的情况是程序在启动时或收到一个 web 请求时设置地区,之后便不再改变它。

本章会包含 locale 模块的一些高级函数。同时也会介绍一些更低级的操作,如 format_string() —— 格式化字符串和与管理应用地区设置有关的 resetlocale()

探索当前的地区设置

一般通过设置环境变量,让用户可以改变某个应用的地区设置。不同的平台环境变量也不相同,常见的有:lc_alllc_ctypelang或 language
然后程序通过调用 setlocale() 函数从环境变量中获取地区设置,而不是把地区设置硬编码在程序中。

locale_env.py

import locale
import os
import pprint
# 基于用户环境变量的默认值
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, ''))
    )
# 目前的地区设置是什么?
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() 方法会返回一个字典,其中包含了地区设置约定。字典中其它的名称与定义可以在标准库的文档中找到。

在运行 os x 10.11.6 系统的 mac 上,不设置任何环境变量时,运行程序会输出以下结果:

$ export lang=; export lc_ctype=; python3 locale_env.py
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):

$ lang=en_us lc_ctype=en_us lc_all=en_us python3 locale_env.py
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):

$ lang=fr_fr lc_ctype=fr_fr lc_all=fr_fr python3 locale_env.py
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):

$ lang=es_es lc_ctype=es_es lc_all=es_es python3 locale_env.py
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):

$ lang=pt_pt lc_ctype=pt_pt lc_all=pt_pt python3 locale_env.py
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):

$ lang=pl_pl lc_ctype=pl_pl lc_all=pl_pl python3 locale_env.py
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-

格式化数字

地区设置改变时,与货币单位无关的数字格式发生了变化。用于将大数字分割成可读小块的分组字符也发生了变化。

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('d', 123456, grouping=true), end=' ')
    print(locale.format('.2f', 123456.78, grouping=true))

要让格式化后的数字不带货币单位,应该使用 format() 而不是 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('%0.2f', 123456.78, grouping=true)
    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 mar 18 16:20:59 2018
    france: dim 18 mar 16:20:59 2018
     spain: dom 18 mar 16:20:59 2018
  portugal: dom 18 mar 16:20:59 2018
    poland: ndz 18 mar 16:20:59 2018

参见

  • (英文)
  • (英文)
  •  -- 供翻译使用的消息分类。

本文章首发在 江南app体育官方入口 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 cc 协议,如果我们的工作有侵犯到您的权益,请及时联系江南app体育官方入口。

原文地址:https://learnku.com/docs/pymotw/locale-c...

译文地址:https://learnku.com/docs/pymotw/locale-c...

上一篇 下一篇
讨论数量: 0



暂无话题~
网站地图