Search code examples
ruby-on-railsinternationalizationruby-on-rails-7turbo-rails

Rails Internationalization (I18n) + Turbo Streams: how to change the locale for Turbo Streams?


TL;DR: the components updated with Turbo Streams in my Rails app always use the default locale instead of the currently set locale.

I have a Rails application with multiple engines. I'm implementing the possibility of switching between two languages, but all the HTML rendered via Turbo Stream doesn't respect the locale and it always uses the default locale for translations. I couldn't find anything in the documentation of Turbo Streams about dealing with internationalisation.

Currently I change the locale following the indications in the Rails docs, with an around_action callback to switch_locale:

# app/helpers/application_helper.rb
def switch_locale(&action)
   locale = session[:locale] || params[:locale] || I18n.default_locale
   I18n.with_locale(locale, &action)
end
# app/controllers/application_controller.rb
around_action :switch_locale

I render parts of the HTML calling broadcast_render_to(...) from a controller or a model. For example, the following piece of code is an after_save callback por my PersonalData model. When the model gets updated, it updates the display component, a small box showing a summary of the user's personal data:

# engines/my_engine/app/models/personal_data.rb
 broadcast_render_to(
    "personal_data:#{id}",
     partial: "personal_data_display",
     locals: {
       personal_data: self,
     }
)

And the partial looks like this:

# engines/my_engine/app/views/my_engine_1/personal_data/_personal_data_update.erb
<%= turbo_stream.replace "target-personal-data-display" do %>
  <div id='target-personal-data-display'>
    <%= render MyEngine::Display::PersonalDataComponent.new(personal_data: personal_data) %>
  </div>

My intuition is that I can somehow have a custom controller to execute Turbo Stream actions which also includes the around_action :switch_locale callback. However, I cannot find any documentation or code that would allow me to do that.


Solution

  • In the ApplicationController include the callback before_action :set_locale where the method directly sets I18n.locale:

    def set_locale 
      I18n.locale = params[:locale] || session[:locale] || I18n.default_locale
    end
    

    and get rid of the around_action :switch_locale. Kudos to mate.