Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem changing locale with multiple threads #269

Closed
michelboaventura opened this issue Jul 10, 2014 · 6 comments
Closed

Problem changing locale with multiple threads #269

michelboaventura opened this issue Jul 10, 2014 · 6 comments

Comments

@michelboaventura
Copy link

Hi,

I'm having a problem with I18n and multiple threads on a pure ruby app, which can be reproduced with this small script:

require 'i18n'

I18n.available_locales = [:pt, :en]
I18n.enforce_available_locales = true

t1 = Thread.new do
  1.upto(4) do
    puts I18n.t(:foo)
    sleep 1
  end
end

sleep 1 #<<<THIS

I18n.default_locale = :pt
I18n.locale = :pt

t1.join

The problem is: If I run this, I got as output four translation missing: en.foo, but if I remove the sleep marked on the code, I got four translation missing: pt.foo.

I'm aware that the four messages for the pt make sense, since the locale change happens before the thread runs, but I think that on the first case it should print some messages on en and some on pt (the amount of each would be not deterministic).

This is a expected behavior?

@carlosantoniodasilva
Copy link
Member

I'll try to verify your script and the issue tomorrow. Thanks for reporting.

@michelboaventura
Copy link
Author

Thank you Carlos,

I forgot to mention, this happens on master too and my ruby is:

ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux]

@arthurnn
Copy link
Contributor

As far as I can tell , default_locale is not thread safe https://github.com/tjgfernandes/i18n/blob/master/lib/i18n/config.rb#L35 so changing it in one thread, would affect the others. I guess this is done by design.

@michelboaventura
Copy link
Author

On this same file, the comment on lines 5 and 6 says that :locale is the only config scoped to a specific thread, so I assumed that default_locale is a global, and all threads should respect it.

If this is by design, we should think a way to change locale to every single thread. This is useful on a GUI software which has several threads running and a user changes the default locale.

@boazsegev
Copy link

The issue is still unresolved.

The source of the issue, as it seems from my testing, is that I18n stores the settings in the thread's variable using: Thread.current[:i18n_config].

As you can see in the source code, the settings are persistent. The default_locale isn't reviewed again after it had been reviewed for the first time.

The solution would probably be to change the I18n::Config class's #locale method to keep accessing the default_locale (replacing the ||= with ||), like so:

@locale || default_locale

An easy workaround is to manually reset the locale to the default locale each time.

Here is the code I used for testing:

require 'i18n'

I18n.available_locales = [:pt, :en]
I18n.enforce_available_locales = true
I18n.default_locale = :en

# t1 = Thread.new do
#   1.upto(4) do
#     Thread.current[:i18n_config] = nil
#     puts I18n.t(:foo)
#     puts Thread.current.keys
#     sleep 1
#   end
# end

t1 = Thread.new do
  1.upto(4) do
    I18n.locale = I18n.default_locale
    puts I18n.t(:foo)
    sleep 1
  end
end

sleep 0.1 #<<<THIS

I18n.default_locale = :pt

t1.join

@radar
Copy link
Collaborator

radar commented Nov 15, 2016

I've added the fix from #320 to master now, which should fix this issue. Thanks everyone!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants