支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2

55.2. 针对程序员 #

55.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() 调用中提供的那样。

    GETTEXT_FILES

    包含可翻译字符串的文件列表,即那些用 gettext 或替代解决方案标记的文件。最终,这将包括程序的几乎所有源文件。如果此列表太长,您可以使第一个file成为 +,第二个单词是一个文件,每行包含一个文件名。

    GETTEXT_TRIGGERS

    为翻译人员生成消息目录的工具需要知道哪些函数调用包含可翻译的字符串。默认情况下,仅知道 gettext() 调用。如果您使用了 _ 或其他标识符,则需要在此处列出它们。如果可翻译的字符串不是第一个参数,则该项需要采用 func:2 的形式(对于第二个参数)。如果您有一个支持复数消息的函数,则该项应如下所示:func:1,2(标识单数和复数消息参数)。

  4. 添加一个文件 po/LINGUAS,其中将包含提供的翻译列表,最初为空。

构建系统将自动处理构建和安装消息目录。

55.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 或不为 1 时才重要,但是在其他语言中,可能会有许多不同的复数形式。翻译人员将两个英语形式视为一组,并有机会提供多个替代字符串,并根据 n 的运行时值选择适当的字符串。

    如果您需要复数化一个不直接发送到 errmsgerrdetail 报告的消息,则必须使用底层函数 ngettext。请参阅 gettext 文档。

  • 如果您想向翻译人员传达某些信息,例如关于消息如何与其他输出对齐,请在字符串出现之前加上以 translator 开头的注释,例如

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

    这些注释被复制到消息目录文件中,以便翻译人员可以看到它们。

提交更正

如果您在文档中发现任何不正确、与您使用特定功能的经验不符或需要进一步澄清的内容,请使用此表单报告文档问题。