据我了解这个问题,这是您主要关心的问题:
所有这些意味着翻译人员(其中大多数不是计算机程序员)必须非常小心地进行翻译,每个人都需要非常小心包含 % 的翻译。
tl;dr:这就是原因msgfmt
有一个选项--check
。该选项导致msgfmt
检查翻译是否可以安全地通过目标语言的字符串插值工具运行。所有这些问题的根源都是Cprintf()
当使用错误的参数调用时,很容易崩溃:
printf("Bonjour, %s!");
The printf()
函数是一个可变函数。这%s
导致它从堆栈中弹出另一个参数。在上面的示例中,除了字符串文字之外没有其他参数。这意味着插入的字符串%s
可以被认为来自任意地址,例如 0。在大多数现代语言中这将是空指针异常。在 C 中,它是一个空指针取消引用,经常被利用来运行任意代码,这很糟糕。
我们假设代码如下所示:
printf(gettext("Hello, world!"));
只要翻译是安全的gettext()
出现的内容不包含任何“%”字符。但如果法语翻译翻译“你好,世界!”与“你好,%s!”程序会崩溃。
好吧,如果软件的维护者使用标准的翻译工作流程,它就不会崩溃。在这种情况下,xgettext
(在 Python 中,它可能类似于“pybabel extract”)会在.po
file:
#: filename.c:1
#, c-format
msgid "Hello, world!"
msgstr ""
将“#, c-format”行读取为“这是一个 printf 格式字符串”!
比如说,法语翻译将其翻译成以下条目:
#: filename.c:1
#, c-format
msgid "Hello, world!"
msgstr "Bonjour, %s!"
如果你运行这个msgfmt whatever.po
它将被接受。但这不是推荐的工作流程。你应该运行它msgfmt --check whatever.po
。现在你得到一个错误:
messages.po:23: number of format specifications in 'msgid' and 'msgstr' does not match
msgfmt: found 1 fatal error
这是因为对于 GNU gettext 支持的每种语言,都会实现一个格式检查器来准确检查该问题。它确保翻译不会导致运行时问题。
您现在可能会争辩说,恶意翻译器会简单地从文件中删除“c-format”限定符。.po
文件。但是您的构建系统应该确保从外部源返回的翻译始终与当前的消息集合并,通常称为YOURPROJECT.pot
,然后这样的修改.po
文件将被简单地丢弃。
所以,理论上你说的没有道理。在实践中,您可能会拥有一个,因为有很多项目和软件都使用.po
文件直接用于运行时翻译。这是一个坏主意,请参阅我的答案 https://stackoverflow.com/questions/53743208/benefits-of-compiling-po-files-to-mo/53819204#53819204类似的问题。
我不知道这在多大程度上适用于你的问题,因为你没有提到如何将字符串提取到你的.pot
文件以及如何将其编译为二进制文件.mo
文件。上面的解释应该清楚地表明这一点至关重要:提取步骤应该向.po
关于所使用的字符串插值方法的文件,以及.po
文件到一个.mo
文件应启用格式字符串检查。如果你做不到这一点,那么你的构建系统就有缺陷。