Rails somehow mixes my locales an I have absolutely no clue why. Most of my translated strings work as expected, but for some it mixes the locales.
Interestingly, this only happens on one of our systems. Specifically running Passenger with Apache.
When using Webrick, Thin, or Passenger Standalone on my development system everything is alright.
This is what I have in my application.rb
:
config.i18n.default_locale = :de
This is in application_controller.rb
:
before_filter :set_locale
def set_locale
I18n.locale = @current_client ? @current_client.locale : I18n.default_locale
end
(I experience the problems on pages where @current_client
is nil
and the else
part gets executed).
So, I am basically using the :de
locale. When showing a validation error on a form, I experience mixed up translations like this:
ist zu kurz (nicht weniger als 6 Zeichen) und translation missing: en.activerecord.errors.custom.password_format
As you can see, the error message from the first failing validation is translated as expected, for the second error message tries to access the English translation (which does not exist).
I suspect a problem with lazy loading of translated strings even before the before_filter
gets executed.
Any clues why this might happen?
For the record: This is Rails 3
EDIT:
I just discovered that this depends on the environment used. When using the development environment, everything is fine. When using the production environment (or a production-like) environment, I experience the behavior described above.
EDIT 2:
I found out even more: It specifically depends on config.cache_classes
. When set to true
, I see the mixed translations. When set to false
(as in the typical development environment), i18n works as expected.
EDIT 3:
Maybe this is related to the following bug?
https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/5522
Edit 4:
This IS related to the bug mentioned above, the problem is due to eagerly loaded model classes, which use I18n strings, but eager class loading happens before I18n initialization, hence the translations are not found. There even is another bug about this:
https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/6353
Unfortunately, the Rails guys did not manage to include the fix in the recent 3.0.4 release (as far as I can tell). Hence I'm trying to figure out a workaround like this (in my application configuration):
config.before_eager_load do
I18n.load_path += Dir[Rails.root.join('config', 'locales', 'de.yml').to_s]
I18n::Railtie.reloader.paths.concat I18n.load_path
I18n::Railtie.reloader.execute_if_updated
I18n.reload!
end
Unlucky, this does not work. Any clues?
This problem may also occours in case you have a Gem that also uses I18n (I was having this problem with active_admin). Rails sets I18n to late for the Gem to be able to use that same load_paths.
What I have done was to add this to production.rb:
config.before_configuration do
I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}').to_s]
I18n.locale = 'pt-PT'
I18n.reload!
end
Here is my final workaround, which seems to work (put this in application.rb
or one of your environment configuration files, as needed):
# THIS IS A WORKAROUND FOR A I18N BUG IN RAILS!
# Only required when cache_classes is set to true
# See https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/6353
config.before_eager_load do
I18n.locale = :de
I18n.load_path += Dir[Rails.root.join('config', 'locales', 'de.yml').to_s]
I18n.reload!
end
Hope this is useful to anybody else...
EDIT:
If this does not work for you, try before_configuration
instead of before_eager_load
(see solution below). At least, works again as workaround for me in Rails 3.0.10
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With