Question

I have this locale switcher in my Rails 4 application:

class LocalesController < ApplicationController

  def change_locale
    if params[:set_locale]
      session[:locale] = params[:set_locale]
      redirect_to(:back, :locale => params[:set_locale])
    end
  end

end

Everything works fine except that the new locale is not shown in the URL when the user switches the locale.

For example, when I'm on the page /de/faq and then click English in the drop down menu, the content of the page switches to English (and I guess the session also adjusts to English), however the URL remains /de/faq. Only the next click after that will make the locale in the URL adjust to /en/....

It would be nice, though, if the locale change would be reflected in the URL instantly.

How can this be done?

Was it helpful?

Solution

redirect_to :back do not accept any additional params, as it will use the url supplied by the request headers. You should probably do:

url_hash = Rails.application.routes.recognize_path URI(request.referer).path
url_hash[:locale] = params[:set_locale]
redirect_to url_hash

Explanation:

Rails.application.routes.recognize_path URI(request.referer).path

This line takes the referer url (this is the url the request comes from and it is used when you call redirect_to :back). Then it is parsed with URI to extract the path alone, like /de/faq.

Having the path we are using Rails plumbing function recognize_path. This method uses your routes to translate given path into a hash like {controller: 'MyController', action: 'my_action', param: 'my_param', ... }. Since your route includes locale in the URL, the locale used in referrer URL will be accessible in this hash under :locale key.

Now the second line is just to change the value of :locale in this hash to whatever value of locale has been passed. Then if you do redirect with this hash, rails will use this hash to generate the URL from it, which will be exactly same as referer URL except for locale.

Most likely you still need to use the session to store the locale.

OTHER TIPS

You can also create an helper and add uri.query to keep the params:

def redirect_back_with_locale(locale)
  uri = URI(request.referer)
  url_hash = Rails.application.routes.recognize_path(uri.path)
  url_hash[:locale] = locale
  redirect_to [url_for(url_hash), uri.query].compact.join('?')
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top