Skip to content

57.2. 面向程序员#

57.2.1. 机制
57.2.2. 消息编写指南

57.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,其中将包含所提供的翻译列表(最初为空)。

构建系统将自动负责构建和安装消息目录。

57.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. */
    

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