locale --- 国际化服务

源代码: Lib/locale.py


locale 模块开放了对 POSIX locale 数据库和功能的访问。POSIX locale 机制允许程序员处理应用程序中的某些文化问题,而无需程序员了解软件执行的每个国家/地区的所有细节。

locale 模块是在 _locale 模块之上实现的,后者又在可用时使用 ANSI C locale 实现。

locale 模块定义了以下异常和函数

exception locale.Error

当传递给 setlocale() 的 locale 未被识别时引发的异常。

locale.setlocale(category, locale=None)

如果 locale 被给出且不为 Nonesetlocale() 将修改 category 的区域设置。可用的类别在下面的数据描述中列出。locale 可以是一个 字符串,或者一个由语言代码和编码组成的元组。空字符串指定用户的默认设置。如果 locale 的修改失败,则会引发 Error 异常。如果成功,将返回新的区域设置。

如果 locale 是一个元组,它将使用 locale 别名引擎转换为 locale 名称。语言代码的格式与区域设置名称相同,但没有编码和 @-修饰符。语言代码和编码可以是 None

如果 locale 省略或为 None,则返回 category 的当前设置。

在大多数系统上,setlocale() 不是线程安全的。应用程序通常以调用以下代码开始

import locale
locale.setlocale(locale.LC_ALL, '')

这将所有类别的区域设置设为用户的默认设置(通常在 LANG 环境变量中指定)。如果之后不更改区域设置,使用多线程应该不会导致问题。

locale.localeconv()

以字典形式返回本地惯例的数据库。该字典包含以下字符串作为键

类别

含义

LC_NUMERIC

'decimal_point'

小数点字符。

'grouping'

指定 'thousands_sep' 预期出现位置的相对位置的数字序列。如果序列以 CHAR_MAX 结尾,则不再进行分组。如果序列以 0 结尾,则重复使用最后一个组的大小。

'thousands_sep'

组之间使用的字符。

LC_MONETARY

'int_curr_symbol'

国际货币符号。

'currency_symbol'

本地货币符号。

'p_cs_precedes/n_cs_precedes'

货币符号是否在值之前(分别对应正值和负值)。

'p_sep_by_space/n_sep_by_space'

货币符号是否与值之间用空格分隔(分别对应正值和负值)。

'mon_decimal_point'

用于货币值的小数点。

'frac_digits'

本地货币值格式中使用的小数位数。

'int_frac_digits'

国际货币值格式中使用的小数位数。

'mon_thousands_sep'

用于货币值的组分隔符。

'mon_grouping'

等同于 'grouping',用于货币值。

'positive_sign'

用于标注正货币值的符号。

'negative_sign'

用于标注负货币值的符号。

'p_sign_posn/n_sign_posn'

符号的位置(分别对应正值和负值),见下文。

所有数值都可以设置为 CHAR_MAX,以表示在此区域设置中没有指定值。

'p_sign_posn''n_sign_posn' 的可能值如下。

说明

0

货币和值被括号包围。

1

符号应在值和货币符号之前。

2

符号应在值和货币符号之后。

3

符号应紧接在值之前。

4

符号应紧接在值之后。

CHAR_MAX

此区域设置中未指定任何内容。

如果 locale 不同并且数字或货币字符串为非 ASCII,该函数会临时将 LC_CTYPE locale 设置为 LC_NUMERIC locale 或 LC_MONETARY locale。此临时更改会影响其他线程。

在 3.7 版更改: 在某些情况下,该函数现在会临时将 LC_CTYPE locale 设置为 LC_NUMERIC locale。

locale.nl_langinfo(option)

以字符串形式返回一些特定于区域设置的信息。此函数并非在所有系统上都可用,并且可能的选项集也可能因平台而异。可能的参数值是数字,在 locale 模块中有相应的符号常量。

nl_langinfo() 函数接受以下键之一。大多数描述均取自 GNU C 库中的相应描述。

locale.CODESET

获取一个字符串,其中包含所选区域设置中使用的字符编码的名称。

locale.D_T_FMT

获取一个可用作 time.strftime() 格式字符串的字符串,以特定于区域设置的方式表示日期和时间。

locale.D_FMT

获取一个可用作 time.strftime() 格式字符串的字符串,以特定于区域设置的方式表示日期。

locale.T_FMT

获取一个可用作 time.strftime() 格式字符串的字符串,以特定于区域设置的方式表示时间。

locale.T_FMT_AMPM

获取 time.strftime() 的格式字符串,以 am/pm 格式表示时间。

locale.DAY_1
locale.DAY_2
locale.DAY_3
locale.DAY_4
locale.DAY_5
locale.DAY_6
locale.DAY_7

获取一周中第 n 天的名称。

备注

这遵循美国的惯例,即 DAY_1 是星期日,而不是国际惯例(ISO 8601)中星期一为一周的第一天。

locale.ABDAY_1
locale.ABDAY_2
locale.ABDAY_3
locale.ABDAY_4
locale.ABDAY_5
locale.ABDAY_6
locale.ABDAY_7

获取一周中第 n 天的缩写名称。

locale.MON_1
locale.MON_2
locale.MON_3
locale.MON_4
locale.MON_5
locale.MON_6
locale.MON_7
locale.MON_8
locale.MON_9
locale.MON_10
locale.MON_11
locale.MON_12

获取第 n 个月的名称。

locale.ABMON_1
locale.ABMON_2
locale.ABMON_3
locale.ABMON_4
locale.ABMON_5
locale.ABMON_6
locale.ABMON_7
locale.ABMON_8
locale.ABMON_9
locale.ABMON_10
locale.ABMON_11
locale.ABMON_12

获取第 n 个月的缩写名称。

locale.RADIXCHAR

获取基数字符(小数点、小数逗号等)。

locale.THOUSEP

获取千位(三位数字组)的分隔符。

locale.YESEXPR

获取一个可与 regex 函数一起使用的正则表达式,用于识别对“是/否”问题的肯定回答。

locale.NOEXPR

获取一个可与 regex(3) 函数一起使用的正则表达式,用于识别对“是/否”问题的否定回答。

备注

YESEXPRNOEXPR 的正则表达式使用适用于 C 库中 regex 函数的语法,这可能与 re 中使用的语法不同。

locale.CRNCYSTR

获取货币符号,如果符号应出现在值之前,则前缀为“-”;如果符号应出现在值之后,则前缀为“+”;如果符号应替换基数字符,则前缀为“.”。

locale.ERA

获取一个描述在区域设置中每个纪元的年份如何计数和显示的字符串。

大多数区域设置不定义此值。一个定义此值的区域设置示例是日语区域设置。在日本,日期的传统表示包括与当时天皇统治相对应的纪元年号。

通常不需要直接使用此值。在格式字符串中指定 E 修饰符会使 time.strftime() 函数使用此信息。返回字符串的格式在 The Open Group Base Specifications Issue 8,段落 7.3.5.2 LC_TIME C-Language Access 中指定。

locale.ERA_D_T_FMT

获取一个 time.strftime() 的格式化字符串,用于以特定于区域的、基于纪元的方式表示日期和时间。

locale.ERA_D_FMT

获取一个 time.strftime() 的格式化字符串,用于以特定于区域的、基于纪元的方式表示日期。

locale.ERA_T_FMT

获取一个 time.strftime() 的格式化字符串,用于以特定于区域的、基于纪元的方式表示时间。

locale.ALT_DIGITS

获取一个由最多 100 个分号分隔的符号组成的字符串,用于以特定于区域的方式表示 0 到 99 的值。在大多数区域中,这是一个空字符串。

如果区域设置不同且结果字符串为非 ASCII,该函数会临时将 LC_CTYPE 区域设置为确定请求值的类别的区域(LC_TIME, LC_NUMERIC, LC_MONETARYLC_MESSAGES)。此临时更改会影响其他线程。

在 3.14 版更改: 该函数现在在某些情况下会临时设置 LC_CTYPE 区域设置。

locale.getdefaultlocale([envvars])

尝试确定默认的区域设置,并以 (language code, encoding) 形式的元组返回它们。

根据 POSIX,未调用 setlocale(LC_ALL, '') 的程序使用可移植的 'C' 区域。调用 setlocale(LC_ALL, '') 让它使用由 LANG 变量定义的默认区域。由于我们不想干扰当前的区域设置,因此我们以上述方式模拟该行为。

为了与其他平台保持兼容性,不仅测试 LANG 变量,还会测试作为 envvars 参数给出的变量列表。第一个被发现已定义的将被使用。envvars 默认为 GNU gettext 中使用的搜索路径;它必须始终包含变量名 'LANG'。GNU gettext 搜索路径包含 'LC_ALL''LC_CTYPE''LANG''LANGUAGE',按此顺序。

语言代码的格式与区域设置名称相同,但没有编码和 @-修饰符。如果无法确定其值,语言代码和编码可以为 None。"C" 区域表示为 (None, None)

自 3.11 版起弃用,将在 3.15 版中移除。

locale.getlocale(category=LC_CTYPE)

返回给定区域类别的当前设置,形式为包含语言代码和编码的元组。category 可以是 LC_* 值之一,除了 LC_ALL。它默认为 LC_CTYPE

语言代码的格式与区域设置名称相同,但没有编码和 @-修饰符。如果无法确定其值,语言代码和编码可以为 None。"C" 区域表示为 (None, None)

locale.getpreferredencoding(do_setlocale=True)

根据用户偏好,返回用于文本数据的区域编码。用户偏好在不同系统上的表达方式不同,并且在某些系统上可能无法通过编程方式获得,因此此函数仅返回一个猜测值。

在某些系统上,需要调用 setlocale() 来获取用户偏好,因此该函数不是线程安全的。如果不需要或不希望调用 setlocale,do_setlocale 应设置为 False

在 Android 上或启用了Python UTF-8 模式时,总是返回 'utf-8'区域编码do_setlocale 参数会被忽略。

Python 预初始化会配置 LC_CTYPE 区域。另请参阅文件系统编码和错误处理程序

在 3.7 版更改: 该函数现在在 Android 上或启用Python UTF-8 模式时总是返回 "utf-8"

locale.getencoding()

获取当前的区域编码

  • 在 Android 和 VxWorks 上,返回 "utf-8"

  • 在 Unix 上,返回当前 LC_CTYPE 区域的编码。如果 nl_langinfo(CODESET) 返回空字符串,则返回 "utf-8":例如,如果当前 LC_CTYPE 区域不受支持。

  • 在 Windows 上,返回 ANSI 代码页。

Python 预初始化会配置 LC_CTYPE 区域。另请参阅文件系统编码和错误处理程序

此函数类似于 getpreferredencoding(False),但此函数忽略Python UTF-8 模式

在 3.11 版本中新增。

locale.normalize(localename)

为给定的区域名称返回一个规范化的区域代码。返回的区域代码已格式化,可用于 setlocale()。如果规范化失败,则返回原始名称不变。

如果给定的编码未知,函数将默认使用区域代码的默认编码,就像 setlocale() 一样。

locale.strcoll(string1, string2)

根据当前的 LC_COLLATE 设置比较两个字符串。与其他比较函数一样,根据 string1 是排在 string2 之前、之后还是与之相等,返回负值、正值或 0

locale.strxfrm(string)

将字符串转换为可用于区域感知比较的字符串。例如,strxfrm(s1) < strxfrm(s2) 等价于 strcoll(s1, s2) < 0。当同一个字符串被重复比较时,例如在整理字符串序列时,可以使用此函数。

locale.format_string(format, val, grouping=False, monetary=False)

根据当前的 LC_NUMERIC 设置格式化数字 val。格式遵循 % 运算符的约定。对于浮点值,如果适用,小数点将被修改。如果 groupingTrue,还会考虑分组。

如果 monetary 为真,转换将使用货币千位分隔符和分组字符串。

format % val 一样处理格式说明符,但会考虑当前的区域设置。

在 3.7 版更改: 增加了 monetary 关键字参数。

locale.currency(val, symbol=True, grouping=False, international=False)

根据当前的 LC_MONETARY 设置格式化数字 val

如果 symbol 为真(默认值),返回的字符串将包含货币符号。如果 groupingTrue(非默认值),将对值进行分组。如果 internationalTrue(非默认值),将使用国际货币符号。

备注

此函数在“C”区域设置下无法工作,因此您必须先通过 setlocale() 设置一个区域。

locale.str(float)

使用与内置函数 str(float) 相同的格式格式化浮点数,但会考虑小数点。

locale.delocalize(string)

根据 LC_NUMERIC 设置将字符串转换为规范化的数字字符串。

在 3.5 版本加入。

locale.localize(string, grouping=False, monetary=False)

根据 LC_NUMERIC 设置,将规范化的数字字符串转换为格式化的字符串。

在 3.10 版本加入。

locale.atof(string, func=float)

根据 LC_NUMERIC 设置,通过对 string 调用 delocalize() 的结果调用 func,将字符串转换为数字。

locale.atoi(string)

根据 LC_NUMERIC 约定将字符串转换为整数。

locale.LC_CTYPE

字符类型函数的区域类别。最重要的是,此类别定义了文本编码,即字节如何被解释为 Unicode 码点。有关此变量如何可能被自动强制为 C.UTF-8 以避免容器中无效设置或通过远程 SSH 连接传递的不兼容设置所造成的问题,请参阅 PEP 538PEP 540

Python 内部不使用 ctype.h 中依赖于区域的字符转换函数。相反,一个内部的 pyctype.h 提供了与区域无关的等价物,如 Py_TOLOWER

locale.LC_COLLATE

用于排序字符串的区域类别。 locale 模块的 strcoll()strxfrm() 函数受此影响。

locale.LC_TIME

用于时间格式化的区域类别。time.strftime() 函数遵循这些约定。

locale.LC_MONETARY

用于格式化货币值的区域类别。可用选项可通过 localeconv() 函数获得。

locale.LC_MESSAGES

用于消息显示的区域类别。Python 目前不支持应用程序特定的区域感知消息。操作系统显示的消息,如 os.strerror() 返回的消息,可能会受此类别的影响。

此值可能在不符合 POSIX 标准的操作系统上不可用,最显著的是 Windows。

locale.LC_NUMERIC

用于格式化数字的区域类别。 locale 模块的 format_string()atoi()atof()str() 函数受此类别影响。所有其他数字格式化操作不受影响。

locale.LC_ALL

所有区域设置的组合。如果在更改区域时使用此标志,则会尝试为所有类别设置区域。如果任何类别设置失败,则所有类别都不会更改。使用此标志检索区域时,将返回一个指示所有类别设置的字符串。此字符串以后可用于恢复设置。

locale.CHAR_MAX

这是一个符号常量,用于 localeconv() 返回的不同值。

示例

>>> import locale
>>> loc = locale.getlocale()  # get current locale
# use German locale; name might vary with platform
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
>>> locale.strcoll('f\xe4n', 'foo')  # compare a string containing an umlaut
>>> locale.setlocale(locale.LC_ALL, '')   # use user's preferred locale
>>> locale.setlocale(locale.LC_ALL, 'C')  # use default (C) locale
>>> locale.setlocale(locale.LC_ALL, loc)  # restore saved locale

背景、细节、提示、技巧和注意事项

C 标准将区域定义为一个程序范围的属性,更改它可能相对昂贵。此外,某些实现存在缺陷,频繁更改区域可能导致核心转储。这使得正确使用区域有些痛苦。

最初,当程序启动时,无论用户的首选区域是什么,区域都是 C 区域。有一个例外:LC_CTYPE 类别在启动时被更改,以将当前区域编码设置为用户的首选区域编码。程序必须通过调用 setlocale(LC_ALL, '') 明确表示它希望对其他类别使用用户的首选区域设置。

在某些库例程中调用 setlocale() 通常是个坏主意,因为它会作为副作用影响整个程序。保存和恢复它几乎同样糟糕:它代价高昂,并且会影响在设置恢复之前碰巧运行的其他线程。

如果在编写通用模块时,你需要一个受区域影响的操作的与区域无关的版本(例如 time.strftime() 使用的某些格式),你将必须找到一种不使用标准库例程的方法来完成它。更好的做法是说服自己使用区域设置是可以的。只有在万不得已的情况下,才应记录你的模块与非 C 区域设置不兼容。

根据区域执行数字操作的唯一方法是使用此模块定义的特殊函数:atof()atoi()format_string()str()

没有办法根据区域设置执行大小写转换和字符分类。对于(Unicode)文本字符串,这些操作仅根据字符值进行,而对于字节串,转换和分类是根据字节的 ASCII 值进行的,高位被设置的字节(即非 ASCII 字节)永远不会被转换或被视作字符类(如字母或空白)的一部分。

区域设置名称

区域设置名称的格式取决于平台,支持的区域设置集可能取决于系统配置。

在 Posix 平台上,它通常具有以下格式 [1]

  language ["_" territory] ["." charset] ["@" modifier]

其中 language 是来自 ISO 639 的两或三字母语言代码,territory 是来自 ISO 3166 的两字母国家或地区代码,charset 是一个区域编码,而 modifier 是一个脚本名称、语言子标签、排序顺序标识符或其他区域修饰符(例如,“latin”、“valencia”、“stroke”和“euro”)。

在 Windows 上,支持多种格式。[2] [3] IETF BCP 47 标签的一个子集

  language ["-" script] ["-" territory] ["." charset]
  language ["-" script] "-" territory "-" modifier

其中 languageterritory 的含义与 Posix 中的相同,script 是来自 ISO 15924 的四字母脚本代码,modifier 是语言子标签、排序顺序标识符或自定义修饰符(例如,“valencia”、“stroke”或“x-python”)。连字符 ('-') 和下划线 ('_') 分隔符都支持。BCP 47 标签只允许 UTF-8 编码。

Windows 还支持以下格式的区域名称

  language ["_" territory] ["." charset]

其中 languageterritory 是全名,例如“English”和“United States”,而 charset 是代码页编号(例如,“1252”)或 UTF-8。此格式仅支持下划线分隔符。

“C”区域在所有平台上都受支持。

给扩展模块编写者和嵌入 Python 的程序

扩展模块决不应该调用 setlocale(),除非是为了找出当前的区域设置。但由于返回值只能用于可移植地恢复它,所以这并不十分有用(除了或许可以用来确定区域设置是否为 C)。

当 Python 代码使用 locale 模块更改区域设置时,这也会影响嵌入的应用程序。如果嵌入的应用程序不希望发生这种情况,它应该从 config.c 文件中的内置模块表中移除 _locale 扩展模块(它完成了所有工作),并确保 _locale 模块不能作为共享库访问。

访问消息目录

locale.gettext(msg)
locale.dgettext(domain, msg)
locale.dcgettext(domain, msg, category)
locale.textdomain(domain)
locale.bindtextdomain(domain, dir)
locale.bind_textdomain_codeset(domain, codeset)

locale 模块在提供此接口的系统上公开了 C 库的 gettext 接口。它由 gettext()dgettext()dcgettext()textdomain()bindtextdomain()bind_textdomain_codeset() 函数组成。这些函数与 gettext 模块中的同名函数类似,但使用 C 库的消息目录二进制格式,以及 C 库的搜索算法来定位消息目录。

Python 应用程序通常不需要调用这些函数,而应使用 gettext。此规则的一个已知例外是那些链接了其他 C 库的应用程序,这些库内部调用 C 函数 gettextdcgettext。对于这些应用程序,可能需要绑定文本域,以便库可以正确地定位其消息目录。