使用 GNU Gettext 的翻译软件

GNU Gettext 是自由软件国际化最广泛使用的工具之一。它提供了简单但灵活的方式将软件本地化。它对复数具有巨大的支持,他剋有将进一步的文本添加到翻译的字符串中,并且由非常多的工具围绕它构建。当然,它在 Weblate 中具有巨大的支持(文件格式描述请参见 GNU gettext )。

注解

如果打算在私有软件中使用它,那么请首先咨询许可,它可能不适合您。

GNU Gettext 可以在大量语言中使用(C、Python、PHP、Ruby、JavaScript 以及更多),并且一些 UI 框架通常已经为它带有一些支持。标准使用是通过 gettext() 函数调用,这通常具有 _() 别名,使代码更简单且更容易阅读。

此外,它提供 pgettext() 调用而为翻译者提供另外的文本,以及提供 ngettext(),可以处理目标语言定义的附属类型。

作为广泛传播的工具,它具有很多封装,使其使用真正简单,除了下面描述的手动调用 Gettext,您会想要尝试其中之一,例如 intltool

工作流程概览

GNU Gettext 使用几个文件来管理本地化:

  • PACKAGE.pot 包含从您的源代码中提取的字符串,典型地使用 xgettext 或一些高级封装,如 intltool

  • LANGUAGE.po 包含翻译为单一语言的字符串。一旦 PACKAGE.pot 更新,那么必须由 msgmerge 来更新它。您可以使用 msginit 或在 Weblate 内新建新的语言文件。

  • LANGUAGE.mo 包含 LANGUAGE.po 的二进制表达,并且应用运行时使用。它典型地并不保持在版本控制之下,但在编译时使用 msgfmt 生成。在您想要使它处于版本控制中时,可以使用 生成 MO 文件 插件在 Weblate 中生成它。

整个 GNU Gettext 工作流程看起来像这样:

digraph translations { graph [fontname = "sans-serif", fontsize=10]; node [fontname = "sans-serif", fontsize=10, shape=note, margin=0.1, height=0]; edge [fontname = "monospace", fontsize=10]; "Source code" -> "PACKAGE.pot" [label=" xgettext "]; "PACKAGE.pot" -> "LANGUAGE.po" [label=" msgmerge "]; "LANGUAGE.po" -> "LANGUAGE.mo" [label=" msgfmt "]; }

示例程序

使用 Gettext 的 C 语言简单程序看起来会像后面这样:

#include <libintl.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int count = 1;
    setlocale(LC_ALL, "");
    bindtextdomain("hello", "/usr/share/locale");
    textdomain("hello");
    printf(
        ngettext(
            "Orangutan has %d banana.\n",
            "Orangutan has %d bananas.\n",
            count
        ),
        count
    );
    printf("%s\n", gettext("Thank you for using Weblate."));
    exit(0);
}

提取可翻译的字符串

一旦您具有了使用 gettext 调用的代码,您可以使用 xgettext 从中提取消息,并将它们存储在 .pot 中:

$ xgettext main.c -o po/hello.pot

注解

有另外的程序从代码中提取字符串,例如 pybabel

这新建了模板文件,您可以用它来开始新的翻译(使用`msginit`_),或在代码更改后更新现有的翻译(为此您将使用 msgmerge)。结果文件是简单的结构化文本文件:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-23 11:02+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"

#: main.c:14
#, c-format
msgid "Orangutan has %d banana.\n"
msgid_plural "Orangutan has %d bananas.\n"
msgstr[0] ""
msgstr[1] ""

#: main.c:20
msgid "Thank you for using Weblate."
msgstr ""

每个 msgid 行定义了要翻译的字符串,在开始的特殊空字符串是包含关于翻译的元数据的文件标头。

开始新的翻译

在模板就位后,我们就可以开始我们的第一个翻译了:

$ msginit -i po/hello.pot -l cs --no-translator -o po/cs.po
Created cs.po.

刚刚新建的 cs.po 已经有一些信息填充进去了。最重要的是它获得了所选择的语言的适当复数形式定义,并且您可以看到几种复数已经根据它更改了:

# Czech translations for PACKAGE package.
# Copyright (C) 2015 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Automatically generated, 2015.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-23 11:02+0200\n"
"PO-Revision-Date: 2015-10-23 11:02+0200\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ASCII\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"

#: main.c:14
#, c-format
msgid "Orangutan has %d banana.\n"
msgid_plural "Orangutan has %d bananas.\n"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""

#: main.c:20
msgid "Thank you for using Weblate."
msgstr ""

这个文件被编译为优化的二进制形式,.mo 文件,由 GNU Gettext 函数在运行时使用。

更新字符串

一旦在您的程序中添加了更多的字符串或更改了一些字符串,您再次执行 xgettext ,生成模板文件:

$ xgettext main.c -o po/hello.pot

然后您可以更新各自的翻译文件来匹配新建的模板(这包括重新排序字符串,赖于新的模板匹配):

$ msgmerge --previous --update po/cs.po po/hello.pot

导入到 Weblate

为了将这样的翻译导入 Weblate,当新建组件时,所有需要您定义的是后面的字段(字段的具体描述请参见 组件配置):

字段

源代码库

您的项目的版本控制系统(VCS)仓库的 URL

文件掩码

po/*.po

新翻译的译文模版

po/hello.pot

文件格式

选择 Gettext PO file

新语言

选择 :guilabel:`Create new language file`(新建新语言文件)

就是这样,现在您已经准备号开始翻译您的软件了!

参见

您可以在 GitHub: <https://github.com/WeblateOrg/hello> 上的 Weblate Hello 项目中找到带有很多语言的 Gettext 示例。