I want to set the locale by the clients browserlocale request.env['HTTP_ACCEPT_LANGUAGE']
and by the URL.
If a user visits a URL (e.g.: myapp.com) it should check the HTTP_ACCEPT_LANGUAGE
and redirect to the right URL (e.g.: myapp.com/en - if the browserlocale
is en)
If a user then chooses a different language via a language-menu it should change the URL to e.g.: myapp.com/de.
Here is my what I got so far:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :set_locale
private
# set the language
def set_locale
if params[:locale].blank?
I18n.locale = extract_locale_from_accept_language_header
else
I18n.locale = params[:locale]
end
end
# pass in language as a default url parameter
def default_url_options(options = {})
{locale: I18n.locale}
end
# extract the language from the clients browser
def extract_locale_from_accept_language_header
browser_locale = request.env['HTTP_ACCEPT_LANGUAGE'].try(:scan, /^[a-z]{2}/).try(:first).try(:to_sym)
if I18n.available_locales.include? browser_locale
browser_locale
else
I18n.default_locale
end
end
end
In my routes file I got:
Myapp::Application.routes.draw do
# set language path
scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
root :to => "mycontrollers#new"
...
end
match '*path', to: redirect("/#{I18n.locale}/%{path}"), constraints: lambda { |req| !req.path.starts_with? "/#{I18n.default_locale}/" }
match '', to: redirect("/#{I18n.locale}")
end
The Problem is that the routesfile gets executed first and the HTTP_ACCEPT_LANGUAGE
has no effect, because the url-param already got set when it comes to the controller.
Does anyone has a solution for that? Maybe solve it by a middleware?
I'd change a few things in your routes.
First:
scope :path => ":locale" do
...
end
Second:
I see what you are trying to do here:
match '', to: redirect("/#{I18n.locale}")
It seems redundant though.
I'd get rid of that line and just modify the set_locale method, like this:
# set the language
def set_locale
if params[:locale].blank?
redirect_to "/#{extract_locale_from_accept_language_header}"
else
I18n.locale = params[:locale]
end
end