使用GNU gettext 来翻译软件¶
GNU gettext 是自由软件国际化最广泛使用的工具之一。它提供了简单但灵活的方式将软件本地化。它对复数具有巨大的支持,他剋有将进一步的文本添加到翻译的字符串中,并且由非常多的工具围绕它构建。当然,它在 Weblate 中具有巨大的支持(文件格式描述请参见 :ref:`get。
注解
如果打算在私有软件中使用它,那么请首先咨询许可,它可能不适合您。
GNU gettext 可以在大量语言中使用(C、Python、PHP、Ruby、JavaScript 以及更多),并且一些 UI 框架通常已经为它带有一些支持。标准使用是通过 gettext() 函数调用,这通常具有 _() 别名,使代码更简单且更容易阅读。
此外,它提供 pgettext() 调用而为翻译者提供另外的文本,以及提供 ngettext(),可以处理目标语言定义的附属类型。
作为广泛传播的工具,它具有很多封装,使其使用相当简单,你也许会想尝试其中之一,例如 intltool,而非下面描述的对 gettext 的手动调用。
工作流程概览¶
GNU gettext 使用几个文件来管理本地化工作:
PACKAGE.pot
包含从您的源代码中提取的字符串,典型地使用 xgettext 或一些高级封装,如 intltool。LANGUAGE.po
包含翻译为单一语言的字符串。一旦PACKAGE.pot
更新,那么必须由 msgmerge 来更新它。您可以使用 msginit 或在 Weblate 内新建新的语言文件。LANGUAGE.mo
包含LANGUAGE.po
的二进制表达,并且应用运行时使用。它典型地并不保持在版本控制之下,但在编译时使用 msgfmt 生成。在您想要使它处于版本控制中时,可以使用 生成 MO 文件 插件在 Weblate 中生成它。
GNU gettext 总体工作流程看起来像这样:
示例程序¶
使用 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 |
文件掩码 |
|
新翻译的译文模版 |
|
文件格式 |
选择 gettext PO file |
新语言 |
选择 :guilabel:`Create new language file`(新建新语言文件) |
就是这样,现在您已经准备号开始翻译您的软件了!
参见
你可以在 GitHub: <https://github.com/WeblateOrg/hello> 上的 Weblate Hello 项目中找到带有很多语言的 gettext 示例。