要进行本地化的文本消息必须与应用程序的源代码分隔开,并存储在单独的文件中。这些文件称为消息包、消息目录或可移植消息文件。每种编程语言都提供一组用于处理这些文件的工具。例如,编程语言(如 C、Python 和 Perl)中提供了用于转换消息的 gettext 函数。
您可以使用 gettext 实用程序创建可移植消息文件。这些文件都是纯文本文件,其文件扩展名为 .po。将可移植消息文件发送给翻译者进行翻译,翻译者会用翻译文本更新此文件。翻译之后,.po 文件将包含消息 ID 和对应的翻译文本。例如:
$ cat cs.po . . #: code.c:37 #,c-format msgid "My hovercraft is full of eels.\n" msgstr "Moje vznášedlo je plné úhořů.\n"
不过,您可通过将可移植对象文件转换为消息对象文件来提高系统的性能。消息对象文件的扩展名为.mo。要将可移植对象文件转换为消息对象文件,可使用 msgfmt 实用程序。
此例说明如何生成 shell 脚本的本地化消息对象。假定您具有以下 shell 脚本并调用了 gettext 函数。
#!/usr/bin/bash # # set TEXTDOMAIN and TEXTDOMAINDIR as per the gettext(1) manual page TEXTDOMAIN=test_gettext_sh export TEXTDOMAIN TEXTDOMAINDIR=/home/xxxxx/lib/locale export TEXTDOMAINDIR PATH=/usr/gnu/bin:/usr/bin export PATH # source gettext.sh for using eval_gettext and eval_ngettext . gettext.sh f="filename.dat" # Use eval_gettext or eval_ngettext if it refers to shell variables # TRANSLATORS: $f is replaced with a file name eval_gettext "\$f not found"; echo gettext "file not found"; echo echo "`eval_gettext "\\\$f not found"`" echo "`gettext "file not found"`"
对于此 shell 脚本,您可通过以下步骤创建本地化消息对象:
将 usr/gnu/bin 置于 PATH 环境变量之前,以使用 GNU 版本的 gettext 工具。
$ PATH=/usr/gnu/bin:$PATH
使用 xgettext 命令将 shell 脚本中的消息提取到消息文件模板中。
$ xgettext -c"TRANSLATORS:" -L"Shell" test_gettext.sh
将创建一个名为 messages.po 的文件,其中包含来自此 shell 脚本的头信息和消息字符串。此文件还包括对翻译者的解释性注释。以下示例显示的是 messages.po 文件的一段摘录:
#. TRANSLATORS: $f is replaced with a file name #: test_gettext.sh:18 test_gettext.sh:21 #, sh-format msgid "$f not found" msgstr "" #: test_gettext.sh:19 test_gettext.sh:22 msgid "file not found" msgstr ""
使用 msginit 命令创建特定于翻译语言的可移植消息 (.po) 文件。例如,使用以下命令针对日语 ja_JP.UTF-8 语言环境创建 .po 文件:
$ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages.po
将创建一个名为 ja.po 的文件。
翻译 ja.po 文件中的消息。
在 TEXTDOMAINDIR 环境变量指定的目录中创建 LC_MESSAGES 目录。
$ mkdir -p lib/locale/ja/LC_MESSAGES
创建符号链接或者设置 LANGUAGE 变量。
创建符号链接
$ ln -s ja lib/locale/ja_JP.UTF-8
设置 LANGUAGE 变量。
$ LANGUAGE=ja_JP.UTF-8:ja $ export LANGUAGE
创建消息对象 (.mo) 文件。
$ msgfmt -o lib/locale/ja/LC_MESSAGES/test_gettext_sh.mo ja.po
此例说明如何生成 C 程序的本地化消息对象。假定您具有以下 C 程序并调用了 gettext 函数。
#include <stdio.h> #include <sys/types.h> #include <libintl.h> #include <locale.h> #include <time.h> /* * _() is used for the strings to extract messages. * N_() is used for the string array message to extract messages. * T_() is used for the strings to extract messages with working on LC_TIME */ #define _(String) gettext (String) #define gettext_noop(String) String #define N_(String) gettext_noop (String) #define T_(String) gettext_noop (String) #define LOCALEDIR "/home/xxxxx/lib/locale" #define PACKAGE "test_gettext" static const char *msg[] = { N_("The first message"), N_("The second message"), }; int main(int ac, char **av) { char *file = "test.dat"; int line = 40; int column = 10; time_t tloc; char time_buf[BUFSIZ]; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); /* * By default, the characters are converted to current locale's encoding. * If this is not desired, call bind_textdomain_codeset(). For example, * if you want "UTF-8" encoding, specify "UTF-8" in the second argument. * * bind_textdomain_codeset("test_gettext", "UTF-8"); */ printf(_("This is a test\n")); printf("%s\n", _(msg[0])); printf("%s\n", _(msg[1])); /* TRANSLATORS: First %d is replaced by a line number. Second %d is replaced by a column number. %s is replaced by a file name. */ printf(_("ERROR: invalid input at line %1$d, %2$d in %3$s\n"), line, column, file); /* * strftime() works with LC_TIME not LC_MESSAGES so to get properly * formatted time messages we have to call dcgettext() with LC_TIME category. */ (void) time(&tloc); (void) strftime(time_buf, sizeof (time_buf), /* TRANSLATORS: This is time format used with strftime(). Please modify time format to fit your locale by using date '+%a %b %e %H:%M:%S' */ dcgettext(NULL, T_("%a %b %e %H:%M:%S"), LC_TIME), localtime(&tloc)); printf("%s\n", time_buf); return(0); }
对于此 C 程序,您可通过以下步骤创建本地化消息对象:
将 /usr/gnu/bin 置于 PATH 环境变量之前:
$ PATH=/usr/gnu/bin:$PATH
使用 xgettext 命令将源代码中的消息提取到消息文件模板中:
$ xgettext -c"TRANSLATORS:" -k -k"_" -k"N_" -L"C" test_gettext.c
为 LC_MESSAGES 语言环境类别创建 messages.po 文件。此文件包含头信息和消息字符串,以及对翻译者的解释性注释。以下示例显示的是 messages.po 文件的一段摘录:
#: test_gettext.c:21 msgid "The first message" msgstr "" #: test_gettext.c:22 msgid "The second message" msgstr "" #: test_gettext.c:43 #, c-format msgid "This is a test\n" msgstr "" #. TRANSLATORS: #. First %d is replaced by a line number. #. Second %d is replaced by a column number. #. %s is replaced by a file name. #: test_gettext.c:51 #, c-format msgid "ERROR: invalid input at line %1$d, %2$d in %3$s\n" msgstr ""
为 LC_TIME 语言环境类别创建另一个 .po 文件:
$ xgettext -c"TRANSLATORS:" -k -k"T_" -L"C" -o messages_t.po test_gettext.c
为 LC_TIME 语言环境类别创建 messages_t.po 文件。
使用 msginit 命令创建特定于翻译语言的可移植消息 (.po) 文件。
例如,使用以下命令针对日语 ja_JP.UTF-8 语言环境创建可移植文件消息:
$ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages.po $ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages_t.po --output-file=ja_t.po
将创建 ja.po 和 ja_t.po 文件。
翻译创建的 ja.po 和 ja_t.po 文件。
在 LOCALEDIR 变量指定的目录中创建 LC_MESSAGES 和 LC_TIME 目录。
$ mkdir -p lib/locale/ja/LC_MESSAGES lib/locale/ja/LC_TIME
创建符号链接或者设置LANGUAGE 变量:
创建符号链接。
$ ln -s ja lib/locale/ja_JP.UTF-8
设置 LANGUAGE 变量。
$ LANGUAGE=ja_JP.UTF-8:ja $ export LANGUAGE
创建消息对象 (.mo) 文件。
$ msgfmt -o lib/locale/ja/LC_MESSAGES/test_gettext.mo ja.po $ msgfmt -o lib/locale/ja/LC_TIME/test_gettext.mo ja_t.po
使用以下格式创建消息对象文件:
/usr/lib/locale/locale/category/textdomain.mo
路径具有多个组件:
消息对象文件的缺省路径谓语。例如,如果文本域发生冲突,则会通过调用 bindtextdomain() 函数来指定此路径。如果使用第三方软件,则 /usr/share/locale 目录中将提供消息对象文件。
语言环境目录。
语言环境类别。
通过调用 textdomain() 函数指定的文本域。它是消息目录的唯一标识符和文件名。
请看以下示例:
/usr/lib/locale/it_IT.UTF-8/LC_MESSAGES/mymessages.mo
其中:
语言环境目录。此消息对象包含意大利文的翻译内容,并将用于此语言环境以及任何作为此目录的符号链接的语言环境。
语言环境类别。
消息目录名称。
Oracle Solaris gettext API 同时支持与 Oracle Solaris 和 GNU 兼容的消息目录文件。但某些 gettext API 专用于与 GNU 兼容的消息目录文件。与 Solaris 和 GNU 兼容的 gettext 接口如下所示:
从消息目录中检索文本字符串
从特定域的消息目录中检索消息
设置和查询当前域
绑定消息域的路径
从特定域和类别的消息目录中检索消息
仅用于处理与 GNU 兼容的消息目录文件的 gettext API 如下所示:
从消息目录中检索文本字符串,并选择复数形式
从特定域的消息目录中检索文本字符串,并选择复数形式
针对域指定 codeset 消息目录的输出
从特定域和类别的消息目录中检索文本字符串,并选择复数形式
有关 GNU 文本消息处理的更多信息,请参见 GNU gettext reference(GNU gettext 参考)。
有关 gettext 函数的更多信息,请参见 msgfmt(1)、xgettext(1) 和 gettext(1) 手册页。
gettext 提供函数和命令行工具以创建和处理消息对象文件。Oracle Solaris 消息对象的格式与 GNU gettext 消息对象的格式不同。Oracle Solaris 用于处理消息的命令行工具变体如下所示:
从消息目录中检索文本字符串
根据可移植消息文件创建消息对象
从 C 程序中检索对 gettext 字符串的调用
GNU 用于处理消息的命令行工具变体如下所示:
从消息目录中检索文本字符串
根据消息文件创建消息对象
检索 gettext 调用字符串
为了与 Oracle Solaris 工具进行区分,GNU 变体工具使用字母 g 作为前缀,并且是指向 /usr/gnu/bin 目录的符号链接。例如,/usr/bin/ggettext 是指向 /usr/gnu/bin/gettext 的符号链接。
GNU gettext 工具是 text/gnu-gettext 软件包的一部分,此软件包还包括用于处理消息目录的其他实用程序。
有关更多信息,请参见 msgcat(1)、msgcmp(1) 和 msgmerge(1) 手册页。