使用GNU gettext 來翻譯軟件

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

備註

如果打算在私有軟件中使用它,那麼請首先諮詢許可,它可能不適合您。

GNU gettext 可以在大量語言中使用(C、Python、PHP、Ruby、JavaScript 以及更多),並且一些 UI 框架通常已經為它帶有一些支持。標準使用是通過 gettext() 函數調用,這通常具有 _() 別名,使代碼更簡單且更容易閱讀。

此外,它提供 pgettext() 調用而為翻譯者提供另外的文本,以及提供 ngettext(),可以處理目標語言定義的附屬類型。

作為廣泛傳播的工具,它具有很多封裝,使其使用相當簡單,你也許會想嘗試其中之一,例如 intltool,而非下面描述的對 gettext 的手動調用。

Workflow overview

GNU gettext 使用幾個文件來管理本地化工作:

  • PACKAGE.pot 包含從您的源代碼中提取的字符串,典型地使用 xgettext 或一些高級封裝,如 intltool

  • LANGUAGE.po 包含翻譯為單一語言的字符串。一旦 PACKAGE.pot 更新,那麼必須由 msgmerge 來更新它。您可以使用 msginit 或在 Weblate 內新建新的語言文件。

  • LANGUAGE.mo contains binary representation of LANGUAGE.po and is used at application runtime. Typically it is not kept under version control, but generated at compilation time using msgfmt. In case you want to have it in the version control, you can generate it in Weblate using 生成 MO 檔 add-on.

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 "]; }

也參考

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 <https://www.gnu.org/software/gettext/manual/gettext.html# index-files_002c-_002epot>`_ 中:

$ 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,當新建組件時,所有需要您定義的是後面的字段(字段的具體描述請參見 組件配置):

Field

Value

源始碼儲存庫

您的項目的版本控制系統(VCS)倉庫的 URL

文件掩碼

po/*.po

新翻譯的模板

po/hello.pot

檔案格式

Choose gettext PO file

新增語言

選擇 :guilabel:`Create new language file`(新建新語言文件)

就是這樣,現在您已經準備號開始翻譯您的軟件了!

也參考

你可以在 GitHub: <https://github.com/WeblateOrg/hello> 上的 Weblate Hello 項目中找到帶有很多語言的 gettext 示例。