PERF: bypass slow locale lookups in various cases

PERF: bypass slow locale lookups in various cases

Previously as soon as any override was defined we would regress to the slow path for locale lookups. Additionally if raise: true was specified which rails likes to add in views we would bypass the cache

The new design manages to use the fast path for many more cases

diff --git a/lib/freedom_patches/translate_accelerator.rb b/lib/freedom_patches/translate_accelerator.rb
index ea43dac..7a8969d 100644
--- a/lib/freedom_patches/translate_accelerator.rb
+++ b/lib/freedom_patches/translate_accelerator.rb
@@ -19,7 +19,7 @@ module I18n
     alias_method :reload_no_cache!, :reload!
     alias_method :locale_no_cache=, :locale=
 
-    LRU_CACHE_SIZE = 300
+    LRU_CACHE_SIZE = 400
 
     def init_accelerator!
       @overrides_enabled = true
@@ -43,7 +43,8 @@ module I18n
           # load plural rules from plugins
           DiscoursePluginRegistry.locales.each do |plugin_locale, options|
             if options[:plural]
-              I18n.backend.store_translations(plugin_locale,
+              I18n.backend.store_translations(
+                plugin_locale,
                 i18n: { plural: options[:plural] }
               )
             end
@@ -94,18 +95,43 @@ module I18n
       @overrides_enabled = true
     end
 
-    def translate_no_override(*args)
-      return translate_no_cache(*args) if args.length > 1 && args[1].present?
+    class MissingTranslation; end
 
-      options  = args.last.is_a?(Hash) ? args.pop.dup : {}
-      key      = args.shift
-      locale   = options[:locale] || config.locale
+    def translate_no_override(key, options)
+      # note we skip cache for :format and :count
+      should_raise = false
+      locale = nil
+
+      dup_options = nil
+      if options
+        dup_options = options.dup
+        should_raise = dup_options.delete(:raise)
+        locale = dup_options.delete(:locale)
+      end
+
+      if dup_options.present?
+        return translate_no_cache(key, options)
+      end
+
+      locale ||= config.locale
 
       @cache ||= LruRedux::ThreadSafeCache.new(LRU_CACHE_SIZE)
       k = "#{key}#{locale}#{config.backend.object_id}"
 
-      @cache.getset(k) do
-        translate_no_cache(key, options).freeze
+      val = @cache.getset(k) do
+        begin
+          translate_no_cache(key, raise: true).freeze
+        rescue I18n::MissingTranslationData
+          MissingTranslation
+        end
+      end
+
+      if val != MissingTranslation
+        val
+      elsif should_raise
+        raise I18n::MissingTranslationData.new(locale, key)
+      else
+        -"translation missing: #{locale}.#{key}"
       end
     end
 
@@ -153,11 +179,16 @@ module I18n
       if @overrides_enabled
         overrides = {}
 
+        # for now lets do all the expensive work for keys with count
+        # no choice really
+        has_override = !!options[:count]
+
         I18n.fallbacks[locale].each do |l|
-          overrides[l] = overrides_by_locale(l)
+          override = overrides[l] = overrides_by_locale(l)
+          has_override ||= override.key?(key)
         end
 
-        if overrides.present?
+        if has_override && overrides.present?
           if options.present?
             options[:overrides] = overrides
 
diff --git a/spec/components/freedom_patches/translate_accelerator_spec.rb b/spec/components/freedom_patches/translate_accelerator_spec.rb
index 9e3de03..ea3427f 100644
--- a/spec/components/freedom_patches/translate_accelerator_spec.rb
+++ b/spec/components/freedom_patches/translate_accelerator_spec.rb
@@ -24,6 +24,15 @@ describe "translate accelerator" do
     expect(override.persisted?).to eq(true)
   end
 
+  it "supports raising if requested, and cache bypasses" do
+    expect { I18n.t('i_am_an_unknown_key99', raise: true) }.to raise_error(I18n::MissingTranslationData)
+
+    orig = I18n.t('i_am_an_unknown_key99')
+
+    expect(I18n.t('i_am_an_unknown_key99').object_id).to eq(orig.object_id)
+    expect(I18n.t('i_am_an_unknown_key99')).to eq("translation missing: en_US.i_am_an_unknown_key99")
+  end
+
   it "overrides for both string and symbol keys" do
     key = 'user.email.not_allowed'
     text_overriden = 'foobar'
@@ -124,6 +133,7 @@ describe "translate accelerator" do
       I18n.overrides_disabled do
         expect(I18n.t('title')).to eq(orig_title)
       end
+
       expect(I18n.t('title')).to eq('overridden title')
     end

GitHub sha: 6d8eb9c1

FIX: Use correct locale when translating without cache