这一节描述如何在PostgreSQL发布中的一个程序或库中实现本地语言支持。当前,这些知识只适用于 C 程序。
为一个程序增加 NLS 支持
将这里的代码插入到该程序的启动序列中:
#ifdef ENABLE_NLS
#include <locale.h>
#endif
...
#ifdef ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain("progname
", LOCALEDIR);
textdomain("progname
");
#endif
(程序名
实际上可以自由选择)。
不管在哪里找到一个可被翻译的消息,需要插入一个gettext()
调用,例如:
fprintf(stderr, "panic level %dn", lvl);
将被改成:
fprintf(stderr, gettext("panic level %dn"), lvl);
(如果 NLS 支持没有被配置,gettext
被定义为一个空操作)。
这容易增加很多混乱。一种常用的捷径是:
#define _(x) gettext(x)
如果该程序通过一个或几个函数(例如后端中的ereport()
)完成他的大部分通信,则有另一种可行的解决方案。那么你可以在所有输入字符串上都内部调用这个函数gettext
。
在程序源码的目录中增加一个文件nls.mk
。这个文件将被读作一个 makefile。其中要创建下列变量赋值:
CATALOG_NAME
程序名,如textdomain()
调用中所提供的。
AVAIL_LANGUAGES
提供的翻译列表 — 初始为空。
GETTEXT_FILES
包含可翻译字符串的文件列表,即那些被用gettext
或另一种替代方案标记的文件。最终,这将包括该程序近乎所有的源文件。如果这个列表太长你可以让第一个“file”变成一个+
并且第二个词变成一个包含那些文件名的文件,第二个词指向的文件中每个文件名一行。
GETTEXT_TRIGGERS
为翻译者产生在其上工作的消息目录的工具需要知道,哪些函数调用包含可翻译的字符串。默认情况下,只有gettext()
调用是已知的。如果你使用_
或其他标识符,你需要在这里列出它们。如果可翻译的字符串不是第一个参数,该条目需要是形式func:2
(用于第二个参数)。如果你有一个支持复数消息的函数,该条目应该看起来像func:1,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
是否唯一有关系,但是在其他语言中可以有多种不同的复数形式。翻译者将两种英语形式看成一组并且有机会提供多个替补字符串,基于n
的运行时值会选择其中合适的那一个。
如果你需要复数化一个不直接进入到errmsg
或errdetail
报告的消息,你必须使用底层函数ngettext
。见 gettext 文档。
如果你想要与翻译者沟通(例如关于一个消息如何在其他输出上对齐),在该字符串出现的地方之前放上一个以translator
开始的注释,例如:
这些注释被复制到消息目录文件中,这样翻译者可以看到它们。
inner/aroundinner/aroundVim 8.2 快速参考备忘单的有用集合,可帮助您更快地学习 vim 编辑器。 开始运动图▼/▶ Cursor ▽/▷ T...
gcfg组件采用了接口化设计,以实现高扩展性。通过接口化设计的方式,使用者可以自定义对接的配置获取方式,例如etcd,z...
使用方式gf-vgfversion用以查看当前gf命令行工具编译时的版本信息。使用示例$ gf versionGoFrame CLI Tool v2.0.0, ...
一、数据模型数据模型又叫做实体模型,主要是来自于底层持久化数据库的数据结构,例如:MySQL、Redis、MongoDB、K...
glog对日志分析工具非常友好,支持输出JSON格式的日志内容,以便于后期对日志内容进行解析分析。想要支持JSON数据格...
以下为Golang标准库的一些基础语法和基础函数,GoFrame框架对部分基础函数做了必要的改进。变量可以使用符号|在函数间传递...
模型创建ModelModel方法用于创建基于数据表的Model对象。常见的,也可以使用g对象管理模块中的Model方法在默认...
可观测性是很重要的,目前已经有比较不错的OpenTelemetry标准,各个第三方组件以及厂商都按照这套标准库来暴露和对接观测数...