dgettext无法翻译字符串

问题描述

我正在使用gettext / libintl,如下所示:

setlocale(LC_ALL,"en_US");
char * result = bindtextdomain("MyApp","/absolute/path/to/locale/dir");
assert(result);
result = dgettext("MyApp","Test String");

/absolute/path/to/locale/dir中,我的翻译文件位于en_US/LC_MESSAGES/MyApp.mo

我正在macOS上对此进行测试。它可以在使用setlocale(LC_ALL,"en_US.UTF-8")的Linux上运行,但是在macOS上则无法运行。

结果不包含转换后的字符串,它是原始字符串“ Test String”。我可能会缺少什么?有什么方法可以调试dgettext?

示例项目:https://mega.nz/file/uBATVKKA#O57nnKDHRELEY8m7U_dmC1OZLiK490sqgvoDRnT7wWY


在Linux上使用strace进行了进一步调查后,尽管setlocale(LC_ALL,"en_US.utf8")有效,但是setlocale(LC_ALL,"en_US")无效– strace输出包括使用{{1}时不存在的这些行}:

en_US.utf8

Full output

Output using en_US.utf8

Linux似乎正在寻找openat(AT_FDCWD,"/usr/lib/locale/en_US/LC_IDENTIFICATION",O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) openat(AT_FDCWD,"/usr/lib/locale/en/LC_IDENTIFICATION",O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 中使用的认编码,但是该文件不存在(Ubuntu 20.04.1)

编辑:按照Guido Flohr的建议运行LC_IDENTIFICATION后,程序将按预期运行。


在macOS 10.15.7(19H2)上使用sudo locale-gen en_US进行了进一步调查之后,dtruss调用是针对open目录(我的认系统语言)的,该目录不存在,并且en_GB仅在认语言设置为en_US的情况下有效,即English (US)看起来实际上不能更改语言环境,即使它返回传递给它的语言环境也是如此。这似乎是一个错误?我想我会向苹果报告。

编辑:似乎setlocale被忽略,而赞成macOS中的setlocale环境变量(通过Homebrew安装的LANG)。在gettext之前添加setenv((char *)"LANG=en_US");会加载正确的邮件文件,而bindtextdomain将按预期返回翻译。

解决方法

您的代码正确,并且可以在en_USen_US.UTF-8的Mac OS和linux系统上使用。因此,除了您通常应该在调用""时使用本地语言环境setlocale()之外,您什么都不会丢失,但是您可能知道自己:

setlocale(LC_ALL,"");

因此,我只能回答如何调试问题的问题。

基本上有两件事可能出错:

首先,您使用setlocale()选择的语言环境在系统上不可用。通过输出setlocale(LC_ALL,selected_locale)的返回值可以很容易地检查出它。在测试项目中,您已经做到了。如果所选区域设置不可用,对setlocale()的调用将返回NULL

第二个可能出错的地方是找不到翻译目录。最好在GNU / Linux上使用strace或在Mac OS上使用dtruss进行调试:

$ sudo dtruss ./dgettextexample

只需跟踪您的程序正在尝试open()的文件,以提示问题所在。

,

由于可能有多种原因,因此GNU gettext常见问题解答https://www.gnu.org/software/gettext/FAQ.html#integrating_noop包含确定环境中原因的方法。