Browse files

Make i18n fallbacks configurable and fallback to the default locale b…

…y default in production [#4428 state:resolved]

Allows to configure locale fallbacks through config.i18n.fallbacks. The default setting
config.i18n.fallbacks = true in production.rb will make I18n.t lookup fallback to the
I18n.default_locale if a translation could not be found for the current or given locale.

config.fallbacks = true

config.fallbacks.map = { :ca => :es }
config.fallbacks.defaults = [:'es-ES', :es]

config.fallbacks = [:'es-ES', :es]

config.fallbacks = { :ca => :es }

config.fallbacks = [:'es-ES', :es, { :ca => :es }]

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
  • Loading branch information...
1 parent b7693dc commit 9a3a4d6aefa7e2ca94340754eb5541bea1783de0 @svenfuchs svenfuchs committed with lifo Apr 16, 2010
View
35 activesupport/lib/active_support/railtie.rb
@@ -33,6 +33,7 @@ class Railtie < Rails::Railtie
config.i18n = ActiveSupport::OrderedOptions.new
config.i18n.railties_load_path = []
config.i18n.load_path = []
+ config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
initializer "i18n.initialize" do
ActiveSupport.on_load(:i18n) do
@@ -53,12 +54,46 @@ class Railtie < Rails::Railtie
app.config.i18n.load_path.unshift(*value)
when :load_path
I18n.load_path += value
+ when :fallbacks
+ init_fallbacks(value) if value && validate_fallbacks(value)
else
I18n.send("#{setting}=", value)
end
end
I18n.reload!
end
+
+ class << self
+ protected
+
+ def init_fallbacks(fallbacks)
+ include_fallbacks_module
+ args = case fallbacks
+ when ActiveSupport::OrderedOptions
+ [*(fallbacks[:defaults] || []) << fallbacks[:map]].compact
+ when Hash, Array
+ Array.wrap(fallbacks)
+ else # TrueClass
+ []
+ end
+ I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
+ end
+
+ def include_fallbacks_module
+ I18n.backend.class.send(:include, I18n::Backend::Fallbacks)
+ end
+
+ def validate_fallbacks(fallbacks)
+ case fallbacks
+ when ActiveSupport::OrderedOptions
+ !fallbacks.empty?
+ when TrueClass, Array, Hash
+ true
+ else
+ raise "Unexpected fallback type #{fallbacks.inspect}"
+ end
+ end
+ end
end
end
View
4 railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -39,4 +39,8 @@
# Enable threaded mode
# config.threadsafe!
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation can not be found)
+ config.i18n.fallbacks = true
end
View
86 railties/test/railties/i18n_railtie_test.rb
@@ -0,0 +1,86 @@
+require "isolation/abstract_unit"
+
+module RailtiesTest
+ class I18nRailtieTest < Test::Unit::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app
+ boot_rails
+ FileUtils.rm_rf("#{app_path}/config/environments")
+ require "rails/all"
+ @old_path = I18n.load_path
+ end
+
+ def teardown
+ I18n.load_path = @old_path || []
+ I18n.backend = nil
+ end
+
+ def load_app
+ require "#{app_path}/config/environment"
+ end
+
+ def assert_fallbacks(fallbacks)
+ fallbacks.each do |locale, expected|
+ actual = I18n.fallbacks[locale]
+ assert_equal expected, actual, "expected fallbacks for #{locale.inspect} to be #{expected.inspect}, but were #{actual.inspect}"
+ end
+ end
+
+ def assert_no_fallbacks
+ assert !I18n.backend.class.included_modules.include?(I18n::Backend::Fallbacks)
+ end
+
+ test "config.i18n.load_path gets added to I18n.load_path" do
+ I18n.load_path = ['existing/path/to/locales']
+ I18n::Railtie.config.i18n.load_path = ['new/path/to/locales']
+ load_app
+
+ assert I18n.load_path.include?('existing/path/to/locales')
+ assert I18n.load_path.include?('new/path/to/locales')
+ end
+
+ test "not using config.i18n.fallbacks does not initialize I18n.fallbacks" do
+ I18n.backend = Class.new { include I18n::Backend::Base }.new # can't uninclude modules, so use a tmp backend class
+ load_app
+ assert_no_fallbacks
+ end
+
+ test "config.i18n.fallbacks = true initializes I18n.fallbacks with default settings" do
+ I18n::Railtie.config.i18n.fallbacks = true
+ load_app
+ assert_fallbacks :de => [:de, :en]
+ end
+
+ test "config.i18n.fallbacks.defaults = [:'en-US'] initializes fallbacks with en-US as a fallback default" do
+ I18n::Railtie.config.i18n.fallbacks.defaults = [:'en-US']
+ load_app
+ assert_fallbacks :de => [:de, :'en-US', :en]
+ end
+
+ test "config.i18n.fallbacks.map = { :ca => :'es-ES' } initializes fallbacks with a mapping ca => es-ES" do
+ I18n::Railtie.config.i18n.fallbacks.map = { :ca => :'es-ES' }
+ load_app
+ assert_fallbacks :ca => [:ca, :"es-ES", :es, :en]
+ end
+
+ test "[shortcut] config.i18n.fallbacks = [:'en-US'] initializes fallbacks with en-US as a fallback default" do
+ I18n::Railtie.config.i18n.fallbacks = [:'en-US']
+ load_app
+ assert_fallbacks :de => [:de, :'en-US', :en]
+ end
+
+ test "[shortcut] config.i18n.fallbacks = [{ :ca => :'es-ES' }] initializes fallbacks with a mapping de-AT => de-DE" do
+ I18n::Railtie.config.i18n.fallbacks.map = { :ca => :'es-ES' }
+ load_app
+ assert_fallbacks :ca => [:ca, :"es-ES", :es, :en]
+ end
+
+ test "[shortcut] config.i18n.fallbacks = [:'en-US', { :ca => :'es-ES' }] initializes fallbacks with the given arguments" do
+ I18n::Railtie.config.i18n.fallbacks = [:'en-US', { :ca => :'es-ES' }]
+ load_app
+ assert_fallbacks :ca => [:ca, :"es-ES", :es, :'en-US', :en]
+ end
+ end
+end

0 comments on commit 9a3a4d6

Please sign in to comment.