Rails - 如何动态添加/覆盖 i18n yaml 中的文本?

10

举个例子,我有一个默认的英语本地化文件 "en.yml",它的内容如下:

 en:
  messages: messages
  users: users

现在,有一个客户希望在他的产品中将消息命名为“讨论”,但用户仍应该保持为“用户”。因此我想创建一个名为“customer.en.yml”的文件。

en:
 messages: discussions

如何在保留其他单词不变的情况下覆盖默认的"messages"翻译?我该如何实现呢?

因为如果我加载en.yml文件,会出现以下情况:

config.i18n.load_path += Dir[File.join(RAILS_ROOT, 'config', 'locales', '*.{rb,yml}')] 

接着使用以下方式加载customer.en.yml文件(假设APP_CONFIG['customer_name']已经定义):

config.i18n.load_path += Dir[File.join(RAILS_ROOT, 'config', 'custom_locales',  APP_CONFIG['customer_name']+'.{rb|yml}')]

它只会覆盖我的“en”本地化,而“users”翻译将消失,对吗?

4个回答

7

使用i18n.fallbacks

我不确定这是在哪个版本的Rails中添加的,但在4.2.2中,您可以执行以下操作:

# application.rb
# If key is not found in a locale, we look in fallback
config.i18n.fallbacks = {
  "locale_1"    => "en",
  "locale_2"    => "en",
  "locale_3"    => "de",
}

如果你也设置了 config.action_view.raise_on_missing_translations = true (我在开发和测试中都这样做),它只会在语言环境或者回退中找不到键时才会引发异常。

3

它不应该覆盖您的“en”本地化。翻译将被合并。store_translations在简单的I18n后端中调用merge_translations,其代码如下:

# Deep merges the given translations hash with the existing translations
# for the given locale
def merge_translations(locale, data)
  locale = locale.to_sym
  translations[locale] ||= {}
  data = deep_symbolize_keys(data)

  # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
  merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
  translations[locale].merge!(data, &merger)
end

正如您所见,只有在后面的翻译 yml 文件中输入的键才会被覆盖。


1

当我们写一个 pirate.yml 的翻译时,我想要的是类似的东西,但我希望在 pirate.yml 中未定义的任何内容都可以默认为 en.yml 中的内容。

我写的代码可以在 Github 上找到。


Github链接已失效! - Yan Foto
无效?虽然这是一个非常老的项目,但链接对我仍然有效。你是否遇到了404错误? - Amiel Martin
我得到的正是“页面未找到”! - Yan Foto
@YanFoto 奇怪,链接对我仍然有效(即使未登录)。可能是https问题吗?您需要代码吗?我可以为您提供gist。我不确定我还能怎么帮助您... - Amiel Martin
当我复制/粘贴链接时,它可以工作,但是当我点击它时却不行!神秘...但是我已经找到了解决我的问题的方法。谢谢! - Yan Foto

-2

我认为你可能混淆了两件不同的事情。

i18n文件是用于翻译的。

如果您有一个客户端需要某个字段的特定名称,那不是一个翻译问题,而是功能问题。

换句话说,我认为您需要这样的东西:

 en:
   messages: messages
   users: users
   discussions: discussions

然后在其他地方添加特定的功能,例如在您的视图中:

if(customer.needs_discussions?)
<%= t(:discussions) %>
else
<%= t(:messages) %>
end

或者,您可以为客户添加一个字符串属性,默认为“messages”。然后,您的视图将如下所示:

<%= t(customer.messages_field_name) %>

2
好的,那么如果他需要200个措辞上的更改,我就必须写200个if语句并添加200个客户设置,对于每个使用产品的其他客户也是如此。这将大大增加代码量。而且,如果特定客户离开了,所有这些if语句都会留在代码中,否则我只需删除翻译覆盖即可。 - Pavel K.
这段代码只是一个例子 - 我的意思是你不应该用i18n来做那件事。我已经在我的评论中编辑了其他解决方案。如果你继续考虑使用i18n,请想想当你需要将你的应用程序翻译成法语时会发生什么。 - kikito
1
我已经有了法语和英语的i18n,并在其上加载客户端重写。 我有locales/en.yml,locales/fr.yml以及在需要时加载locales/customer.en.yml和locales/customer.fr.yml。 很抱歉,但我真的认为这种方式对于简单措辞的自定义更好。 - Pavel K.

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