使用Google翻译将基于printf的字符串进行翻译。

4
我正在尝试使用基于网络的Google翻译将我的英语文件翻译为另一种语言。它们包含像%s和%d这样的字符。有没有办法保护它们不被错误地翻译。
例如,文本:
运动员已经存在,编号为%s
被翻译为:
Athlète existe déjà avec nombre% s
而我希望它被翻译为:
Athlète existe déjà avec nombre %s
(我正在处理输入和输出,所以我可以在其周围添加字符来“转义”% s和%d字符串。我想过用某个单词来替换%s,我确信谷歌不会尝试自行翻译,但我希望有一个更好的解决方案)

2
将C风格的格式字符串翻译成另一种语言并不是一个好主意(我以前也曾这样做过,所以我知道)。不能保证所有格式说明符的顺序在另一种语言中是相同的。例如,“Error reading line %ld of file %s”可以翻译成“Probleem tijdens lezen van bestand %s, lijn %ld”(荷兰语)。考虑使用另一种约定,比如.NET,其中使用{1},{2}等。当然,你应该自己解析这些字符串,这比仅仅使用printf要困难一些,但在长期内将会获得更好的结果。 - Patrick
3
@Patrick:Tcl支持格式字符串中的XPG3位置指示符,例如%1$ld。 对于这种情况非常有用,而msgcat包使其更容易实现。 - Donal Fellows
@Patrick:我试图通过谷歌翻译输入类似{\1}的内容,但它无法保持完整,所以对于{1}的运气可能也不太好。 - Roalt
@Donal:我之前还不知道Tcl的msgcat支持%1$d语法。即使现在,我对这种语言的内容仍然感到惊讶... - Roalt
@Roalt:这就是为什么它在手册页面中明确记录了一个示例,尽管它不是“msgcat”本身的功能(而是“format”的功能)。 - Donal Fellows
显示剩余2条评论
4个回答

3

奇怪的想法,但是...

将每个格式说明符替换为下划线中的唯一数字(或任何在翻译过程中保持不变且不干扰您使用数字的内容),例如:

Athlete already exists with number %s => Athlete already exists with number _001_

翻译成中文: 运动员已经存在的号码 _001_

之后,检查翻译中的数字是否按照相同的顺序排列,如果有多个格式说明符在格式字符串翻译中,则将其替换回。


1
这类似于我的意见建议使用.Net规范符号:{1},{2}。优点是翻译可以更改格式说明符的顺序,翻译仍将起作用。 - Patrick
Donal,在翻译时,请尽量避免使用男性/女性(特别是在翻译成法语、德语等语言时),以及单数/复数。请注意,甚至有些语言对于两个不同的后缀与许多的后缀也不同(斯洛文尼亚语)。 - Patrick
1
下划线(_)的使用非常聪明,因为它不属于任何词汇,但对于机器来说却被认为是字母的一部分。考虑到中文的翻译效果良好,这种方法可能适用于大多数其他语言。我会尝试一下! - Roalt
我使用谷歌翻译的想法是为了得到一个良好的“第一次尝试”翻译。母语翻译人员将更容易手动翻译列表以获得更好的语言表达。 - Roalt
使用双下划线('name')在两侧非常好用,谷歌不会尝试翻译它们(或者它无法翻译)。无论哪种方式,对我来说都很有效,谢谢! - Steve Bauman
显示剩余2条评论

2

对于sprintf的PHP文章的评论还提供了一个巧妙的解决方案。

http://www.php.net/manual/en/function.sprintf.php#93552

/**
 * Converts any sprintf to a Google Translate suitable string.
 */
function _toTranslateSafeString($original)
{
    $pattern = '/(?:%%|%(?:[0-9]+\$)?[+-]?(?:[ 0]|\'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFosxX])/';       
    $escapeString = '<span class="notranslate">$0</span>';
    return preg_replace($pattern, $escapeString, $original);
}

/**
 * Converts any Google Translate suitable string to a sprintf string.
 */
function _fromTranslateSafeString($translated)
{
    $escapePattern = '/<span class="notranslate">([^<]*)<\/span>/';
    return preg_replace($escapePattern, '$1', $translated);
}

1
你是否已经重构了程序,使用msgcat包来处理字符串?它的文档涵盖了大部分要点,包括如何处理替换的顺序。唯一有点棘手的是你需要处理%符号移动的方式;如果处理的文本量足够小,你甚至可以手动或借助一些机械辅助工具(vi、emacs和eclipse都可以完成所需的匹配/替换操作;其他编辑器可能也可以,但我不用那些)。

是的,我使用msgcat包来进行翻译。目前,在句子中实际上有多个%s实例的字符串数量有限,对于我最初从英语到荷兰语的单一翻译,我还没有遇到问题(但)。也许在法语方面我会遇到这些问题! - Roalt

0
我建议逐个翻译字符串的每个部分,然后再添加c令牌。你可能会得到不太准确的翻译,但这就是使用自动翻译器的风险。
而且总有测试人员 :)
或者更好的想法:将%d更改为任意整数,将%s更改为任意拉丁字符串,Google不会对其进行翻译(使用罕见的姓氏通常可以解决问题),将%d更改为任意数字等。

4
让我想起我们在公司20年前所做的事情。 想象一下像“读取文件%s的第%d行时出错,字符%c无效”这样的字符串。你不能认真翻译所有的部分,例如“读取文件”,“的第”,“行时出错”,“,字符”和“无效”。这只会产生垃圾。你甚至不想把它交给你的测试人员。 - Patrick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接