gettext 模块为 Python 模块和应用程序提供国际化(i18n)和本地化(l10n)支持。该模块既支持 GNU gettext 风格的 API,也支持更高级的、基于类的 API。通过 gettext,在应用程序中,可以只使用一种自然语言。在运行时,再将其翻译成多种不同的自然语言。
需要注意的是:GNU 风格的 API 会全局地影响整个应用程序的翻译。因此当应用程序需要在运行时切换语言时,那么应该使用基于类的 API。
gettext.bindtextdomain(domain, localedir=None)
该函数用于将 domain 绑定到 locale 目录 localedir。对于给定的 domain 而言,gettext 会使用路径 <localedir>/<language>/LC_MESSAGES/<domain>.mo
寻找二进制的 .mo 文件。其中 language 的值是环境变量 LANGUAGE
、LC_ALL
、 LC_MESSAGES
和 LANG
中的第一个非空值。
如果省略 localedir 或将其设置为 None,那么该函数会返回 domain 当前绑定的 locale 目录。
gettext.bind_textdomain_codeset(domain, codeset=None)
该函数用于将 domain 绑定到 codeset 上。它会改变 gettext 系列函数所返回的字符串的编码。如果忽略 codeset,那么将返回当前绑定的字符集。
gettext.textdomain(domain=None)
更改或查询当前的全局 domain。如果 domain 参数的值为 None,那么该函数返回当前的全局 domain,否则将当前的全局 domain 设置为 domain 参数所指定的值,并返回。
gettext.gettext(message)
根据当前的全局 domain、language 和 locale 目录,返回 message 的本地化翻译。
接下来用一个实例说明如何使用 gettext,示例代码(test.py)如下:
xxxxxxxxxx
# coding: utf-8
import os
import gettext
for name in ["LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG"]:
if name in os.environ and os.environ[name]:
print("当前的语言环境是:", os.environ[name])
break
gettext.bindtextdomain("test_messages", "translations/")
gettext.textdomain("test_messages")
_ = gettext.gettext
print(_("just a test string"))
gettext.textdomain("messages")
print(_("just a test string"))
其中 # coding: utf-8
用于指定源代码文件的编码。
执行下面的流程完成本地化翻译:
1, 创建 locale 目录:
xxxxxxxxxx
mkdir -p translations/en_US/LC_MESSAGES/
其中 en_US 是要使用的语言。
2,使用 GNU 工具 xgettext 从源代码中抽取需要国际化的文本消息:
xxxxxxxxxx
xgettext test.py -o test_messages.pot
其中 test_messages 是要使用的 domain。
3,使用 test_messages.pot 作为模版,创建 test_messages.po 文件,并将 po 文件拷贝到 locale 目录:
xxxxxxxxxx
# vim test_messages.pot
...
"Content-Type: text/plain; charset=UTF-8\n"
...
msgid "just a test string"
msgstr "这是一个测试字符串"
# mv test_messages.pot translations/en_US/LC_MESSAGES/test_messages.po
在 Content-Type 中指定编码。
4,将 .po 文件转换成二进制的 .mo 文件:
xxxxxxxxxx
msgfmt translations/en_US/LC_MESSAGES/test_messages.po -o translations/en_US/LC_MESSAGES/test_messages.mo
5,执行测试代码:
xxxxxxxxxx
# echo $LANG
zh_CN.UTF-8
# python3 test.py
当前的语言环境是: zh_CN.UTF-8
just a test string
just a test string
# LANG=en_US.UTF-8
# python3 test.py
当前的语言环境是: en_US.UTF-8
这是一个测试字符串
just a test string
gettext.find(domain, localedir=None, languages=None, all=False)
该函数实现了标准的 .mo 文件搜索算法。其中 domain 参数的含义与 gettext.textdomain()
函数中的 domain 参数的含义相同;可选的 localedir 参数的含义与 gettext.bindtextdomain()
函数中的 localedir 参数的含义相同;可选的 languages 参数是一个字符串列表,列表中的每个字符串是一个语言代码。
如果未指定 localedir,那么会使用系统默认的 locale 目录。如果未指定 languages,那么会使用环境变量 LANGUAGE
、LC_ALL
、 LC_MESSAGES
和 LANG
中的第一个非空值,这几个环境变量的值应该是冒号分隔的语言编码列表。
find()
函数会展开和标准化 languages,然后通过迭代它们,搜索 .mo 文件(<localedir>/<language>/LC_MESSAGES/<domain>.mo
)。
默认情况下,find()
函数在找到一个已经存在的 .mo 文件后,就会返回。如果将 all 参数设置为 True,那么 find()
函数会返回所有符合条件的 .mo 文件的列表。
gettext.translation(domain, localedir=None, languages=None, class_=None, fallback=False, codeset=None)
该函数根据 domain、localedir、languages,返回一个 Translations
实例,这些参数首先会被传递给 find()
函数,以获取相关的 .mo 文件的路径列表。
如果提供了 class_ 参数,那么将使用它所指定的类来生成 Translations
实例,否则使用 GNUTranslations
类生成 Translations
实例。这些类的构造器必须有且仅有一个 file object
参数。
如果未找到 .mo 文件,并且 fallback 参数为 False,那么该函数将抛出 OSError
异常;如果 fallback 参数为 True,那么将返回一个 NullTranslations
实例。
下面是 test.py 的另外一种写法:
xxxxxxxxxx
import gettext
translation = gettext.translation("test_messages", "translations/", languages=["en_US", "zh_CN"])
_ = translation.gettext
print(_("just a test string"))