Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixed locales in Rails i18n

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?

like image 779
tbk Avatar asked Feb 03 '11 10:02

tbk


2 Answers

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
like image 157
fkreusch Avatar answered Nov 20 '22 08:11

fkreusch


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

like image 44
tbk Avatar answered Nov 20 '22 06:11

tbk