From 70e624993057a45573b73ca0259a8ea61f7c3231 Mon Sep 17 00:00:00 2001 From: Markus Doits Date: Thu, 8 Sep 2016 20:51:03 +0200 Subject: [PATCH] some tests and fixes for some cache invalidation misses --- lib/i18n/globals.rb | 32 +++++++++++++++++++++ test/test_i18n_globals.rb | 60 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/lib/i18n/globals.rb b/lib/i18n/globals.rb index 77430c5..99a258d 100644 --- a/lib/i18n/globals.rb +++ b/lib/i18n/globals.rb @@ -6,6 +6,7 @@ class Config class CachedGlobals < Hash def []=(key, val) clear_cache + annotate_hash(val) if val.is_a?(Hash) # see annotate hash below why whis must be done super(key, val) end @@ -17,6 +18,17 @@ def for_locale(locale) end end + def clear + clear_cache + super + end + + def merge!(val) + # see annotate hash below why whis must be done + val.select { |_, v| v.is_a?(Hash) }.each { |_, v| annotate_hash(v) } + super(val) + end + private def globals_cache @@ -26,6 +38,26 @@ def globals_cache def clear_cache @globals_cache = {} end + + # This is a little bit cumbersome. It might happen that this is done: + # + # I18n.config.globals[:en][:welcome] = 'Hello' + # + # What this does is changing the locale dependent version of `welcome`. + # Unfortunately we only override `:[]=` for our globals hash so it + # does not detect that the globals have been changed. + # + # To overcome this we annotate every hash that might passed in with this + # method. So when the sub hash is changed like above, the whole cache + # is cleared like it should. + def annotate_hash(hash) + return if hash.instance_variable_get(:@cached_global) + hash.instance_variable_set(:@cached_global, self) + def hash.[]=(key, value) + super(key, value) + @cached_global.send(:clear_cache) + end + end end def globals diff --git a/test/test_i18n_globals.rb b/test/test_i18n_globals.rb index 8d0419e..2e428d3 100644 --- a/test/test_i18n_globals.rb +++ b/test/test_i18n_globals.rb @@ -6,6 +6,8 @@ class TestI18nGlobals < Minitest::Test def setup I18n.backend.load_translations 'test/fixtures/translations.yml' I18n.config = I18n::Config.new + I18n.config.globals = {} # glear globals between runs + I18n.locale = :en end def test_that_simple_translations_work @@ -70,4 +72,62 @@ def test_that_global_variables_are_shared_between_config_instances assert_equal I18n.translate('greeting'), 'Hi there, Greg!' end + + def test_that_locale_dependent_variable_overrides_default_one + I18n.config.globals = { + name: 'Greg', + en: { name: 'Debby' } + } + + assert_equal 'Hi there, Debby!', I18n.translate('greeting') + end + + def test_that_default_variable_is_used_if_no_special_locale_version_is_present + I18n.config.globals = { + name: 'Greg', + fr: { name: 'Debora' } + } + + assert_equal 'Hi there, Greg!', I18n.translate('greeting') + end + + def test_that_cache_is_cleared_after_setting_a_new_locale_global + I18n.config.globals = { + name: 'Greg', + en: { name: 'Debby' } + } + + assert_equal 'Hi there, Debby!', I18n.translate('greeting') + + I18n.config.globals[:en][:name] = 'Elisa' + + assert_equal 'Hi there, Elisa!', I18n.translate('greeting') + end + + def test_that_cache_is_cleared_after_setting_a_new_locale_hash + I18n.config.globals = { + name: 'Greg', + en: { name: 'Debby' } + } + + assert_equal 'Hi there, Debby!', I18n.translate('greeting') + + I18n.config.globals[:en] = { + name: 'Elisa' + } + + assert_equal 'Hi there, Elisa!', I18n.translate('greeting') + end + + def test_that_cache_is_cleared_after_setting_a_new_global + I18n.config.globals = { + name: 'Greg' + } + + assert_equal 'Hi there, Greg!', I18n.translate('greeting') + + I18n.config.globals[:name] = 'Dobby' + + assert_equal 'Hi there, Dobby!', I18n.translate('greeting') + end end