Why locale setting in Rails acts as global (when using Thin)? Why locale setting in Rails acts as global (when using Thin)? ruby-on-rails ruby-on-rails

Why locale setting in Rails acts as global (when using Thin)?


So now the final answer. TL;DR Setting locale acts as global only when you use threaded web servers, like Thin and Puma.

As I mentioned, I18n.locale=

Sets the current locale pseudo-globally, i.e. in the Thread.current hash

So it is supposed to be per-request, and it works this way in Webrick and Unicorn.

But if you use threaded web server like Thin or Puma, seems that the thread lives longer, and the value is preserved for future requests, until it is changed explicitly. Where I learned it is from the new Steve Klabnik's gem request_store:

If you need global state, you've probably reached for Thread.current.

<...>

So people are using those fancy threaded web servers, like Thin or Puma. But if you use Thread.current, and you use one of those servers, watch out! Values can stick around longer than you'd expect, and this can cause bugs.


Recommended code from above does not set locale globally it sets it by request.

before_filter :set_localedef set_locale  I18n.locale = params[:locale] || I18n.default_localeend

Code is usually place in BaseController so before each page is render it is triggered and set. There is no race conditions since every page will trigger this code and I18n locale will be calculated there. You can expand this to let's say looks for users locale, than session locale, than request params, than uses English.

def set_locale  I18n.locale = @user.locale || session[:locale] || params[:locale] || :enend

In other words if you set local on one page let's say in home controller to german and got to dashboard controller you will see default language (english). Since change is not global. That is why code is placed in base controller. Hope it makes sense.