Rails I18n 嵌套翻译键

6
有没有一种方法可以嵌套翻译查找?就像这样:
en:
  uh_oh: 'Uh Oh!'
  error1: :'uh_oh' + ' There was a big error!'
  error2: :'uh_oh' + ' There was another big error!'

I18n.t('error1') #=> 'Uh Oh! There was a big error!'
I18n.t('error2') #=> 'Uh Oh! There was another big error!'

我已经尝试过很多不同的变化,也尝试使用 Ruby 的翻译文件代替 YAML。请注意这个确实可以工作:

en:
  uh_oh: 'Uh Oh!'
  error1: :'uh_oh'

I18n.t('error1') #=> 'Uh Oh!'

但是如果我给error1添加其他文本,uh_oh就不会被翻译了。

基本上,我想避免总是传递常见术语,像这样:

en:
  uh_oh: 'Uh Oh!'
  error1: '%{uh_oh} There was a big error!'

I18n.t('error1', {uh_oh: I18n.t('uh_oh')})

对于常见术语,例如uh_oh,每次调用error1(和任何其他使用uh_oh的键)的内插都是相同的,因此没有必要传入要内插的字符串。相反,可以更轻松地执行以下操作,并让error1翻译处理通用键翻译:

I18n.t('error1')
2个回答

6
我不会回答你的问题(我认为使用i18n gem不可能,但也有可能是我错了)。我要说的是,你不应该采取这种方法,并给你提供背景链接[1]。作为开发人员,看到模式并提取通用代码以保持DRY是很自然的。但在处理多种语言时,这一步太过头了,会阻止正确翻译。并非所有语言都遵循英语相同的句子结构,你所替换的内容可能需要更改以与其他部分的句子一致。
在我工作的网站上,我们在法语方面遇到了这个问题。我们有包含地名的句子,在英语中很简单。无论地名是什么,“%{location_name} property”都可以使用。但在法语中,你需要根据地点是城镇、省份、地区以及名称是否以元音字母开头来使用不同的结构。
[1] http://www.multilingual.com/articleDetail.php?id=594

我知道你所说的不同句子结构和语法规则。但是,无论是从翻译键/值对(就像我所问的那样)中获取变量的值,还是通过显式传递它来获取变量的值,都不会改变你在每种语言文件中如何构造句子的方式。 - Brian Ray
是的,你仍然需要注意性别。我认为你需要编写自己的帮助程序来实现这一点。例如,将你的键设置为:key: "!some.key! foo bar"在这种情况下,你的 I18n.t 包装器会获取该键,然后查找 some.key 并进行替换。 - chrismcg
您也可以将其作为定制的i18n后端来完成此操作。 - chrismcg
@chrismcg 对于所给的例子来说,句子结构的差异并不是一个问题,因为在其他语言的error1和error2中,'uh_oh'可以放在不同的位置,或者完全省略。 - undefined

0

你可以单独使用"I18n.t('error1')"替换的原因是这是I18n调用的一个特殊情况,被称为"符号链接"。

不幸的是,它不会做任何进一步的操作,只会进行一次完整的替换。

我看到解决这个问题有两种方法。第一种是后处理I18n的输出,但当你无法完全控制何时调用I18n和翻译消息的消耗可能分散在各处(例如在Rails中)时,这可能很困难。最好的选择可能是覆盖I18n.t函数。

另一种选择是利用在I18n后端存储lambda的能力。不幸的是,这意味着你不能将组合翻译存储在YAML文件中,因为它只支持基本字符串。

例如,在翻译YAML中,我们可以有任何错误消息:

en:
  error:  "There was a big error [%{arg}]!"

现在我们想要在它之前使用 uh_oh 的翻译来调用它。 我们需要将 uh_oh 的组合翻译与 I18n 后端存储:

translam = lambda { |key,opts| "Uh Oh! #{I18n.t(opts[:for],opts)}" }
I18n.backend.store_translations(:en,:uh_oh => translam)

现在我们可以翻译“uh_oh”,并为其提供我们想要翻译的错误以及它可能需要的任何参数:
I18n.t(:uh_oh, for: :error, arg: 42))  #=> 'Uh Oh! There was a big error [42]!'

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