9.3 9.4 9.5 9.6 10 11 12 13 14 15 Current(16) 17
问题报告 纠错本页面

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
    

    程序名实际上可以自由选择)。

  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或其他替代解决方案的文件。 最终,这将包括程序的几乎所有源文件。如果此列表过长, 您可以将第一个文件设为+, 第二个单词设为一个文件,该文件每行包含一个文件名。

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

    如果你需要复数化一个不直接进入到errmsgerrdetail报告的消息,你必须使用底层函数ngettext。见 gettext 文档。

  • 如果您想与翻译人员交流某些内容,例如关于消息如何与其他输出对齐,在该字符串出现的地方之前放上一个以translator开始的注释,例如:

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

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