printf 有其他选择吗?

发布于 2024-09-26 22:17:58 字数 557 浏览 6 评论 0原文

我必须创建一个必须在多个 *nix 平台(Linux、AIX...)上运行的软件。

我需要处理国际化,我的翻译字符串采用以下形式:

"Hi %1, you are %2." // English
"Vous êtes %2, bonjour %1 !" // French

这里 %1 代表名称,%2 代表另一个单词。我可以改变格式,这不是问题。

我尝试使用 printf() 但您无法指定参数的顺序,您只需指定它们的类型。

"Hi %s, you are %s"
"Vous êtes %s, bonjour %s !"

现在无法知道使用哪个参数来替换 %sprintf() 仅使用第一个参数,然后是下一个。

除了 printf() 之外,还有其他方法可以解决这个问题吗?

注意:gettext() 不是一个选项。

I have to create a software that must work on several *nix platforms (Linux, AIX, ...).

I need to handle internationalization and my translation strings are in the following form:

"Hi %1, you are %2." // English
"Vous êtes %2, bonjour %1 !" // French

Here %1 stand for the name, and %2 for another word. I may change the format, that's not an issue.

I tried to use printf() but you cannot specify the order of the parameters, you just specify their types.

"Hi %s, you are %s"
"Vous êtes %s, bonjour %s !"

Now there is no way to know which parameter to use for replacement of %s: printf() just uses the first one, then the next.

Is there any alternative to printf() that deals with this ?

Note: gettext() is not an option.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

萌逼全场 2024-10-03 22:17:58

我并不是想传达坏消息,但你的提议实际上是一个坏主意。我在一家非常重视国际化的公司工作,我们(痛苦地)发现你不能只是将单词插入这样的句子中,因为它们通常毫无意义。

我们所做的就是简单地将错误文本与变量位完全断开,以避免这些问题。例如,我们将生成一个错误:

XYZ-E-1002 Frobozz not configured for multiple zorkmids (F22, 7).

然后,在错误描述中,您只需说明末尾括号中的两个值是 Frobozz 标识符和您尝试对其施加的 zorkmids 数量。

这使得国际化翻译成为一项极其简单的任务,因为在翻译时您已经拥有了所需的所有语言元素,而不必担心变量位应该是单数还是复数、男性还是女性、第一还是第二,或第三种变格(无论其实际含义是什么)。

翻译团队只需转换“Frobozz notconfiguration for multiple zorkmids”,这就容易多了。


对于那些想查看具体示例的人,我从我们的翻译机构那里得到了一些反馈(已更改了足够的内容以保护有罪者)。

在某个时候,有人提交了以下内容:

The {name} {object} is invalid

其中 {name} 是对象的名称(客户、订单等),{object} 是对象类型本身(表、文件、文档、存储过程等)。

对于英语来说很简单,英语是开发人员的主要(可能是唯一)语言,但他们在翻译成德语/瑞士德语时遇到了问题。

虽然“客户文档”(从位置意义上)正确翻译为 Kundendokument,但格式字符串在两个单词之间有空格这一事实是一个问题。这基本上是因为开发人员试图让句子听起来更自然,但不幸的是,基于他们有限的经验,这只是更自然。

更大的问题是“客户存储过程”,它变成了“gespeichertes Verfahren der Kunden”,字面意思是“客户的存储过程”。虽然德国客户可能已经忍受了 Kunden dokument 中的空格,但无法将 gespeichertes Verfahren der Kunden 强加到 {name} {object}< /代码> 成功。

现在你可能会说更聪明的格式字符串可以解决这个问题,但是有几个原因会导致这种情况不正确:

  • 这是一个非常简单的示例,可能还有其他更复杂的示例(我会尝试获取一些示例,但我们的翻译董事会已经明确表示,他们有更紧迫的工作,而不是屈服于我的每一个突发奇想)。
  • 格式字符串的全部意义在于外部化翻译。如果格式字符串本身特定于翻译目标,那么通过外部化文本您将获得很少的收益。
  • 开发人员不必担心像 {possible-pre-adjectives} {possible-pre-owner} {object} {possible-post-adjectives} {possible-post-所有者} {possible-postowner-adjectives}。这是翻译团队的工作,因为他们了解其中的细微差别。

请注意,引入断开连接很好地回避了这个问题:

The object specified by <parameter 1>, of type <parameter 2>, is invalid.
    Parameter 1 = {name}.
    Parameter 2 = {object}.
Der sache nannte <parameter 1>, dessen art <parameter 2> ist, ist falsch. 
    Parameter 1 = {name}.
    Parameter 2 = {object}.

最后的翻译是我的翻译之一,请不要用它来质疑我们翻译人员的质量。毫无疑问,德语说得更流利的人会从中大笑。

I don't mean to be the bearer of bad tidings but what you're proposing is actually a bad idea. I work for a company that take i18n very seriously and we've discovered (painfully) that you cannot just slot words into sentences like that, since they often make no sense.

What we do is to simply disconnect the error text from the variable bits altogether, so as to avoid these problems. For, example, we'll generate an error:

XYZ-E-1002 Frobozz not configured for multiple zorkmids (F22, 7).

And then, in the description of the error, you state simply that the two values in the parentheses at the end were the Frobozz identifier and the number of zorkmids you tried to inflict on it.

This leaves i18n translation as an incredibly easy task since you have, at translation time, all of the language elements you need without worrying whether the variable bits should be singular or plural, masculine or feminine, first, second, or third declension (whatever the heck that actually means).

The translation team simply has to convert "Frobozz not configured for multiple zorkmids" and that's a lot easier.


For those who would like to see a concrete example, I have something back from our translation bods (with enough stuff changed to protect the guilty).

At some point, someone submitted the following:

The {name} {object} is invalid

where {name} was the name of a object (customers, orders, etc) and {object} was the object type itself (table, file, document, stored procedure, etc).

Simple enough for English, the primary (probably only) language of the developers, but they struck a problem when translating to German/Swiss-German.

While the "customers document" translated correctly (in a positional sense) to Kundendokument, the fact that the format string had a space between the two words was an issue. That was basically because the developers were trying to get the sentence to sound more natural but, unfortunately, only more natural based on their limited experience.

A bigger problem was with the "customers stored procedure" which became gespeichertes Verfahren der Kunden, literally "stored procedure of the customers". While the German customers may have put up with a space in Kunden dokument, there is no way to impose gespeichertes Verfahren der Kunden onto {name} {object} successfully.

Now you may say that a cleverer format string would have fixed this but there are several reasons why that would be incorrect:

  • this is a very simple example, there are likely to be others more complex (I'd try get some examples but our translation bods have made it clear they have more pressing work than to submit themselves to my every whim).
  • the whole point of the format strings is to externalise translation. If the format strings themselves are specific to the translation target, you've gained very little by externalising the text.
  • developers should not have to concern themselves with format strings like {possible-pre-adjectives} {possible-pre-owner} {object} {possible-post-adjectives} {possible-post-owner} {possible-postowner-adjectives}. That is the job of the translation teams since they understand the nuances.

Note that introducing the disconnect sidesteps this issue nicely:

The object specified by <parameter 1>, of type <parameter 2>, is invalid.
    Parameter 1 = {name}.
    Parameter 2 = {object}.
Der sache nannte <parameter 1>, dessen art <parameter 2> ist, ist falsch. 
    Parameter 1 = {name}.
    Parameter 2 = {object}.

That last translation was one of mine, please don't use it to impugn the quality of our translators. No doubt more fluent German speakers will get a good laugh out of it.

强辩 2024-10-03 22:17:58

POSIX printf() 支持位置参数。

printf("Hi %1$s, you are %2$s.", name, status);
printf("Vous êtes %2$s, bonjour %1$s !", name, status);

POSIX printf() supports positional arguments.

printf("Hi %1$s, you are %2$s.", name, status);
printf("Vous êtes %2$s, bonjour %1$s !", name, status);
巷雨优美回忆 2024-10-03 22:17:58

boost.format 像 python 一样支持这种方式,但是这是针对 C++ 的

boost.format supports this the way like in python however this is for C++

或十年 2024-10-03 22:17:58

您需要大多数 Unix 系统通用的 %n$s 扩展名。

"Hi %1$s, you are %2$s."

请参阅底部的德语示例 printf

问候
戴夫·F

You want the %n$s extension that is common to most Unix systems.

"Hi %1$s, you are %2$s."

See the German example at the bottom printf

Regards
DaveF

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文