【问题标题】:dgettext failing to translate stringdgettext 无法翻译字符串
【发布时间】:2020-10-28 12:15:10
【问题描述】:

我使用 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 上对此进行测试。它在 linux 上使用 setlocale(LC_ALL, "en_US.UTF-8") 工作,但这在 macOS 上不起作用。

结果不包含翻译后的字符串,它是原始字符串“测试字符串”。我可能会错过什么?有没有办法调试 dgettext?

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


在 Linux 上使用 strace 进行进一步调查后,虽然 setlocale(LC_ALL, "en_US.utf8") 有效,但 setlocale(LC_ALL, "en_US") 无效 - strace 输出包括使用 en_US.utf8 时不存在的这些行:

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)

Full output

Output using en_US.utf8

Linux 似乎正在寻找要在 LC_IDENTIFICATION 中使用的默认编码,但该文件不存在 (Ubuntu 20.04.1)

编辑:按照Guido Flohr 的建议运行sudo locale-gen en_US 后,程序按预期运行。


在 macOS 10.15.7 (19H2) 上使用 dtruss 进行进一步调查后,open 调用是针对不存在的 en_GB 目录(我的默认系统语言),并且 en_US 仅在以下情况下才有效默认语言设置为English (US),即看起来setlocale实际上无法更改语言环境,即使它返回传递给它的语言环境。这似乎是一个错误?我想我会向 Apple 报告。

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

【问题讨论】:

  • setlocale(LC_ALL, "en_US") 在您的 linux 系统上失败(返回 null)。所以这是一个 glibc 问题。你能检查locale -a 的输出吗?您是否尝试使用sudo locale-gen en_US 安装语言环境en_US
  • Ubuntu 设置的语言设置为English (United States)。但是,locale -a 仅返回 en_US.utf8(以及其他语言)。在按照建议运行sudo locale-gen en_US 后,出现了en_USen_US.iso88591。然后程序使用setlocale(LC_ALL, "en_US") 按预期运行。这样Linux就解决了,谢谢
  • 现在 macOS 也解决了(有点)。感谢您的帮助。

标签: c internationalization gettext


【解决方案1】:

您的代码是正确的,可以在我的 Mac OS 和 linux 系统上运行,en_USen_US.UTF-8。因此,除了在调用 setlocale() 时通常应该使用本地语言环境 "" 之外,您并没有遗漏任何东西,但您自己可能知道:

setlocale(LC_ALL, "");

所以,我只能回答如何调试问题。

基本上有两件事会出错:

首先,您使用setlocale() 选择的语言环境在您的系统上不可用。这可以通过输出setlocale(LC_ALL, selected_locale) 的返回值轻松检查。在您的测试项目中,您已经这样做了。如果所选语言环境不可用,则对 setlocale() 的调用将返回 NULL

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

$ sudo dtruss ./dgettextexample

只需跟踪您的程序正在尝试使用哪些文件open() 即可获得出错的提示。

【讨论】:

  • 查看我对我的问题所做的修改——我不知道是否有什么办法可以解决这两个问题
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-15
    • 2015-01-13
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    相关资源
    最近更新 更多