Rails: i18n – Set Locale from Client Browser Settings

[Reading time: 2mn]

Introduction
So your Rails site has been i18n’d (internationalized), and when a user comes by, you would like to display it in the language reported by her browser. How do you do that?

Setting
Rails 3.0.5
Ruby 1.9.2-p180

How does it work?
From the related Rails i18n guide (http://guides.rubyonrails.org/i18n.html), you do something like this.

def set_locale
  logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
  I18n.locale = extract_locale_from_accept_language_header
  logger.debug "* Locale set to '#{I18n.locale}'"
end
private
def extract_locale_from_accept_language_header
  request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
end

Simple enough. Okay, but where do you put such code?

User Session Initialization
Ideally, session initialization is where you’d put it because, a session starts with a user visiting your website. Mind you, I couldn’t find the place when session initialization occurs in Rails, or an observer for it. Searching it via Google resulted in almost nothing.
So, I decided to put this code in a before_filter for the Application Controller. To me, it means it’ll get fired for every page visited so multiple times during the user session. It’s still not a good option. What you can do is actually to record the start of the session in some variable.
Here you go:

class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :set_locale_from_browser
def set_locale_from_browser
  if (session[:initialized].nil? || !session[:initialized])
    logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
    I18n.locale = extract_locale_from_accept_language_header
    logger.debug "* Locale set to '#{I18n.locale}'"
  else
    logger.debug "* Locale already set to '#{I18n.locale}'"
  endsession[:initialized] = true
end
private
def extract_locale_from_accept_language_header
  request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
end
end

Leave a Reply

Your email address will not be published. Required fields are marked *