如何国际化由多个部分组成的字符串?

How to internationalize strings that are built up from multiple parts?

说我想请用户确认一个动作。动作由三部分组成。这三个部分中的每一个都可以用两种方式之一进行格式化。以特定于人类语言的方式,我可能会做这样的事情(伪代码):

res = ""
res = "Do you want to %1 at %2, %3 at time %4%5?" % (
    "foo" if fooing else "bar", foobar_data,
    "expiring" if expiring else "starting", the_time,
    ", without foobing" if no_foob else (", foobing at %1" % when_foob))

即使我用翻译函数包装所有可翻译的字符串(例如 tr("Do you want to %1 at %2 ...")),这也可能只适用于英语,因为其他语言不太可能具有相同的句法结构。

但是如果我写出整个句子然后我得到一个组合爆炸:

if fooing and expiring and no_foob:
    res = "Do you want to foo at %1, expiring at time %2, without foobing?"
elif fooing and expiring and not no_foob:
    res = "Do you want to foo at %1, expiring at time %2, foobing at %3?"
elif fooing and not expiring and no_foob:
    res = "Do you want to foo at %1, starting at time %2, without foobing?"
# etc ...
res = res % (foobar_data, the_time, when_foob) # account for sometimes not having when_foob somehow

处理这种情况的标准方法是什么?

我认为最好完全避免使用此类复杂的句子。相反,提供一个简单的句子并以类似 table 的方式添加更多细节(table 更容易翻译)。

这有额外的好处,您可以默认隐藏详细信息(渐进式披露)并保持主要信息简短。这增加了您的用户阅读确认对话框的机会。

模型:

Do you really want to <Foo/Bar>?

[ Cancel ]  [ <Foo/Bar> ]      [ Details... ]
---------------------------------------------
Time: <Expring at %1 / Starting at %1>
Foobing: <Yes/No>

Even if I wrap all translatable strings with the translation function, this would probably only work for english since other languages are unlikely to have the same syntactic structure.

是也不是。您显然可以切换句子和参数以适应目标语言:

Wollen Sie am %2 %1, %3 %4%5?

棘手的部分显然是获得赤纬等权利;虽然单词本身在交换时在英语中可能根本不会改变,但在其他语言中可能必须进行大量更改。

为此,翻译所有必要的变体非常重要,并能够在您的翻译系统中使用上下文对它们进行注释:

tr('foo', context='infinitive') if fooing else tr('bar', context='infinitive')
tr('expiring', context='verb before date') if expiring else tr('starting', context='verb before date')

例如 PO file format 内置了这个概念:

msgctxt "verb before date"
msgid "expiring"
msgstr "wird auslaufen am"

确实需要一些语言知识才能正确分解句子,能够正确分类和注释每个术语,以便根据需要将其正确翻译成所有语言,并且需要大量问答才能确保完成正确。您希望在足够小的片段(可以重复使用译文)和将其分解得足够多(以便可以正确翻译)之间找到适当的平衡。

如果太复杂,您也可以使用消息 ID:

res = "question.confirmActivty" % (..)

msgid "question.confirmActivty"
msgstr "Do you want to %1 at %2, %3 at time %4%5?"