# 23.2. `locale` - 国际化服务

源代码： Lib / locale.py

`locale`模块打开对POSIX语言环境数据库和功能的访问。POSIX语言环境机制允许程序员处理应用程序中的某些文化问题，而不需要程序员知道执行软件的每个国家的所有细节。

`locale`模块在`_locale`模块之上实现，而后者又使用ANSI C语言环境实现（如果可用）。

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

exception `locale.``Error`

  当区域设置传递到`setlocale()`时无法识别异常。

`locale.``setlocale`(category, locale=None)

  如果给定locale且`None`，`setlocale()`修改类别的区域设置。可用类别在下面的数据描述中列出。locale可以是字符串，也可以是两个字符串的迭代（语言代码和编码）。如果它是一个可迭代的，它将使用语言环境别名引擎转换为一个区域设置名称。空字符串指定用户的默认设置。如果语言环境的修改失败，则会引发异常`Error`。如果成功，则返回新的区域设置。

  如果省略locale或`None`，将返回类别的当前设置。

  `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.``nl_langinfo`(option)

  将一些特定于语言环境的信息作为字符串返回。此功能不适用于所有系统，并且可能的选项集也可能在不同平台上有所不同。可能的参数值是数字，符号常量在语言环境模块中可用。

  `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格式表示时间。

  `DAY_1 ... DAY_7`

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

    注意

    这符合美国惯例`DAY_1`为星期日，而不是国际惯例（ISO 8601），星期一是一周的第一天。

  `ABDAY_1 ... ABDAY_7`

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

  `MON_1 ... MON_12`

    获取第n个月的名称。

  `ABMON_1 ... ABMON_12`

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

  `locale.``RADIXCHAR`

    获取基数字符（小数点，十进制逗号等））。

  `locale.``THOUSEP`

    获取数千（三位数的组）的分隔符。

  `locale.``YESEXPR`

    获取可以与正则表达式函数一起使用的正则表达式，以识别对是/否问题的肯定响应。

    注意

    表达式的语法适合于C库的`regex()`函数，它可能与`re`中使用的语法不同。

  `locale.``NOEXPR`

    获取可以与regex（3）函数一起使用的正则表达式来识别对是/否问题的否定响应。

  `locale.``CRNCYSTR`

    获取货币符号，如果符号应出现在值前面，则以“ - ”开头，如果符号应出现在值后面，则为“+”，如果符号应替换基数字符，则为“。

  `locale.``ERA`

    获取表示当前语言环境中使用的时代的字符串。

    大多数语言环境不定义此值。定义此值的语言环境的示例是日语语言环境。在日本，日期的传统表示包括对应于当时皇帝统治的时代的名称。

    通常不需要直接使用这个值。在其格式字符串中指定`E`修饰符会导致`time.strftime()`函数使用此信息。返回的字符串的格式未指定，因此您不应该在不同的系统上假设它的知识。

  `locale.``ERA_D_T_FMT`

    获取`time.strftime()`的格式字符串，以特定于语言环境的基于时代的方式表示日期和时间。

  `locale.``ERA_D_FMT`

    获取`time.strftime()`的格式字符串，以特定于语言环境的基于时代的方式表示日期。

  `locale.``ERA_T_FMT`

    获取`time.strftime()`的格式字符串，以特定于语言环境的基于时代的方式表示时间。

  `locale.``ALT_DIGITS`

    获取用于表示值0到99的最多100个值的表示。

`locale.``getdefaultlocale`([envvars])

  尝试确定默认语言环境设置，并以`（语言 代码， 编码）` 。

  根据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)

  将指定语言代码类别的当前设置作为包含语言代码，编码的序列返回。类别可以是除`LC_ALL`之外的`LC_*`值之一。它默认为`LC_CTYPE`。

  除了代码`'C'`，语言代码对应于 RFC 1766。如果无法确定其值，则语言代码和编码可能是`None`。

`locale.``getpreferredencoding`(do_setlocale=True)

  根据用户偏好返回用于文本数据的编码。用户首选项在不同系统上的表达方式不同，并且在某些系统上可能无法以编程方式使用，因此此函数仅返回猜测。

  在某些系统上，有必要调用`setlocale()`以获取用户首选项，因此此函数不是线程安全的。如果不需要或不需要调用setlocale，则应将do_setlocale设置为`False`。

`locale.``normalize`(localename)

  返回给定语言环境名称的标准化语言环境代码。返回的语言环境代码的格式为与`setlocale()`一起使用。如果规范化失败，原始名称将不更改地返回。

  如果给定的编码未知，该函数默认为区域设置代码的默认编码，就像`setlocale()`。

`locale.``resetlocale`(category=LC_ALL)

  将类别的区域设置设置为默认设置。

  默认设置是通过调用`getdefaultlocale()`确定的。类别默认为`LC_ALL`。

`locale.``strcoll`(string1, string2)

  根据当前`LC_COLLATE`设置比较两个字符串。作为任何其他比较函数，根据string1是在string2之前还是之后返回一个负值或正值或`0`等于它。

`locale.``strxfrm`(string)

  将字符串转换为可在区域设置感知比较中使用的字符串。例如，`strxfrm（s1） strxfrm（s2）`等效于`strcoll（s1， s2） ＆lt； 0`。当相同的字符串被重复比较时，可以使用该函数。当比较字符串序列时。

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

  根据当前的`LC_NUMERIC`设置格式化数字val。格式遵循`%`操作符号的约定。对于浮点值，如果适当，将修改小数点。如果分组为真，也会考虑分组。

  如果currency为真，则转换使用货币千位分隔符和分组字符串。

  请注意，此函数仅适用于正好一个％char说明符。对于整个格式字符串，请使用`format_string()`。

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

  按`格式 ％ val`处理格式说明符，但会考虑当前的区域设置。

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

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

  如果符号为true，则返回的字符串包含货币符号，这是默认值。如果分组为true（这不是默认值），则使用该值进行分组。如果国际为真（这不是默认值），则使用国际货币符号。

  请注意，此函数不能与“C”语言环境一起使用，因此您必须首先通过`setlocale()`设置语言环境。

`locale.``str`(float)

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

`locale.``delocalize`(string)

  在`LC_NUMERIC`设置后，将字符串转换为规范化的数字字符串。

  版本3.5中的新功能。

`locale.``atof`(string)

  将字符串转换为浮点数，紧跟`LC_NUMERIC`设置。

`locale.``atoi`(string)

  将字符串转换为整数，遵循`LC_NUMERIC`约定。

`locale.``LC_CTYPE`

  字符类型函数的区域设置类别。Depending on the settings of this category, the functions of module `string` dealing with case change their behaviour.

`locale.``LC_COLLATE`

  用于排序字符串的区域设置类别。`locale`模块的函数`strcoll()`和`strxfrm()`

`locale.``LC_TIME`

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

`locale.``LC_MONETARY`

  货币值格式化的区域设置类别。可用的选项可从`localeconv()`函数获得。

`locale.``LC_MESSAGES`

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

`locale.``LC_NUMERIC`

  格式化数字的区域设置类别。The functions `format()`, `atoi()`, `atof()` and `str()` of the `locale` module are affected by that category. 所有其他数字格式化操作不受影响。

`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

## 23.2.1. Background, details, hints, tips and caveats

C标准将区域设置定义为程序范围的属性，其可能相对昂贵以改变。最重要的是，一些实现被破坏，频繁的区域设置更改可能会导致核心转储。这使得locale有点痛苦，正确使用。

最初，当程序启动时，区域设置是`C`区域设置，无论用户的首选区域设置是什么。有一个例外：在启动时更改`LC_CTYPE`类别，将当前语言环境编码设置为用户首选语言环境编码。程序必须通过调用`setlocale（LC_ALL， “'）`来明确表示需要用户对其他类别的首选语言环境设置。

在一些库例程中调用`setlocale()`通常是个坏主意，因为作为副作用它影响整个程序。保存和恢复它几乎同样糟糕：它是昂贵的，并影响在设置恢复之前运行的其他线程。

如果在为一般使用的模块编码时，需要受语言环境影响的操作的语言环境独立版本（例如与`time.strftime()`一起使用的某些格式），则必须找到一种方法来做，而不使用标准库程序。更好的是说服自己使用区域设置是好的。作为最后的手段，您应该记录您的模块与非`C`区域设置不兼容。

根据语言环境执行数字操作的唯一方法是使用此模块定义的特殊函数：`atof()`，`atoi()`，`format()`，`str()`。

没有办法根据语言环境执行案例转换和字符分类。对于（Unicode）文本字符串，这些仅根据字符值完成，而对于字节字符串，转换和分类根据字节的ASCII值以及设置高位的字节（即，非ASCII字节）永远不会被转换或视为字符类的一部分，例如字母或空格。

## 23.2.2. For extension writers and programs that embed Python

扩展模块不应调用`setlocale()`，除非找出当前语言环境。但是由于返回值只能用于可移植地恢复它，这不是非常有用（除非可能找出区域设置是否`C`）。

当Python代码使用`locale`模块更改语言环境时，这也会影响嵌入应用程序。If the embedding application doesn’t want this to happen, it should remove the `_locale` extension module (which does all the work) from the table of built-in modules in the `config.c` file, and make sure that the `_locale` module is not accessible as a shared library.

## 23.2.3. Access to message catalogs

locale模块在提供此接口的系统上公开了C库的gettext接口。It consists of the functions `gettext()`, `dgettext()`, `dcgettext()`, `textdomain()`, `bindtextdomain()`, and `bind_textdomain_codeset()`. 这些类似于`gettext`模块中的相同功能，但是对于消息目录使用C库的二进制格式，并且使用C库的搜索算法来定位消息目录。

Python应用程序通常不需要调用这些函数，应该使用`gettext`。此规则的一个已知异常是应用程序与内部调用`gettext()`或`dcgettext()`的其他C库链接。对于这些应用程序，可能需要绑定文本域，以便库可以正确定位其消息目录。