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