在 Oracle Solaris 中进行应用程序国际化和本地化

退出打印视图

更新时间: 2014 年 7 月
 
 

gettext API

要进行本地化的文本消息必须与应用程序的源代码分隔开,并存储在单独的文件中。这些文件称为消息包消息目录可移植消息文件。每种编程语言都提供一组用于处理这些文件的工具。例如,编程语言(如 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 实用程序。


注 -  如果消息包装在 gettext 函数中,应根据当前语言环境进行翻译。这样,原始文本消息将用作消息目录的密钥。

如何生成 Shell 脚本的本地化消息对象

  1. /usr/gnu/bin 置于 PATH 环境变量之前,以使用 GNU 版本的 gettext 工具。
  2. 使用 xgettext 命令将 shell 脚本中的消息提取到消息文件模板中。
  3. 使用 msginit 命令创建特定于翻译语言的可移植消息 (.po) 文件。
  4. 翻译在 .po 文件中创建的消息。
  5. TEXTDOMAINDIR 环境变量指定的目录中创建 LC_MESSAGES 目录。
  6. 创建符号链接或者设置 LANGUAGE 变量。
  7. 创建消息对象 (.mo) 文件。
示例 2-7  生成 Shell 脚本的本地化消息对象

此例说明如何生成 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 脚本,您可通过以下步骤创建本地化消息对象:

  1. usr/gnu/bin 置于 PATH 环境变量之前,以使用 GNU 版本的 gettext 工具。

    $ PATH=/usr/gnu/bin:$PATH
  2. 使用 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 ""
  3. 使用 msginit 命令创建特定于翻译语言的可移植消息 (.po) 文件。例如,使用以下命令针对日语 ja_JP.UTF-8 语言环境创建 .po 文件:

    $ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages.po

    将创建一个名为 ja.po 的文件。

  4. 翻译 ja.po 文件中的消息。

  5. TEXTDOMAINDIR 环境变量指定的目录中创建 LC_MESSAGES 目录。

    $ mkdir -p lib/locale/ja/LC_MESSAGES
  6. 创建符号链接或者设置 LANGUAGE 变量。

    • 创建符号链接

      $ ln -s ja lib/locale/ja_JP.UTF-8
    • 设置 LANGUAGE 变量。

      $ LANGUAGE=ja_JP.UTF-8:ja
      $ export LANGUAGE
  7. 创建消息对象 (.mo) 文件。

    $ msgfmt -o lib/locale/ja/LC_MESSAGES/test_gettext_sh.mo ja.po

如何生成 C 程序的本地化文本消息

  1. /usr/gnu/bin 置于 PATH 环境变量之前。
  2. 使用 xgettext 命令将源代码中的消息提取到消息文件模板中。
  3. LC_TIME 语言环境类别创建另一个 .po 文件。
  4. 使用 msginit 命令创建特定于翻译语言的可移植消息 (.po) 文件。
  5. 翻译创建的 .po 文件。
  6. LOCALEDIR 变量指定的目录中创建 LC_MESSAGESLC_TIME 目录。
  7. 创建符号链接或者设置 LANGUAGE 变量。
  8. 创建消息对象 (.mo) 文件。
示例 2-8  生成 C 程序的本地化文本消息

此例说明如何生成 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 程序,您可通过以下步骤创建本地化消息对象:

  1. /usr/gnu/bin 置于 PATH 环境变量之前:

    $ PATH=/usr/gnu/bin:$PATH
  2. 使用 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 ""
  3. LC_TIME 语言环境类别创建另一个 .po 文件:

    $ xgettext -c"TRANSLATORS:" -k -k"T_" -L"C" -o messages_t.po test_gettext.c

    LC_TIME 语言环境类别创建 messages_t.po 文件。

  4. 使用 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.poja_t.po 文件。

  5. 翻译创建的 ja.poja_t.po 文件。

  6. LOCALEDIR 变量指定的目录中创建 LC_MESSAGESLC_TIME 目录。

    $ mkdir -p lib/locale/ja/LC_MESSAGES lib/locale/ja/LC_TIME
  7. 创建符号链接或者设置LANGUAGE 变量:

    • 创建符号链接。

      $ ln -s ja lib/locale/ja_JP.UTF-8
    • 设置 LANGUAGE 变量。

      $ LANGUAGE=ja_JP.UTF-8:ja
      $ export LANGUAGE
  8. 创建消息对象 (.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

路径具有多个组件:

/usr/lib/locale

消息对象文件的缺省路径谓语。例如,如果文本域发生冲突,则会通过调用 bindtextdomain() 函数来指定此路径。如果使用第三方软件,则 /usr/share/locale 目录中将提供消息对象文件。

locale

语言环境目录。

category

语言环境类别。

textdomain.mo

通过调用 textdomain() 函数指定的文本域。它是消息目录的唯一标识符和文件名。

请看以下示例:

/usr/lib/locale/it_IT.UTF-8/LC_MESSAGES/mymessages.mo

其中:

it_IT.UTF-8

语言环境目录。此消息对象包含意大利文的翻译内容,并将用于此语言环境以及任何作为此目录的符号链接的语言环境。

LC_MESSAGES

语言环境类别。


注 -  消息通常可归到 LC_MESSAGESLC_TIME 类别中。
mymessages

消息目录名称。

与 Oracle Solaris 和 GNU 兼容的 gettext 接口

Oracle Solaris gettext API 同时支持与 Oracle Solaris 和 GNU 兼容的消息目录文件。但某些 gettext API 专用于与 GNU 兼容的消息目录文件。与 Solaris 和 GNU 兼容的 gettext 接口如下所示:

gettext()

从消息目录中检索文本字符串

dgettext()

从特定域的消息目录中检索消息

textdomain()

设置和查询当前域

bindtextdomain()

绑定消息域的路径

dcgettext()

从特定域和类别的消息目录中检索消息

GNU gettext 接口

仅用于处理与 GNU 兼容的消息目录文件的 gettext API 如下所示:

ngettext()

从消息目录中检索文本字符串,并选择复数形式

dngettext()

从特定域的消息目录中检索文本字符串,并选择复数形式

bind_textdomain_codeset()

针对域指定 codeset 消息目录的输出

dcngettext()

从特定域和类别的消息目录中检索文本字符串,并选择复数形式

有关 GNU 文本消息处理的更多信息,请参见 GNU gettext reference(GNU gettext 参考)。

有关 gettext 函数的更多信息,请参见 msgfmt(1)、xgettext(1) 和 gettext(1) 手册页。

消息处理工具

gettext 提供函数和命令行工具以创建和处理消息对象文件。Oracle Solaris 消息对象的格式与 GNU gettext 消息对象的格式不同。Oracle Solaris 用于处理消息的命令行工具变体如下所示:

/usr/bin/gettext

从消息目录中检索文本字符串

/usr/bin/msgfmt

根据可移植消息文件创建消息对象

/usr/bin/xgettext

从 C 程序中检索对 gettext 字符串的调用

GNU 用于处理消息的命令行工具变体如下所示:

/usr/bin/ggettext

从消息目录中检索文本字符串

/usr/bin/gmsgfmt

根据消息文件创建消息对象

/usr/bin/gxgettext

检索 gettext 调用字符串

为了与 Oracle Solaris 工具进行区分,GNU 变体工具使用字母 g 作为前缀,并且是指向 /usr/gnu/bin 目录的符号链接。例如,/usr/bin/ggettext 是指向 /usr/gnu/bin/gettext 的符号链接。

GNU gettext 工具是 text/gnu-gettext 软件包的一部分,此软件包还包括用于处理消息目录的其他实用程序。


注 -  Python gettext 实现仅支持 GNU gettext 消息对象格式。因此,对于 Python 程序,您必须创建与 GNU 兼容的消息对象。

有关更多信息,请参见 msgcat(1)、msgcmp(1) 和 msgmerge(1) 手册页。