enriclluelles/route_translator

Bug: host_locales does not set the locale

Closed this issue · 5 comments

Bug description

Hello,

I would like to report an issue related to host_locales property.

I followed the guide and configured host_locales in route_translator.rb as shown below:

  ...
  config.host_locales = {
    "*.pl"                 => :pl,
    "*.de"                 => :de,
    "*.cz"                 => :cz
  }
  ...

Unfortunately, after starting the server and visiting a controller with a single action - index, which renders the value of locale, I noticed that the value did not change despite the above configuration. To solve the problem, it was necessary to apply a workaround in the ApplicationController:

class ApplicationController < ActionController::Base
  before_action :set_locale

  private

  def set_locale
    case request.host
    when /\.pl\z/
      I18n.locale = :pl
    when /\.de\z/
      I18n.locale = :de
    when /\.cz\z/
      I18n.locale = :cz
    else
      I18n.locale = I18n.default_locale
    end
  end
end

The problem - config.host_locales does not set the locale.

Steps to reproduce

  1. Update your /etc/hosts file:
127.0.0.1 abc.my-domain.pl
127.0.0.1 abc.my-domain.de
127.0.0.1 abc.my-domain.cz
  1. Install Ruby on Rails 8
  2. Add the configuration to development.rb file:
  config.hosts.concat(%w[
    abc.my-domain.pl
    abc.my-domain.de
    abc.my-domain.cz
  ])
  1. Add route_translator gem
  2. Run bundle install
  3. Run bundle exec rails g route_translator:install
  4. Configure the gem:
...
  config.host_locales = {
    "*.pl"                 => :pl,
    "*.de"                 => :de,
    "*.cz"                 => :cz
  }
  config.hide_locale = true
...
  1. Run rails g controller products
  2. Add one action to ProductsController - index
  3. Create translation files for two languages, de and cz:
de:
  routes:
    products: produkte

and

cz:
  routes:
    products: produkty
  1. Create following views for de (index.de.html.erb) and cz (index.cz.html.erb) language:
view: index.de.html.erb
<br />
locale: <%= I18n.locale %>

and

view: index.cz.html.erb
<br />
locale: <%= I18n.locale %>
  1. Create a default view (index.html.erb):
view: index.html.erb
<br />
locale: <%= I18n.locale %>
  1. Run ./bin/dev
  2. Visit http://abc.my-domain.de:3000/produkte
  3. Visit http://abc.my-domain.cz:3000/produkty

Expected behavior

When I visit http://abc.my-domain.de:3000/produkte I would like to see this in the view:

view: index.de.html.erb
locale: de

When I visit http://abc.my-domain.cz:3000/produkty I would like to see this in the view:

view: index.cz.html.erb
locale: cz

Actual behavior

When I visit http://abc.my-domain.de:3000/produkte I see this in the view:

view: index.html.erb
locale: en

When I visit http://abc.my-domain.cz:3000/produkty I see this in the view:

view: index.html.erb
locale: en

Reproducible reduced test case

No response

Ruby version

3.3.5

Ruby on Rails version

8.0

Route Translator version

14.2.0

I18n configuration

No custom configuration

Route Translator configuration

  config.host_locales = {
    "*.pl"                 => :pl,
    "*.de"                 => :de,
    "*.cz"                 => :cz
  }
  config.hide_locale = true

Rails routes source

...
localized do
    resources :products
end
...

Rails locales

de:
  routes:
    products: produkte

cz:
  routes:
    products: produkty

Rails routes

                             products_cz GET    /produkty(.:format)                                                                               products#index {:locale=>"cz"}
                             products_de GET    /produkte(.:format)                                                                               products#index {:locale=>"de"}
                             products_pl GET    /produkty(.:format)                                                                               products#index {:locale=>"pl"}
                             products_en GET    /products(.:format)                                                                               products#index {:locale=>"en"}
                                         POST   /produkty(.:format)                                                                               products#create {:locale=>"cz"}
                                         POST   /produkte(.:format)                                                                               products#create {:locale=>"de"}
                                         POST   /produkty(.:format)                                                                               products#create {:locale=>"pl"}
                                         POST   /products(.:format)                                                                               products#create {:locale=>"en"}
                          new_product_cz GET    /produkty/new(.:format)                                                                           products#new {:locale=>"cz"}
                          new_product_de GET    /produkte/new(.:format)                                                                           products#new {:locale=>"de"}
                          new_product_pl GET    /produkty/new(.:format)                                                                           products#new {:locale=>"pl"}
                          new_product_en GET    /products/new(.:format)                                                                           products#new {:locale=>"en"}
                         edit_product_cz GET    /produkty/:id/edit(.:format)                                                                      products#edit {:locale=>"cz"}
                         edit_product_de GET    /produkte/:id/edit(.:format)                                                                      products#edit {:locale=>"de"}
                         edit_product_pl GET    /produkty/:id/edit(.:format)                                                                      products#edit {:locale=>"pl"}
                         edit_product_en GET    /products/:id/edit(.:format)                                                                      products#edit {:locale=>"en"}
                              product_cz GET    /produkty/:id(.:format)                                                                           products#show {:locale=>"cz"}
                              product_de GET    /produkte/:id(.:format)                                                                           products#show {:locale=>"de"}
                              product_pl GET    /produkty/:id(.:format)                                                                           products#show {:locale=>"pl"}
                              product_en GET    /products/:id(.:format)                                                                           products#show {:locale=>"en"}
                                         PATCH  /produkty/:id(.:format)                                                                           products#update {:locale=>"cz"}
                                         PATCH  /produkte/:id(.:format)                                                                           products#update {:locale=>"de"}
                                         PATCH  /produkty/:id(.:format)                                                                           products#update {:locale=>"pl"}
                                         PATCH  /products/:id(.:format)                                                                           products#update {:locale=>"en"}
                                         PUT    /produkty/:id(.:format)                                                                           products#update {:locale=>"cz"}
                                         PUT    /produkte/:id(.:format)                                                                           products#update {:locale=>"de"}
                                         PUT    /produkty/:id(.:format)                                                                           products#update {:locale=>"pl"}
                                         PUT    /products/:id(.:format)                                                                           products#update {:locale=>"en"}
                                         DELETE /produkty/:id(.:format)                                                                           products#destroy {:locale=>"cz"}
                                         DELETE /produkte/:id(.:format)                                                                           products#destroy {:locale=>"de"}
                                         DELETE /produkty/:id(.:format)                                                                           products#destroy {:locale=>"pl"}
                                         DELETE /products/:id(.:format)                                                                           products#destroy {:locale=>"en"}

Bug report checklist

  • I have searched for existing issues and to the best of my knowledge this is not a duplicate
  • I understand that debugging Route Translator is a time consuming task, and I have carefully provided all the information requested

Hi!

Thanks for being part of the Route Translator Community.

I don't know when I will have time to take a look here, because route translator issues are time consuming to review, however

before_action :set_locale

I strongly suggest to avoid this, because the locale will leak to other requests: Route Translator's current implementation, with around_action, is the correct one. Ref: #44

Please also post your controller code, or better, please host on github a test application showing the issue

Hi,

Thank you for your response! I appreciate it!

Please have a look at the repository https://github.com/staskolukasz/route-translator-test
I recommend you to go through commits section - I tried to keep them sweet and short.

In README.md file there is an instruction how to setup the application.

Also thank you for the great tip regarding #44 - I will adjust my code.

Hello,

https://github.com/staskolukasz/route-translator-test/blob/main/app/controllers/application_controller.rb

After a fast look at the application controller, I'm not seeing

around_action :set_locale_from_url

From readme:

  1. If you want to set I18n.locale from the url parameter locale, add
    the following line in your ApplicationController or in the controllers
    that have translated content:
around_action :set_locale_from_url

Note: you might be tempted to use before_action instead of around_action: just don't. That could lead to thread-related issues.

Ref: https://github.com/enriclluelles/route_translator?tab=readme-ov-file#quick-start

Sir, you are right.

Added around_action as you suggested and everything's good now.
I don't know how I can thank you - just starred the project.

I'm closing the issue.

Glad you solved