mdmb
mdmb

Reputation: 5283

Rails - redirection with locale

I set the basic options for locale in application.rb:

config.i18n.available_locales = [:pl, :en]
config.i18n.default_locale = :pl

And also scoped the routes:

Rails.application.routes.draw do
    get '/:locale', to: 'home#index'
    root            to: 'home#index'

    scope ":locale", locale: /#{I18n.available_locales.join("|")}/  do
      get 'settings', to: 'home#settings'
    end
end

This way I can visit my root site under www.mysite.com and www.mysite.com/en or pl, as well as my settings site when including the locale in the url.

Now let's say user typed www.mysite.com/settings. I want my app to know that there is no locale in the url, so go and grab the default_locale, set it, and redirect to www.mysite.com/pl/settings.

How am I able to do it?

PS I also have added those to my ApplicationController:

before_action :set_locale

    def set_locale
      I18n.locale = params[:locale] || I18n.default_locale
    end

    def default_url_options
      { locale: I18n.locale }
    end

Upvotes: 2

Views: 3500

Answers (2)

Kochka
Kochka

Reputation: 113

Better to redirect to english for root path if the user have no polish in accept-language header even if you redirect other non localized routes to polish.

 # Usefull to parse accept-language header but also for browser detection
 gem 'browser'

In routes.rb :

Rails.application.routes.draw do
  scope ':locale', locale: /#{I18n.available_locales.join('|')}/ do
    # Your routes...

    # Home
    root 'pages#index'
  end

  root 'pages#detect_locale'

  # Catch all requests without a available locale and redirect to the PL default...
  # The constraint is made to not redirect a 404 of an existing locale on itself
  get '*path', to: redirect("/#{I18n.default_locale}/%{path}"), 
               constraints: { path: %r{(?!(#{I18n.available_locales.join('|')})\/).*} }
end

In a controller :

class PagesController < ApplicationController
  def index; end

  # Detect localization preferences
  def detect_locale
    # You can parse yourself the accept-language header if you don't use the browser gem
    languages = browser.accept_language.map(&:code)

    # Select the first language available, fallback to english
    locale = languages.find { |l| I18n.available_locales.include?(l.to_sym) } || :en

    redirect_to root_path(locale: locale)
  end
end

Upvotes: 4

Denis Oster
Denis Oster

Reputation: 11

Rails.application.routes.draw do
  scope ':locale', locale: /#{I18n.available_locales.join("|")}/ do
    root 'users/landing#index'
    get '*path', to: 'users/errors#not_found'
  end
  root to: redirect("/#{I18n.default_locale}", status: 302), as: :redirected_root
  get "/*path", to: redirect("/#{I18n.default_locale}/%{path}", status: 302)
end

Upvotes: 0

Related Questions