使用邮件目录

介绍

这个 gettext 翻译系统使您能够将应用程序中使用的任何字符串标记为本地化,方法是将它们包装在如下函数中 gettext(str)ngettext(singular, plural, num) 。为简明起见, gettext 函数通常别名为 _(str) ,因此您可以编写:

print(_("Hello"))

而不仅仅是:

print("Hello")

若要使字符串“Hello”可本地化,请执行以下操作。

消息目录是应用程序中使用的此类可本地化消息的翻译集合。它们通常存储在PO(便携对象)和MO(机器对象)文件中,其格式由GNU定义 gettext 工具和GNU translation project .

构建消息目录的一般过程如下所示:

  • 使用工具(如 xgettext )从代码库提取可本地化字符串,并将它们写入POT(PO模板)文件。

  • 复制特定区域设置的POT文件(例如,“en_US”),然后开始翻译消息

  • 使用工具,如 msgfmt 要将区域设置PO文件编译为二进制MO文件,请执行以下操作

  • 稍后,当代码更改需要更新翻译时,您可以重新生成POT文件并将更改合并到各种特定于区域设置的PO文件中,例如使用 msgmerge

python提供 gettext 模块作为标准库的一部分,使应用程序能够使用适当生成的MO文件。

AS gettext 为翻译应用程序消息提供了坚实且得到良好支持的基础,但Babel并没有重新发明轮子,而是重用了这个基础设施,并使为Python应用程序构建消息目录变得更容易。

消息提取

Babel提供的功能类似于 xgettext 程序,只是内置了从Python源文件中提取,而可以使用简单的扩展机制添加对其他文件格式的支持。

不像 xgettext ,它通常为每个文件调用一次,所以在Babel中用于消息提取的例程对目录进行操作。而每个文件的方法 xgettext 类很好地处理项目。 Makefile ,Python项目很少使用 make 因此,需要一种不同的机制来从由许多Python项目组成的异构源文件集合中提取消息。

当邮件提取基于目录而不是单个文件时,需要有一种方法来配置应以何种方式处理哪些文件。例如,虽然许多项目可能包含 .html 文件,其中一些文件可能是不包含可本地化消息的静电Html文件,而其他文件可能是 Jinja2 模板,还有其他模板可能包含 Genshi 标记模板。有些项目甚至可能混合使用不同模板语言的HTML文件(不管是什么原因)。因此,从源文件中提取消息的方式不仅取决于文件扩展名,而且需要以精确的方式进行控制。

Babel接受一个配置文件来指定文件到提取方法的这种映射,如下所述。

前端

Babel提供了两个不同的前端来访问其使用消息目录的功能:

您选择哪一个取决于您项目的性质。对于大多数现代Python项目,distutils/setuptools集成可能更方便。

提取方式映射和配置

提取方法到Babel中的文件的映射是通过配置文件完成的。此文件将扩展全局模式映射到提取方法的名称,还可以为每个模式设置各种选项(哪些选项可用取决于特定的提取方法)。

例如,以下配置添加了从根式标记模板和文本模板中提取消息:

# Extraction from Python source files

[python: **.py]

# Extraction from Genshi HTML and text templates

[genshi: **/templates/**.html]
ignore_tags = script,style
include_attrs = alt title summary

[genshi: **/templates/**.txt]
template_class = genshi.template:TextTemplate
encoding = ISO-8819-15

# Extraction from JavaScript files

[javascript: **.js]
extract_messages = $._, jQuery._

配置文件语法基于中常见的格式 .INI Windows系统上的文件,并且受 ConfigParser Python标准库中的模块。节名称(方括号括起来的字符串)指定提取方法的名称和扩展全局模式,以指定应使用此提取方法的文件,并用冒号分隔。部分中的选项将传递给提取方法。可用的选项取决于使用的提取方法。

此配置中使用的扩展全局模式类似于大多数shell提供的全局模式。单个星号 (* )是任意数量字符的通配符(路径名组件分隔符“/”除外),而问号 (? )仅匹配单个字符。此外,后续的两个星号字符 (** )可用于使通配符与任何目录级别匹配,因此模式 **.txt 匹配扩展名为的任何文件 .txt 在任何目录中。

#; 字符会被忽略,并可用于注释。空行也会被忽略。

备注

如果您正在使用BA贝尔提供的命令执行消息提取,以便集成到 setup.py 脚本,您还可以以不同的方式提供此配置,即作为关键字参数提供给 setup() 功能。见 总代理商/安装工具集成 更多信息。

默认提取方法

巴别塔自带了几个内置的提取器: python (它从Python源文件中提取消息), javascriptignore (它不提取任何内容)。

这个 python 默认情况下,提取器映射到全局模式 **.py ,这意味着它将应用于所有具有 .py 任何目录中的扩展名。如果您指定自己的映射配置,此缺省映射将被丢弃,因此您需要显式地将其添加到您的映射中(如上面的示例所示)。

参考提取方法

为了能够使用简短的提取方法名称(如“genshi”),您需要 pkg_resources 已安装,并且实现该提取方法的软件包需要与其元数据一起安装( egg-info

如果由于某些原因无法做到这一点,您需要在映射配置的Extract部分中将短名称映射到完全限定的函数名称。例如:

# Some custom extraction method

[extractors]
custom = mypackage.module:extract_custom

[custom: **.ctm]
some_option = foo

请注意,内置提取方法 pythonignore 默认情况下可用,即使 pkg_resources 未安装。属性中显式定义它们。 [extractors] 部分。

文字提取方法

添加用于提取可本地化方法的新方法很容易。首先,您需要实现一个符合以下接口的函数:

def extract_xxx(fileobj, keywords, comment_tags, options):
    """Extract messages from XXX files.

    :param fileobj: the file-like object the messages should be extracted
                    from
    :param keywords: a list of keywords (i.e. function names) that should
                     be recognized as translation functions
    :param comment_tags: a list of translator tags to search for and
                         include in the results
    :param options: a dictionary of additional options (optional)
    :return: an iterator over ``(lineno, funcname, message, comments)``
             tuples
    :rtype: ``iterator``
    """

备注

此函数生成的元组中的任何字符串必须为 unicode 对象,或 str 使用纯ASCII字符的对象。这意味着,如果源包含使用其他编码的字符串,则对其进行解码是提取器实现的工作 unicode 物体。

接下来,您应该将该函数注册为入口点。这需要您的 setup.py 要使用的脚本 setuptools ,以及要与必要的元数据一起安装的软件包。如果已经解决了这一点,请将类似以下内容添加到您的 setup.py 脚本:

def setup(...

    entry_points = """
    [babel.extractors]
    xxx = your.package:extract_xxx
    """,

也就是说,将您的提取方法添加到入口点组 babel.extractors ,其中入口点的名称是人们将用来引用提取方法的名称,值是实现实际提取的模块和函数的名称(用冒号分隔)。

备注

如图所示 Referencing Extraction Methods ,声明入口点并不是严格的要求,因为用户仍然可以直接引用提取函数。但只要有可能,都应该声明入口点,以使配置更方便。

译者评论

首先,什么是评论标签。Comments标签是要在注释中搜索的文本摘录,仅在python前面的注释中搜索 gettext 呼叫,如以下示例所示:

# NOTE: This is a comment about `Foo Bar`
_('Foo Bar')

以上示例的注释标记为 NOTE: ,该标记的翻译器注释为 This is a comment about `Foo Bar '.

目录模板中的结果输出将类似于::

#. This is a comment about `Foo Bar`
#: main.py:2
msgid "Foo Bar"
msgstr ""

现在,你可能会问,我为什么需要这个?

考虑一下这个简单的例子;您有一个名为“Manual”的菜单项。你知道这是什么意思,但当翻译看到这一点时,他们会想知道你的意思是:

  1. 文档或帮助手册,或

  2. 需要人工操作吗?

这是最简单的情况,翻译注释(如“安装手册”)有助于澄清情况,并使翻译人员更有效率。

备注

能否提取译者注释取决于使用的提取方法。Babel提供的Python提取器确实实现了此功能,但其他功能可能不会实现。