cau*_*eld 5 rspec ruby-on-rails internationalization
我想将我的测试与内化隔离开来。我使用 rails 3.2.8 和 rspec 2.11.1
我把这段代码 spec/support/translations.rb
module I18nHelpers
def with_translations(locale, translations)
I18n.backend.store_translations locale, translations
yield
ensure
I18n.reload!
end
Run Code Online (Sandbox Code Playgroud)
结尾
RSpec.configure do |config|
config.include I18nHelpers
end
Run Code Online (Sandbox Code Playgroud)
然后我测试应用程序助手:
describe ApplicationHelper do
context "messages" do
it "show body" do
with_translations :en, navigation: {messages: 'foo'} do
concat messages_navigation
assert_test 'span', 'foo'
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
但是这个测试随着消息而下降
Failure/Error: assert_select 'span', text: /foo/
MiniTest::Assertion:
</foo/> expected but was
<"Messages">.
Run Code Online (Sandbox Code Playgroud)
“消息”来自我真实的config/locales/en.yml
我从控制台测试 #store_translations 并且它有效。但是当我在 helper 模块中的 wordp I18n.t(translations.key.first)之前放一行时ensure,它显示了旧的翻译。
谢谢你的帮助!
要与I18n您完全隔离,可能需要像这样切换后端:
def with_translations(locale, translations)
original_backend = I18n.backend
I18n.backend = I18n::Backend::KeyValue.new Hash.new, true
I18n.backend.store_translations locale, translations
yield
ensure
I18n.backend = original_backend
end
Run Code Online (Sandbox Code Playgroud)
我已经深入研究了这个问题,我想我有一个粗略的答案。该问题似乎是由以下事实引起的:在第一次调用之前,rails 不会在语言环境文件中加载翻译I18n.t。
这有点旧,但仍然相关:
https://groups.google.com/forum/?fromgroups=#!msg/rails-i18n/QFe0GDVRIa0/G7K09NAgqJMJ
我们考虑了很多不同的方法,最终我们的解决方案是将实际翻译加载推迟到最新的可能点。因此,客户端(如 Rails)只会将翻译源注册到 I18n,并且当需要查找第一个翻译时,后端实际上会延迟加载它们。
所以基本上,现有的翻译仅在您调用 时才会加载I18n.t。我在控制台中玩耍时发现了这一点,当时我注意到非常奇怪的行为:
irb(main):001:0> def with_translations(locale, translations)
irb(main):002:1> I18n.backend.store_translations locale, translations
irb(main):003:1> yield
irb(main):004:1> ensure
irb(main):005:1* I18n.reload!
irb(main):006:1> end
=> nil
irb(main):007:0> I18n.reload!
=> false
irb(main):008:0> with_translations(:en, { :messages => "foo" }) { puts I18n.t :messages }
Messages
=> nil
irb(main):009:0> I18n.t :some_other_string
=> "Some translation"
irb(main):010:0> with_translations(:en, { :messages => "foo" }) { puts I18n.t :messages }
foo
=> nil
Run Code Online (Sandbox Code Playgroud)
发生的事情与块无关ensure。我们可以删除它,同样的事情也会发生:
irb(main):011:0> I18n.reload!
=> false
irb(main):012:0> def with_translations(locale, translations)
irb(main):013:1> I18n.backend.store_translations locale, translations
irb(main):014:1> yield
irb(main):015:1> end
=> nil
irb(main):016:0> with_translations(:en, { :messages => "foo" }) { puts I18n.t :messages }
Messages
Run Code Online (Sandbox Code Playgroud)
即使没有重新加载,它仍然会输出原始字符串,因为I18n.backend.store_translations调用时调用中的翻译会被原始字符串覆盖I18n.t。但是,如果您在上述代码I18n.t 之前调用,它将起作用(并保留翻译,因为没有ensure块重新加载翻译)。
所以基本上,答案就是调用I18n.t一个实际的翻译字符串来触发 Rails 加载现有的翻译,然后覆盖您想要更改的翻译:
def with_translations(locale, translations)
I18n.t translations.keys.first # to make sure translations are loaded
I18n.backend.store_translations locale, translations
yield
ensure
I18n.reload!
end
Run Code Online (Sandbox Code Playgroud)
我只在控制台中尝试过此操作,但我相信它也适用于您的 rspec 测试。如果有人对这个问题有更深入的见解,我很想听听他们的意见。
| 归档时间: |
|
| 查看次数: |
2664 次 |
| 最近记录: |