私はこの問題を掘り下げましたが、大まかな答えがあると思います。この問題は、への最初の呼び出しが行われるまで、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
何が起こっているかは、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
リロードしなくても、I18n.backend.store_translations
呼び出し時の翻訳が元の文字列で上書きされるため、元の文字列が吐き出されますI18n.t
。I18n.t
ただし、上記のコードの前に呼び出した場合は機能します (翻訳ensure
をリロードするブロックがないため、翻訳は終了します)。
したがって、基本的には、実際の翻訳文字列を呼び出してレールをトリガーし、変更したい翻訳をオーバーライドする前I18n.t
に既存の翻訳をロードするだけです。
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
これはコンソールでしか試していませんが、rspec テストでも機能すると思います。誰かがこの問題についてより深い洞察を持っているなら、私は彼らの話を聞きたいと思っています.