本节介绍如何在 PostgreSQL 发行版的一部分程序或库中实现本地语言支持。目前,它仅适用于 C 程序。
为程序添加 NLS 支持
将此代码插入程序的启动序列中
#ifdef ENABLE_NLS
#include <locale.h>
#endif
...
#ifdef ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain("progname", LOCALEDIR);
textdomain("progname");
#endif
(progname 实际上可以自由选择。)
在找到任何可能需要翻译的消息的地方,都需要插入对 gettext() 的调用。例如:
fprintf(stderr, "panic level %d\n", lvl);
将改为
fprintf(stderr, gettext("panic level %d\n"), lvl);
(如果未配置 NLS 支持,则 gettext 定义为无操作。)
这会增加很多杂乱的代码。一个常见的捷径是使用
#define _(x) gettext(x)
如果程序通过一个或几个函数进行大量通信,例如后端中的 ereport(),则另一种解决方案是可行的。然后,您可以在内部对所有输入字符串调用 gettext。
在包含程序源代码的目录中添加一个名为 nls.mk 的文件。此文件将作为 makefile 读取。此处需要进行以下变量赋值:
CATALOG_NAME程序名,如 textdomain() 调用中所提供。
GETTEXT_FILES包含可翻译字符串的文件列表,即那些用 gettext 或其他解决方案标记的文件。最终,这将包括几乎所有程序源代码文件。如果此列表太长,您可以将第一个“文件”设为 +,第二个词是一个包含每行一个文件名的文件。
GETTEXT_TRIGGERS为翻译人员生成消息目录的工具需要知道哪些函数调用包含可翻译的字符串。默认情况下,只知道 gettext() 调用。如果您使用了 _ 或其他标识符,则需要在此处列出它们。如果可翻译字符串不是第一个参数,则该项应采用 func:2 的形式(表示第二个参数)。如果您有一个支持复数形式消息的函数,该项应为 func:1,2(标识单数和复数消息参数)。
添加一个名为 po/LINGUAS 的文件,其中包含提供的翻译列表 — 最初为空。
构建系统将自动负责构建和安装消息目录。
以下是编写易于翻译的消息的一些指南。
不要在运行时构建句子,例如:
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 才重要,但在其他语言中可能有许多不同的复数形式。翻译者将两个英语形式视为一个组,并有机会提供多个替换字符串,其中一个将根据 n 的运行时值进行选择。
如果您需要为不直接发送到 errmsg 或 errdetail 报告的消息添加复数形式,您必须使用底层函数 ngettext。请参阅 gettext 文档。
如果您想与翻译人员沟通某些信息,例如关于消息如何与其他输出对齐,请在字符串出现之前加上一个以 translator 开头的注释,例如:
/* translator: This message is not what it seems to be. */
这些注释会被复制到消息目录文件中,以便翻译人员可以看到它们。