【发布时间】:2016-04-26 07:17:15
【问题描述】:
对于嵌入式软件项目,我正在添加对翻译的支持,并且由于我们运行的是嵌入式 Linux,因此我选择使用 libc gettext()。我们没有安装任何语言环境定义,所以我只尝试将LC_MESSAGES 语言环境设置为我想要的语言环境:
setlocale(LC_MESSAGES, "fake");
(我使用名称 fake 和 fake.mo 文件进行伪翻译,然后再进行正确的翻译)。
这在静态链接时工作正常,它返回一个语言环境句柄,bindtextdomain() 和朋友都工作正常,我从中得到我的“翻译”字符串:
setlocale() returned "fake"
current textdomain is "ewe"
current base directory is "/opt/btech/probe/share/locale/WA"
current LC_MESSAGES locale is "fake"
gettext("Error") ==> "Ḗřřǿř"
现在,当我动态编译它时,它不起作用。既不在目标设备上,也不在我的 PC 上本地(文件安装方式相同)。 setlocale() 调用失败,返回 NULL 指针并将 errno 设置为 ENOENT(找不到文件)。在setlocale() 处,我还没有将bindtextdomain() 指向我的文件所在的位置,但是切换调用并没有帮助。
我做错了吗,我上面的工作示例是否错误并且不应该真正起作用?我是否需要为我调用 setlocale() 的任何内容(甚至是 LC_MESSAGES)定义语言环境?
这是测试二进制文件的来源:
#include <libintl.h>
#include <locale.h>
#include <stdio.h>
int main()
{
const char *l = setlocale(LC_MESSAGES, "fake");
printf("setlocale() returned \"%s\"\n", l);
bind_textdomain_codeset("ewe", "UTF-8");
bindtextdomain("ewe", "/opt/btech/probe/share/locale/WA");
textdomain("ewe");
printf("current textdomain is \"%s\"\n", textdomain(NULL));
printf("current base directory is \"%s\"\n", bindtextdomain(textdomain(NULL), NULL));
printf("current LC_MESSAGES locale is \"%s\"\n", setlocale(LC_MESSAGES, NULL));
printf("gettext(\"Error\") ==> \"%s\"\n", gettext("Error"));
return 0;
}
这是动态编译时的输出(对于目标或主机):
setlocale() returned "(null)"
current textdomain is "ewe"
current base directory is "/opt/btech/probe/share/locale/WA"
current LC_MESSAGES locale is "C"
gettext("Error") ==> "Error"
编辑:在我的主机(x64 Linux)上将测试二进制文件编译为静态也可以使其工作,因此静态编译有一些特别之处。
附加问题:我可以强制 gettext 直接加载特定的 mo 文件吗?基本上我想替换bindtextdomain(),它接受一个文件名参数。
编辑 2:所以,我最终发现 this post 说我可以让 gettext() 加载任何翻译,只要我有一个有效的 setlocale() 首先调用。因此,我当前的解决方法是实际生成一个仅包含 en_US 语言环境的 /usr/lib/locale/locale-archive,调用 setlocale(LC_MESSAGES, "en_US"); setenv("LANGUAGE", "fake");,最终加载正确的消息目录。仍然感觉像一个丑陋的解决方法,我仍然不明白为什么没有它静态链接也能工作。
【问题讨论】:
-
将
setlocale(LC_MESSAGES, "");与适当的环境变量一起使用不是更好吗? -
这是一个嵌入式系统,我在没有设置环境变量的情况下运行。当程序启动时,我从配置文件中加载要使用的语言(即要设置的语言环境)。
-
首先执行
setenv("LC_MESSAGES", "fake")并用setlocale(LC_MESSAGES, "")替换setlocale 调用仍然与直接执行setlocale()调用相同。
标签: c localization glibc setlocale