Logo

Your Personal Sysadmin

Redirect

One way to redirect inside the Rails router based on the client’s Accept-Language header.

Previously I thought I had to do this inside the proxy webserver Nginx, only really possible with the LUA-enhanced fork of Openresty, or the selfcompiled Nginx version.

Or to go into the rack middleware world and figure out how to do it there - it’s probably still the fastest, cleanest to do it there.

There are more ways above that: routes file, and of course application controller.

I went for the routes file and added this directive:

root to: redirect { |params, request|

"/#{best_locale_from_request!(request)}"

}, status: 302, as: :redirected_root

The curly braces syntax is obligatory, do/end block does not work.

The actual work is being done with the help of the accept_language gem and these two methods, split up for easier reading i presume:

def best_locale_from_request(request)
	return I18n.default_locale unless request.headers.key?("HTTP_ACCEPT_LANGUAGE")
	string = request.headers.fetch("HTTP_ACCEPT_LANGUAGE")
	locale = AcceptLanguage.parse(string).match(*I18n.available_locales)

	# If the server cannot serve any matching language,
	# it can theoretically send back a 406 (Not Acceptable) error code.
	# But, for a better user experience, this is rarely done and more
	# common way is to ignore the Accept-Language header in this case.

	return I18n.default_locale if locale.nil?
	locale
end

I’ve put them both into the routes file, but there might be a better place for that.

The available locales array grew a bit, in order to prevent edge cases:

# config/application.rb

config.i18n.available_locales = [:en, :"en-150", :"en-001", :"en-DE", :de, :"de-AT", :"de-CH", :"de-DE", :"de-BE", :"de-IT", :"de-LI", :"de-LU", :et, :"et-EE"]

Turns out the gem always forwards the geography part as well, so in order to make sure nobody is left out, I have added this for now. this might become tricky later on as paths are created based on that, and the language switcher might be a bit more tricky. maybe it makes sense to cut the second part off somehow.

Resources

Accept-Language gem: https://github.com/cyril/accept_language.rb

A rack app i did not get to work, but apparently does the i18n settings as well: https://github.com/blindsidenetworks/i18n-language-mapping

This was very helpful for the redirect syntax: https://www.paweldabrowski.com/articles/rails-routes-less-known-features

Hey! I'll happily receive your comments via email

Andreas Wagner
Freelance System Administrator from Tallinn, Estonia.