[ACCEPTED]-Simplest way to detect client locale in PHP-locale

Accepted answer
Score: 32

PHP provides a function since 5.3.0 to parse 1 the $_SERVER['HTTP_ACCEPT_LANGUAGE'] variable into a locale.

$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
echo $locale; // returns "en_US"

Documentation: https://www.php.net/manual/en/locale.acceptfromhttp.php

Score: 21

Not guaranteed, but most browsers submit 19 an Accept-Language HTTP header that specifies 18 en-us if they're from the US. Some older 17 browsers only said they are en, though. And 16 not all machines are set up correctly to 15 indicate which locale they prefer. But it's 14 a good first guess.

English-UK based-users 13 usually set their system or user locale 12 to English-UK, which in default browser 11 configurations should result in en-gb as 10 the Accept Language header. (An earlier 9 version of this said en-uk; that was a typo, sorry.) Other 8 countries also have en locales, such as 7 en-za (south africa), and, primarily theoretically, combinations 6 like en-jp are also possible.

Geo-IP based 5 guesses will less likely be correct on the 4 preferred language/locale, however. Google 3 thinks that content-negotiation based on 2 IP address geolocation makes sense, which 1 really annoys me when I'm in Japan or Korea...

Score: 13

You can check out the HTTP_ACCEPT_LANGUAGE header (from $_SERVER) that 3 most browsers will send.

Take a look at Zend_Locale for 2 an example, or maybe you might even want 1 to use the lib.

Score: 7

You can do some IP comparaison without having a 10 whole library to do it.

Solution #1

Use an API, this 9 way nothing is needed from your side. This 8 is a web API that let you know the country:

 Example: http://api.hostip.info/get_html.php?ip=
 Return : Country: UNITED STATES (US)

Solution #2

But, Have 7 you think to use the browser agent language? You 6 might be able to know the type of english 5 from it.

Solution #3

This website called BlockCountry let you have 4 a list of IP by country. Of course, you 3 do not want to block, but you can use the 2 list of IP and compare them (get all US 1 IP...) this might not be accurate...

Score: 2

Given your stated purpose, the Accept-Language 3 header is a more suitable solution than 2 IP-based geolocation. Indeed, it's precisely 1 the intended purpose of Accept-Language.

Score: 2

Parse $_SERVER["HTTP_ACCEPT_LANGUAGE"] to get country and browser's locale.


Score: 2


    $localePreferences = explode(",",$_SERVER['HTTP_ACCEPT_LANGUAGE']);
    if(is_array($localePreferences) && count($localePreferences) > 0) {
       $browserLocale = $localePreferences[0];
       $_SESSION['browser_locale'] = $browserLocale;


Score: 1

For identifying your visitors country I've 1 used GeoIP extension, very simple to use.

Score: 0

The http://countries.nerd.dk service is what I use for IP-to-country 5 mapping. It works really well and being 4 based on DNS, is cached well too.

You can 3 also download the database for local use 2 if you don't want to rely on an external 1 service.

Score: 0

GeoIP extension is good choice.


Score: 0

Or you can do the following:

download 'geoip.dat' and 3 geoip.inc from http://www.maxmind.com/app/geoip_country

in geoip.inc header you will 2 find how to use it (eg. initialize and the 1 rest...)

Score: 0

One thing is which language viewer wants, second 6 - which you can serve:

$SystemLocales = explode("\n", shell_exec('locale -a'));
$BrowserLocales = explode(",",str_replace("-","_",$_SERVER["HTTP_ACCEPT_LANGUAGE"])); // brosers use en-US, Linux uses en_US
for($i=0;$i<count($BrowserLocales);$i++) {         
  list($BrowserLocales[$i])=explode(";",$BrowserLocales[$i]); //trick for "en;q=0.8"
  for($j=0;$j<count($SystemLocales);$j++) {
    if ($BrowserLocales[$i]==substr($SystemLocales[$j],0,strlen($BrowserLocales[$i]))){
      setlocale(LC_ALL, $SystemLocales[$j]);
      break 2; // found and set, so no more check is needed

for example, mine 5 system serves only:

  • C
  • pl_PL.UTF-8

and my browser languages 4 are: pl, en-US, en => so the only correct 3 locale is pl_PL.UTF-8.

When no successful 2 comparison is found - there's no setlocale 1 at all.

More Related questions