Coding with Jesse

Parse Accept-Language to detect a user's language

I'm an English-speaking Canadian living in Germany. Quite often I go to a website like Google or Kayak and find myself looking at a German version of the site.

Okay, I do live in Germany, but why assume that everyone within Germany speaks German? What about visitors from other countries, or even people living here that would prefer to use another language?

What must be happening is these sites are taking my IP address, looking up the geographical location of that address, and choosing the official language for that country. This may work most of the time, but there is an even easier way to choose a language.

Most browsers send an Accept-Language header. For example, mine is set to:


What this basically says is that I prefer (in decreasing order of preference) Canadian English, generic English, US English, German spoken in Germany, and lastly generic German. Any web site I visit is capable of looking at this list and deciding what language I would prefer.

Of course, no matter what assumptions you make about a visitor, give them a chance to change their language if needed. For example, if you use an Internet cafe in Berlin, you shouldn't be stuck viewing websites in German!

One really nice thing: I often see Google Ads and other geographically targeted ads in German, and this makes ignoring the ads much easier! :)

Update: I was inspired to throw together a quick Accept-Language parser in PHP:

$langs = array();

    // break up string into pieces (languages and q factors)
    preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);

    if (count($lang_parse[1])) {
        // create a list like "en" => 0.8
        $langs = array_combine($lang_parse[1], $lang_parse[4]);
        // set default to 1 for any without q factor
        foreach ($langs as $lang => $val) {
            if ($val === '') $langs[$lang] = 1;

        // sort list based on value	
        arsort($langs, SORT_NUMERIC);

// look through sorted list and use first one that matches our languages
foreach ($langs as $lang => $val) {
	if (strpos($lang, 'de') === 0) {
		// show German site
	} else if (strpos($lang, 'en') === 0) {
		// show English site

// show default site or prompt for language

This would produce the following structure for my Accept-Language string:

    [en-ca] => 1
    [en] => 0.8
    [en-us] => 0.6
    [de-de] => 0.4
    [de] => 0.2

Published on May 4th, 2008. © Jesse Skinner

About the author

Jesse Skinner Hi, I'm Jesse Skinner. I'm a web development coach focused on reducing developer burnout. I work with web development teams to reduce stress through automated testing and deployment, scalable infrastructure, and the modernization of painful legacy systems.

Through customized training and coaching, I empower teams to adopt new technologies to improve their workflows and make work more enjoyable. Feel free to email me. I'm eager to hear about your challenges and see how I can make your life easier.