16.2. locale — 本地人文接口 | 国际化和本地化 |《python 3 标准库实例教程》| python 技术论坛-380玩彩网官网入口
目的:处理依赖于用户语言与位置的格式与值解析。
locale
模块是 python 的国际化和本地化支持库的一部分。他提供了一种标准方式用于处理依赖于用户语言与位置的相关操作。举个例子:将数字格式化为货币、排序中的字符串比较、处理时间和日期。但这个模块并不包括翻译(参见 模块)和 unicode 编码(参见 模块)相关的函数。
注解
改变地区设置会产生应用级别的影响,所以最佳实践是避免改变库中的值,而让应用自己设置一次。在本章的例子里,我们通过一个小程序多次改变地区设置,以便突出不同地区设置对程序的影响。更常见的情况是程序在启动时或收到一个 web 请求时设置地区,之后便不再改变它。
本章会包含 locale
模块的一些高级函数。同时也会介绍一些更低级的操作,如 format_string()
—— 格式化字符串和与管理应用地区设置有关的 resetlocale()
。
探索当前的地区设置
一般通过设置环境变量,让用户可以改变某个应用的地区设置。不同的平台环境变量也不相同,常见的有:lc_all
、lc_ctype
、lang
或 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
参见
- (英文)
- (英文)
- -- 供翻译使用的消息分类。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 cc 协议,如果我们的工作有侵犯到您的权益,请及时联系380玩彩网官网入口。