23.2. locale — 国际化服务


    模块开通了 POSIX 本地化数据库和功能的访问。POSIX 本地化机制让程序员能够为应用程序处理某些本地化的问题,而不需要去了解运行软件的每个国家的全部文化特点。

    locale 模块是在 模块的基础上实现的,而 _locale 则又用到了 ANSI C 语言实现的本地化功能。

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

    exception locale.Error

    当传给 setlocale() 的 locale 无法识别时,会触发异常。

    locale.setlocale(category, locale=None)

    如果给定了 locale 而不是 None, 会修改 category 的 locale 设置。可用的类别会在下面的数据描述中列出。locale 可以是一个字符串,也可以是两个字符串(语言代码和编码)组成的可迭代对象。若为可迭代对象,则会用地区别名引擎转换为一个地区名称。若为空字符串则指明采用用户的默认设置。如果 locale 设置修改失败,会触发 Error 异常。如果成功则返回新的 locale 设置。

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

    在大多数系统上都不是线程安全的。应用程序通常会如下调用:

    这会把所有类别的 locale 都设为用户的默认设置(通常在 LANG 环境变量中指定)。如果后续 locale 没有改动,则使用多线程应该不会产生问题。

    locale.localeconv()

    以字典的形式返回本地约定的数据库。此字典具有以下字符串作为键:

    可以将所有数值设置为 CHAR_MAX ,以指示此语言环境中未指定任何值。

    下面给出了 'p_sign_posn''n_sign_posn' 的可能值。

    解释

    0

    被括号括起来的货币和金额。

    1

    该标志应位于值和货币符号之前。

    2

    该标志应位于值和货币符号之后。

    3

    标志应该紧跟在值之前。

    4

    CHAR_MAX

    此语言环境中未指定任何内容。

    该函数将 LC_CTYPE 地区设为 LC_NUMERIC 地区,若地区不同且数字或货币字符为非 ASCII,则设置为 LC_MONETARY 地区。这个临时的改变会影响到其他线程。

    在 3.6.5 版更改: 现在在某些情况下,该函数会将 LC_CTYPE 地区设为 LC_NUMERIC 地区。

    locale.nl_langinfo(option)

    以字符串形式返回一些地区相关的信息。本函数并非在所有系统都可用,而且可用的 option 在不同平台上也可能不同。可填的参数值为数值,在 locale 模块中提供了对应的符号常量。

    函数可接受以下值。大部分含义都取自 GNU C 库。

    • locale.CODESET

      获取一个字符串,代表所选地区采用的字符编码名称。

    • locale.D_T_FMT

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

    • locale.D_FMT

      获取一个字符串,可用作 的格式串,以便以地区特定格式表示日期。

    • locale.T_FMT

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

    • locale.T_FMT_AMPM

      获取一个字符串,可用作 的格式串,以便以 am/pm 的格式表示时间。

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

      注解

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

    • MON_1 ... MON_12

      获取第 n 个月的名称。

    • ABMON_1 ... ABMON_12

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

    • locale.RADIXCHAR

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

    • locale.THOUSEP

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

    • locale.YESEXPR

      获取一个可供 regex 函数使用的正则表达式,用于识别需要回答是或否的问题的肯定回答。

      注解

      该表达式的语法适用于 C 库的 regex() 函数,可能与 re 中的语法不一样。

    • locale.NOEXPR

      获取一个可供 regex(3) 函数使用的正则表达式,用于识别需要回答是或否的问题的否定回答。

    • locale.CRNCYSTR

      获取货币符号,如果符号应位于数字之前,则在其前面加上“-”;如果符号应位于数字之后,则前面加“+”;如果符号应取代小数点字符,则前面加“.”。

    • locale.ERA

      获取一个字符串,代表当前地区使用的纪元。

      大多数地区都没有定义该值。定义了该值的一个案例日本。日本传统的日期表示方法中,包含了当时天皇统治朝代的名称。

      通常没有必要直接使用该值。在格式串中指定 E 符号,会让 函数启用此信息。返回字符串的格式并没有定义,因此不得假定各个系统都能理解。

    • locale.ERA_D_T_FMT

      获取一个字符串,可用作 time.strftime() 的格式串,以便以地区特定格式表示带纪元的日期和时间。

    • locale.ERA_T_FMT

      获取一个字符串,可用作 的格式串,以便以地区特定格式表示带纪元的时间。

    • locale.ALT_DIGITS

      获取 0 到 99 的表示法,最多不超过 100 个值。

    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'

    除了 'C' 之外,语言代码对应 RFC 1766 标准。如果 语言代码编码 不能确定,可为 None

    locale.getlocale(category=LC_CTYPE)

    以列表的形式返回指定地区类别的当前设置,结果包括 语言代码编码category 可以是 LC_* 之一, 除外。默认为 LC_CTYPE

    除了 'C' 之外,语言代码对应 标准。如果 语言代码编码 不能确定,可为 None

    locale.getpreferredencoding(do_setlocale=True)

    某些系统必须调用 setlocale() 才能获取用户偏好,所以本函数不是线程安全的。如果不需要或不希望调用 setlocale,do_setlocale 应设为 False

    locale.normalize(localename)

    为给定的区域名称返回标准代码。返回的区域代码已经格式化,可供 使用。 如果标准化操作失败,则返回原名称。

    如果给出的编码无法识别,则本函数默认采用区域代码的默认编码,这正类似于 setlocale()

    locale.resetlocale(category=LC_ALL)

    category 的区域设为默认值。

    默认设置通过调用 确定。category 默认为 LC_ALL

    locale.strcoll(string1, string2)

    根据当前的 设置,对两个字符串进行比较。与其他比较函数一样,根据 string1 位于 string2 之前、之后或是相同,返回负值、、正值或者 0

    locale.strxfrm(string)

    将字符串转换为可用于本地化比较的字符串。例如 strxfrm(s1) < strxfrm(s2) 相当于 strcoll(s1, s2) < 0。在重复比较同一个字符串时,可能会用到本函数,比如整理字符串列表时。

    (format, val, grouping=False, monetary=False)

    根据当前的 LC_NUMERIC 设置,对数字 val 进行格式化。格式将遵循 % 运算符的约定。浮点值的小数点会按需修改。若 grouping 为 True,则还会考虑分组。

    monetary 为 True,则会用到货币千位分隔符和分组字符串。

    Please note that this function will only work for exactly one %char specifier. For whole format strings, use .

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

    格式化符的处理类似 format % val ,但会考虑到当前的区域设置。

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

    根据当前的 LC_MONETARY 设置,对数字 val 进行格式化。

    如果 symbol 为 True(默认值),则返回的字符串将包含货币符号。如果 grouping 为 True(非默认值),则会进行分组。如果 international 为 True(非默认值),将采用国际货币符号。

    请注意,本函数对区域 “C” 无效,所以必须先通过 设置一个区域。

    locale.str(float)

    对浮点数进行格式化,格式要求与内置函数 str(float) 相同,但会考虑小数点。

    locale.delocalize(string)

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

    3.5 新版功能.

    locale.atof(string)

    根据 的设置,将字符串转换为浮点数。

    locale.atoi(string)

    按照 LC_NUMERIC 的约定,将字符串转换为整数。

    locale.LC_CTYPE

    字符型函数的区域类别。根据该类别的设置,模块 中处理大小写的函数会改变操作方式。

    locale.LC_COLLATE

    字符串排序会用到的区域类别。 将会影响 locale 模块的 和 strxfrm() 函数。

    locale.LC_TIME

    格式化时间时会用到的区域类别。 函数会参考这些约定。

    locale.LC_MONETARY

    格式化货币值时会用到的区域类别。可用值可由 localeconv() 函数获取。

    locale.LC_MESSAGES

    显示消息时用到的区域类别。目前 Python 不支持应用定制的本地化消息。 由操作系统显示的消息,比如由 返回的消息可能会受到该类别的影响。

    locale.LC_NUMERIC

    格式化数字时用到的区域类别。 locale 模块的 、 atoi() 、 和 str() 函数会受到该类别的影响。其他所有数字格式化操作不受影响。

    locale.LC_ALL

    混合所有的区域设置。如果在区域改动时使用该标志,将尝试设置所有类别的区域参数。只要有任何一个类别设置失败,就不会修改任何类别。在使用此标志获取区域设置时,会返回一个代表所有类别设置的字符串。之后可用此字符串恢复设置。

    locale.CHAR_MAX

    一个符号常量, 返回多个值时将会用到。

    示例:

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

    The C standard defines the locale as a program-wide property that may be relatively expensive to change. On top of that, some implementation are broken in such a way that frequent locale changes may cause core dumps. This makes the locale somewhat painful to use correctly.

    当程序第一次启动时,无论用户偏好定义成什么,区域值都是 C。不过有一个例外,就是在启动时修改 LC_CTYPE 类别,设置当前区域编码为用户偏好编码。程序必须调用 setlocale(LC_ALL, '') 明确表示用户偏好区域将设为其他类别。

    若要从库程序中调用 ,通常这不是个好主意,因为副作用是会影响整个程序。保存和恢复区域设置也几乎一样糟糕:不仅代价高昂,而且会影响到恢复之前运行的其他线程。

    如果是要编写通用模块,需要有一种不受区域设置影响的操作方式(比如某些用到 time.strftime() 的格式),将不得不寻找一种不用标准库的方案。更好的办法是说服自己,可以采纳区域设置。只有在万不得已的情况下,才能用文档标注出模块与非 C 区域设置不兼容。

    根据区域设置进行数字运算的唯一方法,就是采用本模块定义的函数: 、 atoi() 、 、 str()

    无法根据区域设置进行大小写转换和字符分类。对于(Unicode)文本字符串来说,这些操作都是根据字符值进行的;而对于字节符串来说,转换和分类则是根据字节的 ASCII 值进行的,高位被置位的字节(即非 ASCII 字节)永远不会被转换或被视作字母或空白符之类。

    除了要查询当前区域,扩展模块不应去调用 。但由于返回值只能用于恢复设置,所以也没什么用(也许只能用于确认是否为 C)。

    当 Python 代码利用 locale 模块修改区域设置时,也会影响到嵌入 Python 运行的应用程序。如果嵌入运行的程序不希望发生这种情况,则应从 config.c 文件的内置模块表中删除 _locale 扩展模块(所有操作均是由它完成的),并确保 _locale 模块不能成为一个共享库。

    locale.gettext(msg)

    locale.dgettext(domain, msg)

    locale.dcgettext(domain, msg, category)

    locale.textdomain(domain)

    locale.bindtextdomain(domain, dir)

    Python 应用程序通常不需要调用这些函数,而应改用 。这条规则的一个已知例外,是与附加 C 库链接的应用程序,他们在内部调用了 或 dcgettext()。对于这些应用程序,可能有必要绑定文本域,以便库可以准确找到他们的信息目录。