寄语程序员

PostgreSQL 9.4.4 中文手册
上一页 | 上一级 | 章 51. 本地语言支持 | 下一页

# 51.2. 寄语程序员

## 51.2.1. 机理

本节描述如何在属于 PostgreSQL 版本的程序或者库里面支持本地语言。 目前它只适用于 C 语言。

向程序中增加 NLS 支持

1. 把下面的代码插入到程序的开头：

       #ifdef ENABLE_NLS
       #include <locale.h>
       #endif

       ...

       #ifdef ENABLE_NLS
       setlocale(LC_ALL, "");
       bindtextdomain("progname", LOCALEDIR);
       textdomain("progname");
       #endif

   （这里的 `progname` 实际上可以自由选择。）

2. 如果发现一条需要翻译的消息，那么就需要插入一个对 `gettext()` 的调用。比如

       fprintf(stderr, "panic level %d\n", lvl);

   会改成

       fprintf(stderr, gettext("panic level %d\n"), lvl);

   （如果没有配置 NLS ，那么 `gettext` 会定义成空操作。）

   这么干会出现一堆东西。一种常用的缩写是

       #define _(x) gettext(x)

   如果程序只通过一个或者少数几个函数做大部分的消息传递，比如后端里的 `ereport()` ， 那么也可以用另外一个方法。在这些函数的内部对所有输入字符串调用 `gettext` 。

3. 在程序源代码所在的目录里加一个文件 `nls.mk` 。 这个文件将被当做 makefile 读取。在这里需要做下面一些变量的赋值：

   `CATALOG_NAME`

     那些在 `textdomain()` 调用里提供的程序的名字。

   `AVAIL_LANGUAGES`

     提供的翻译的语言列表，开始的时候是空的。

   `GETTEXT_FILES`

     一列包含可翻译字符串的文件，也就是那些用 `gettext` 或者其它相应手段标记了的文件。 最终，这里会包括几乎所有的程序源文件。如果列表太长，你可以把第一个"文件"写成一个 `+` 和第二个词组成，第二个词是一个文件，在这个文件里每行包含一个文件名。

   `GETTEXT_TRIGGERS`

     生成给翻译者使用的消息表的工具，以便知道哪些函数调用包含可翻译字符串。 缺省时只知道 `gettext()` 调用。 如果你使用了 `_` 或其它标识符，那么你需要把它们列在这里。 如果可翻译字符串不是第一个参数，那么该项需要是这样的形式：`func:2` (用于第二给参数)。 如果函数支持多个消息，那么该项看起来就像这样:`func:1,2`(识别单个和多个消息参数)。

编译系统将自动制作和安装消息表。

## 51.2.2. 消息书写指导

这里是一些关于如何书写易于翻译的消息的指导：

- 不要在运行时构造语句，比如像

      printf("Files were %s.\n", flag ? "copied" : "removed");

  语句里这样的单词顺序会让其它语言很难翻译。 而且，即使你记得在每个片断上调用 `gettext()`，这些片断也不一定能很好地独立翻译。 最好复制一些代码，好让每条消息可以当作有机的整体进行翻译。 只有数字，文件名和类似的运行时变量才应该在运行时插入消息文本。

- 出于类似的原因，下面的东西不能用：

      printf("copied %d file%s", n, n!=1 ? "s" : "");

  因为它假设了如何形成复数形。如果你看到这样的东西，你可以用下面方法解决

      if (n==1)
          printf("copied 1 file");
      else
          printf("copied %d files", n):

  不过还是有让人失望的时候，有些语言在某些特殊规则上有超过两种形式。 通常最好是通过消息的设计避免这些东西，比如你可以这样写：

      printf("number of copied files: %d", n);

  如果你真的要构造一条恰当的复数形消息，也是支持的，但形式上有一点笨拙。 比如当通过`ereport()`生成一条概要或者详细消息时，你可以这样写：

      errmsg_plural("copied %d file",
                    "copied %d files",
                    n,
                    n)

  第一个参数是对应英文单数形的格式字符串，第二个参数是对应英文复数形的格式字符串，第三个参数是决定是否是复数形的一个整数值。 随后的参数和通常一样对应与格式字符串中的参数值。（通常，控制复数形的值也是格式字符串中的其中一个参数。） 英语中只关心`n`是不是1，但其它语言中可能有多个复数形。 针对英文中作为一组的2个格式字符串，翻译者能够为根据`n`的运行值选中的恰当的那个提供多个替代字符串。

  如果你需要一条不直接调用`errmsg`或`errdetail`的复数形消息， 必须使用下层的`ngettext`函数。具体参考gettext的文档。

- 如果你想和翻译者进行交流，比如说一条消息是如何与其它输出对齐的，那么在该字符串出现之前，放上一条以 `translator` 开头的注释，比如

      /* translator: This message is not what it seems to be. */

  这些注释都拷贝到消息表文件里，这样翻译者就可以看见它们了。

上一页 | 起始页 | 下一页
寄语翻译家 | 上一级 | 书写一个过程语言处理器