Introduction
Nowadays, I see many sites, which are supporting internationalization, including huge ones like NBA.com, google.com, skype.com 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.
I am Russian and my system default language is English, but popular sites don't care.
Background
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.
PHP
For PHP applications, I would recommend using pear/HTTP2 extension.
<?php
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.
Ruby-on-Rails
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
private
def set_locale
I18n.locale = http_accept_language.compatible_language_from(I18n.available_locales)
end
end
Node.js
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!