A Simple Way to Provide Optional Locale Scope in Url

Putting the locale key in the url is a common method to pass in the I18n locale,  see Railscast: http://railscasts.com/episodes/138-i18n-revised

But how do you make the default locale not show up in the url?

i.e. Instead of http://www.example.com/en/some_path (for default :en locale)
I want: http://www.example.com/some_path (for default :en locale)
        & http://www.example.com/cn/some_path (for :cn locale)

----
Without using gems, there is a simple way to do this, simply by changing a few lines in the application controller and routes file. (The following method assumes you followed Railscast's method of setting up the locale scope)

In the routes.rb file, make the locale scope optional:
1
2
3
4
5
6
7
Rails.application.routes.draw do
  scope "(:locale)", locale: /en|cn/ do
    #your paths here
  end

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

In application_controller.rb, change the methods set_locale and default_url_options like so:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :set_locale

  private
    def set_locale
      I18n.locale = (params[:locale].present?) ? params[:locale] : I18n.default_locale
    end
    
    def default_url_options(options = {})
      options.merge!({ :locale => ((I18n.locale == I18n.default_locale) ? nil : I18n.locale) })
    end
end

Now, when the url does not provide a locale key, it will use the default locale; moreover, when browsing under the default locale, the links in your site would not have a locale scope in the url!

Reference:
https://stackoverflow.com/questions/8224245/rails-routes-with-optional-scope-locale

Note:
This is one bit I don't quite understand though:

1
2
3
4
5
    def set_locale
      #somehow, just the line below causes the locale to fluctuate randomly, would like some explanation if known
        I18n.locale = params[:locale] if params[:locale].present? 
        
    end
If someone knows why this happens, I would appreciate your explanation, thank you!

Comments

Popular posts from this blog

I18n Country & City Select Fields - Reconstructing Carmen-Rails from Scratch

(Re: Pagination, You're doing it wrong) - Fixing Duplicate/Missing Records in Infinite Scrolling + Pagination by Hacking the Kaminari Gem

Sending an Email Confirmation Link with the Right Locale (with Devise)