Question

Using locale in my rails app. I have the following routes.rb

scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
    root to: 'static_pages#home'
    devise_for :users, :controllers => { :registrations => :registrations }

    resources :blogs do
        resources :comments
    end

    get 'tags/:tag', to: 'blogs#index', as: :tag
    resources :users 
    get '/users/subregion_options' => 'users#subregion_options'

    resources "contacts", only: [:new, :create]
    match '/crew',    to: 'static_pages#crew',    via: 'get'

    ....
end



match '*path', to: redirect("/#{I18n.locale}/%{path}"), constraints: lambda { |req| !req.path.starts_with? "/#{I18n.default_locale}/" }, via: 'get' 

I would like the user accessing the page to get redirected to the locale depending on language browser settings (http header). This all works - basically. However, accessing localhost:3000/ application_controller.rb is not being called -therefore the set_locale is not being executed and that means the user ends up with the welcome rails page

How can I force the set_locale to be called?

class ApplicationController < ActionController::Base

    before_filter :set_locale

    def set_locale
      if params[:locale].blank?
        redirect_to "/#{extract_locale_from_accept_language_header}"
      else
        I18n.locale = params[:locale]
      end
    end


private
    def extract_locale_from_accept_language_header
        case request.env['HTTP_ACCEPT_LANGUAGE'].try(:scan, /^[a-z]{2}/).try(:first).try(:to_sym)
      when 'en'
        'en'
      when 'de'
        'de'
      when 'de-at'
        'de'
      when 'de-ch'
        'de'
      else
        'en'
      end

    end

    def default_url_options(options = {})
         {locale: I18n.locale}
   end
Was it helpful?

Solution

I have somehow resolved the issue (not entirely sure if that is the most elegant way), by creating a redirect to trigger set locale:

In my routes.rb I added the following outside the locale scope:

root to: 'static_pages#redirect'

Here the full version

scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
match '',    to: 'static_pages#home', :as => 'home',    via: 'get''
devise_for :users, :controllers => { :registrations => :registrations }

resources :blogs do
    resources :comments
end

get 'tags/:tag', to: 'blogs#index', as: :tag
resources :users 
get '/users/subregion_options' => 'users#subregion_options'

resources "contacts", only: [:new, :create]
match '/crew',    to: 'static_pages#crew',    via: 'get'

....
end

I do have only one root now. I also changed the root_to to match within the locale scope, using :as => home so I can refer to it in link_to from the views as home_path.

So when user enters the xxxx.com - he/she will end up in redirect which does the following:

class StaticPagesController < ApplicationController
  def redirect
    redirect_to home
  end

  def home
  end

Since the locale is blank it will now check for locale in http header and if users preferred language does exist he/she will get directed to the right page/language. For subsequent requests (i.e.: when user clicks a link) the locale will be read out from the URL parameter.

If there's a more elegant solution to this feel free to answer - points are still up for grabs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top