I have a multi-country Rails app. And I need to set per request i18n fallbacks schema. Is it possible and how to achieve this?
UPD
class Country < ApplicationRecord
# String attribute "languages" (array)
end
class CountriesController < ApplicationController
def show
@country = Country.find params[:id]
I18n.fallbacks = {
@country.languages.first => @country.languages.second
} # This does not work
render 'show'
end
end
Experimenting a bit (with Rails 6), it is possible to change the fallbacks using the Simple (default) backend, but doing so is not thread-safe and will likely cause problems if you do it on a per-request basis. It's somewhat counter-intuitive -- setting I18n.locale
is the documented way to dynamically set locale per request, so it's natural to assume fallbacks would work the same way. However, from the the i18n
source:
The only configuration value that is not global and scoped to thread is :locale.
Even that isn't very clearly worded. But indeed locale
is defined as an instance variable, and all other configuration attributes are @@
class variables.
The Rails guide for I18n says that the Simple (default) backend was designed to only do the "simplest thing that could possibly work", but the framework allows for plugging in custom backends that go beyond that. So, the best way for you to achieve your result will be to find (or create) a backend that supports per-request fallbacks in a thread-safe way.
For reference, if someone does need to change a language fallback outside the initializer (again, that's globally), fallbacks.map()
does that:
I18n.fallbacks.map(:ca => :"es-ES")
My original answer mentioned fiddling with the fallback
hash directly, but using .map()
preserves falling back to the default locale.