Drupal Multilingual guide (i18n): Language detection by IP

Screen Shot 2013-03-23 at 02.06.08

By default, Drupal’s i18n provides 5 ways to detect user’s preference of language:

User settings

user can set their language on their settings

Screen Shot 2013-03-23 at 02.04.33


Detect user’s browser language and provides the same.


Get the language from the query in url or $_SESSION variable. For example, if your setting is as following:

Screen Shot 2013-03-23 at 01.58.14

This means you can get your language code from url like http://xxx.com/?lang=en,

or you can get your language code from $_SESSION variable. With Devel you can simply dpm($_SESSION) to get what’s inside, and add your code, put the correct language code into it by $_SESSION['lang'] = 'en';. Then dpm again and you get:

Screen Shot 2013-03-23 at 02.03.28


With this detection method checked, all the path on the site will be prefixed a language code.


Site default language.

Customisation using Language Negotiation API

But in my case, none of above work for anonymous users. I prefer users to choose the language in the settings like what Google does, I don’t want the language show on url, but for anonymous users, browser language isn’t the best way to localize my site, I need to detect users’ IP and give them the right content.

Luckily Drupal has a good Language Negotiation API, life is easy! Here’s my codes.

I use Smart IP which tells you users’ country code so it’s easy to get the language code.

First you’ll need to create a module. Say, it’s ip_lang.module.

In ip_lang.info
name = IP Lang description = Using smart ip to get users' country code, then assign the language for them. core = 7.x package = "Custom Modules"   dependencies[] = smart_ip
##### In ip_lang.module
/** * Implements hook_language_negotiation_info(). */function bh_misc_language_negotiation_info(){returnarray('smart_ip'=>array('callbacks'=>array('language'=>'bh_misc_smart_ip_to_language',),'weight'=>-10,'name'=> t('Smart IP'),'file'=> drupal_get_path('module','ip_lang').'/ip_lang.func.inc','description'=> t('Determine the language from the version cookie.'),),);}
##### In ip_lang.func.inc
/** * Callback for hook_language_negotiation_info(). * * @see http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm */function bh_misc_smart_ip_to_language(){switch($_SESSION['smart_ip']['location']['country_code']){case'TW':return'zh-TW';break;case'HK':return'zh-TW';break;default:return'en';break;}}
That’s it! Now we only have 3 languages for 3 regions (Taiwan, Hong Kong and other), this is a way to deeply localize your site without making users get confused about content they shouldn’t be seeing.