gpt4 book ai didi

c - 将 LC_MESSAGES 设置为不存在的语言环境的 setlocale() 失败

转载 作者:太空狗 更新时间:2023-10-29 15:06:55 24 4
gpt4 key购买 nike

对于嵌入式软件项目,我正在添加对翻译的支持,并且由于我们运行的是嵌入式 Linux,所以我选择使用 libc gettext()。我们没有安装任何语言环境定义,所以我只尝试将 LC_MESSAGES 语言环境设置为我想要的语言环境:

setlocale(LC_MESSAGES, "fake");

(在我得到正确的翻译之前,我使用名称 fake 和一个 fake.mo 文件来进行伪翻译)。

这在静态链接时工作正常,它返回一个语言环境句柄,bindtextdomain() 和 friend 都工作正常,我从中得到我的“翻译”字符串:

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");,最终加载正确的消息目录。仍然感觉像是一个丑陋的解决方法,我仍然不明白为什么静态链接没有它就可以工作。

最佳答案

我有一个类似的问题(我对根文件系统没有太多控制的嵌入式系统),我发现这个解决方法有效:

  • 将所有翻译放入/<mydir>/lang/
  • SYS_LC_MESSAGES可以用 localedef 生成.我从系统上的 C 语言环境制作了一个并将其复制到每个目标目录

    mkdir output
    localedef -f UTF-8 -i /usr/share/i18n/locales/C output/mylocale
    cp output/mylocale/LC_MESSAGES/SYS_LC_MESSAGES <mydir>/lang/ENG/LC_MESSAGES/
  • 设置LOCPATH<mydir>
  • 使用 strace 进行调试查看它正在尝试打开哪些文件。

这是我最终的文件布局:

<mydir>
├── lang
│   ├── ENG
│   │   └── LC_MESSAGES
│   │   ├── SYS_LC_MESSAGES
│   │   └── mac.mo
│   ├── FRE
│   │   └── LC_MESSAGES
│   │   ├── SYS_LC_MESSAGES
│   │   └── mac.mo
│   ├── GER
│   │   └── LC_MESSAGES
│   │   ├── SYS_LC_MESSAGES
│   │   └── mac.mo
│   ├── ITA
│   │   └── LC_MESSAGES
│   │   ├── SYS_LC_MESSAGES
│   │   └── mac.mo
│   ├── SPA
│   │   └── LC_MESSAGES
│   │   ├── SYS_LC_MESSAGES
│   │   └── mac.mo

这是代码片段:

putenv("LOCPATH=/<mydir>/lang");
setlocale(LC_ALL, "");
setlocale(LC_MESSAGES, "ENG");
bindtextdomain("mac", "/<mydir>/lang");
textdomain("mac");
gettext("Hello world");

这是一个 hack,正确的解决方案是正确生成语言环境。

关于c - 将 LC_MESSAGES 设置为不存在的语言环境的 setlocale() 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36857863/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com