Click here to Skip to main content
15,791,739 members
Articles / Programming Languages / Ruby

How To Detect User's Locale Right

Rate me:
Please Sign up or sign in to vote.
4.96/5 (8 votes)
17 Nov 2016MIT2 min read 16.6K   8   4
Use HTTP "Accept-Language" Header Instead Of Geo-IP


Nowadays, I see many sites, which are supporting internationalization, including huge ones like,, which are using geo-ip for detecting user locale.

This method is both inaccurate and expensive in terms of computational resources and keeping geo-ip database up-to-date or paying for such services. Even if we ignore VPN users, there would still be a huge number of people, who are enjoying their vacations or going to business trips to other countries. They open favorite web sites and see that content is provided in an unknown language.

Image 1

I am Russian and my system default language is English, but popular sites don't care.


Probably, this issue is not that critical as usually it is quite simple to find and switch locales. The thing is that we as web developers can do much better.

Each http request made by the browser has a special header "Accept-Language", where user locale preferences are provided with weighted values. These preferences are based on user system locale and browser settings. It is highly unlikely that user will set some language, he or she doesn't understand, right? Instead of guessing user's language by geo location, web server can use this header and serve content properly, which is also much cheaper than the geo-ip method. If web server is not able to match any locale, then it would be perfectly fine to fall back to English or some other default locale. If, for some reason, "Accept-Language" header is missing, then it might be also worth falling back to geo-ip locale method, but keep in mind that it is a very rare case.

Using the Code

Below are examples for popular web technology stacks, which perform HTTP "Accept-Language" header parsing and locale detection.


For PHP applications, I would recommend using pear/HTTP2 extension.

  require_once "HTTP2.php";

  $supported = array("de" => true, "en-US" => true);

  $http = new HTTP2();
  echo $http->negotiateLanguage($supported);

This example negotiates with the user agent if any of the languages, which are specified in supported, are supported on the user's system. If the negotiation has a positive result, the language code of the most preferred language is printed. Otherwise, the default language code (en-US) is printed.


For Rails applications, you can use Rack middleware called http_accept_language.
Just add it to your gem list and provide basic configuration in your application.rb, i.e., which locales you are supporting.

class ApplicationController < ActionController::Base
  before_filter :set_locale


  def set_locale
    I18n.locale = http_accept_language.compatible_language_from(I18n.available_locales)



For Node.js applications, I use accept-language package.

import acceptLanguage from 'accept-language';

acceptLanguage.languages(['en-US', 'zh-CN']);

function detectLocale(request) {
  return acceptLanguage.get(request.headers['accept-language']) || 'en';  

Hope this helps to make the Internet slightly better for all of us!


This article, along with any associated source code and files, is licensed under The MIT License

Written By
Software Developer (Senior)
China China
Full stack and mobile senior developer

Comments and Discussions

Question.NET Pin
Ricardo Caltabiano21-Nov-16 10:44
Ricardo Caltabiano21-Nov-16 10:44 
AnswerRe: .NET Pin
Yury Dymov21-Nov-16 23:23
professionalYury Dymov21-Nov-16 23:23 
Questiongood stuff Pin
sosserrurierorleans21-Nov-16 8:17
sosserrurierorleans21-Nov-16 8:17 
Questioncool Pin
Nelek17-Nov-16 11:03
protectorNelek17-Nov-16 11:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.