174

I use the following PHP script as index for my website.

This script should include a specific page depending on the browser's language (automatically detected).

This script does not work well with all browsers, so it always includes index_en.php for any detected language (the cause of the problem is most probably an issue with some Accept-Language header not being considered).

Could you please suggest me a more robust solution?

<?php
// Open session var
session_start();
// views: 1 = first visit; >1 = second visit

// Detect language from user agent browser
function lixlpixel_get_env_var($Var)
{
     if(empty($GLOBALS[$Var]))
     {
         $GLOBALS[$Var]=(!empty($GLOBALS['_SERVER'][$Var]))?
         $GLOBALS['_SERVER'][$Var] : (!empty($GLOBALS['HTTP_SERVER_VARS'][$Var])) ? $GLOBALS['HTTP_SERVER_VARS'][$Var]:'';
     }
}

function lixlpixel_detect_lang()
{
     // Detect HTTP_ACCEPT_LANGUAGE & HTTP_USER_AGENT.
     lixlpixel_get_env_var('HTTP_ACCEPT_LANGUAGE');
     lixlpixel_get_env_var('HTTP_USER_AGENT');

     $_AL=strtolower($GLOBALS['HTTP_ACCEPT_LANGUAGE']);
     $_UA=strtolower($GLOBALS['HTTP_USER_AGENT']);

     // Try to detect Primary language if several languages are accepted.
     foreach($GLOBALS['_LANG'] as $K)
     {
         if(strpos($_AL, $K)===0)
         return $K;
     }

     // Try to detect any language if not yet detected.
     foreach($GLOBALS['_LANG'] as $K)
     {
         if(strpos($_AL, $K)!==false)
         return $K;
     }
     foreach($GLOBALS['_LANG'] as $K)
     {
         //if(preg_match("/[[( ]{$K}[;,_-)]/",$_UA)) // matching other letters (create an error for seo spyder)
         return $K;
     }

     // Return default language if language is not yet detected.
     return $GLOBALS['_DLANG'];
}

// Define default language.
$GLOBALS['_DLANG']='en';

// Define all available languages.
// WARNING: uncomment all available languages

$GLOBALS['_LANG'] = array(
'af', // afrikaans.
'ar', // arabic.
'bg', // bulgarian.
'ca', // catalan.
'cs', // czech.
'da', // danish.
'de', // german.
'el', // greek.
'en', // english.
'es', // spanish.
'et', // estonian.
'fi', // finnish.
'fr', // french.
'gl', // galician.
'he', // hebrew.
'hi', // hindi.
'hr', // croatian.
'hu', // hungarian.
'id', // indonesian.
'it', // italian.
'ja', // japanese.
'ko', // korean.
'ka', // georgian.
'lt', // lithuanian.
'lv', // latvian.
'ms', // malay.
'nl', // dutch.
'no', // norwegian.
'pl', // polish.
'pt', // portuguese.
'ro', // romanian.
'ru', // russian.
'sk', // slovak.
'sl', // slovenian.
'sq', // albanian.
'sr', // serbian.
'sv', // swedish.
'th', // thai.
'tr', // turkish.
'uk', // ukrainian.
'zh' // chinese.
);

// Redirect to the correct location.
// Example Implementation aff var lang to name file
/*
echo 'The Language detected is: '.lixlpixel_detect_lang(); // For Demonstration
echo "<br />";    
*/
$lang_var = lixlpixel_detect_lang(); //insert lang var system in a new var for conditional statement
/*
echo "<br />";    

echo $lang_var; // print var for trace

echo "<br />";    
*/
// Insert the right page iacoording with the language in the browser
switch ($lang_var){
    case "fr":
        //echo "PAGE DE";
        include("index_fr.php");//include check session DE
        break;
    case "it":
        //echo "PAGE IT";
        include("index_it.php");
        break;
    case "en":
        //echo "PAGE EN";
        include("index_en.php");
        break;        
    default:
        //echo "PAGE EN - Setting Default";
        include("index_en.php");//include EN in all other cases of different lang detection
        break;
}
?>
GibboK
  • 71,848
  • 143
  • 435
  • 658
  • 6
    PHP 5.3.0+ comes with `locale_accept_from_http()` which gets the preferred language from the `Accept-Language` header. You should always prefer this method to a self-written method. Check the result against a list of regular expressions that you try and determine the page language that way. See [PHP-I18N](https://github.com/delight-im/PHP-I18N/blob/master/classes/I18N.php) for an example. – caw Jul 04 '14 at 20:41
  • 3
    The problem with `locale_accept_from_http()` is that you may not support the best result it returns so you still have the [parse the header yourself](https://gist.github.com/Xeoncross/dc2ebf017676ae946082) to find the *next-best*. – Xeoncross Sep 09 '14 at 16:39
  • The accepted answer to this should be changed to one of those that take multiple languages into account. – Pekka Jul 23 '18 at 18:26
  • include and require's are happen at the compile time of php so basically you include all the index*.php and show only one - waste of ressources – Michael Jul 21 '19 at 11:15
  • Besides from the real question and regarding the code above, I'd not recommend using different index pages for every language. An user would be happy to see same page layout and content in each language. You only have to load appropriate texts/pics inside one index.php page. The content can be organized e.g. in one XML file like [item]->[lang] sections -
    item[0]->lang[0]; ?>
    , or in SQL, etc.
    – Hristo Apr 28 '22 at 18:18

16 Answers16

409

why dont you keep it simple and clean

<?php
    $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
    $acceptLang = ['fr', 'it', 'en']; 
    $lang = in_array($lang, $acceptLang) ? $lang : 'en';
    require_once "index_{$lang}.php"; 

?>
Mimouni
  • 3,564
  • 3
  • 28
  • 37
Pramendra Gupta
  • 14,667
  • 4
  • 33
  • 34
  • Just a questions in case SESSION on the server are disable script could work? thanks – GibboK Sep 22 '10 at 16:37
  • 11
    Dutch, Greek and Slovenian's language codes are one letter. It seems better to explode like this: http://www.php.net/manual/tr/reserved.variables.server.php#90293 – trante May 20 '12 at 10:19
  • 13
    @trante: Why do you say they are one letter? Dutch (`nl`), Greek (`el`) and Slovenian (`sl`) all appear to be two letter: http://msdn.microsoft.com/en-us/library/ms533052(v=vs.85).aspx – Peter K. Nov 19 '12 at 17:35
  • 25
    This code doesn't look at the whole list. What if `pl` is first priority and `fr` is second in my language list? I'd get English instead of French. – Kos Jan 19 '13 at 13:26
  • 34
    This lacks of detecting priorities, and is'nt compatible with codes [different from two letters](http://www.iana.org/assignments/language-subtag-registry) – Áxel Costas Pena Apr 03 '13 at 16:17
  • 4
    There are no other lengths than two letters! Go in your favorite browser and change the language priority and you will see it. – Gigala Apr 10 '13 at 11:41
  • 3
    @Gigala Yes there is other length than two letters, even if your favorite browser doesn't support them. They can length until 8 chars, the official list is administrated by IANA: http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry – Kustolovic Oct 06 '14 at 07:36
  • 3
    @Kustolovic Right - there are - but header's Accept-Language primary-tag always consists of two letter language abbreviations defined in ISO-639. – BudwiseЯ Nov 04 '14 at 10:45
  • Only the large languages have a two-letter code, most languages don't, see: http://en.wikipedia.org/wiki/List_of_ISO_639-2_codes – Roland Seuhs Feb 13 '15 at 11:40
  • 1
    https://www.dyeager.org/blog/2008/10/getting-browser-default-language-php.html i like this one – cwhsu Mar 23 '15 at 05:37
  • 1
    @budwiser rfc2616 says that Accept-Language could have until 8 chars (obviously). My firefox let me define languages that have more than two letters. There are very few collisions possible for it/en/fr but it is a bad practice not to recommend. – Kustolovic Sep 18 '15 at 15:27
  • also there is a simpler and much shorter way to get the same result `$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2); require("path/to/langs/lang.$lang.php");` –  Oct 21 '15 at 03:01
  • This is a bad approach because the user may have their first choice set as a language that's not in the case structure, but one of their other choices are. You should loop until you find a match. In addition, it's best to explode the languages which are delimited by commas. See answer below. – Darryl Oct 31 '15 at 00:28
83

Accept-Language is a list of weighted values (see q parameter). That means just looking at the first language does not mean it’s also the most preferred; in fact, a q value of 0 means not acceptable at all.

So instead of just looking at the first language, parse the list of accepted languages and available languages and find the best match:

// parse list of comma separated language tags and sort it by the quality value
function parseLanguageList($languageList) {
    if (is_null($languageList)) {
        if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            return array();
        }
        $languageList = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
    }
    $languages = array();
    $languageRanges = explode(',', trim($languageList));
    foreach ($languageRanges as $languageRange) {
        if (preg_match('/(\*|[a-zA-Z0-9]{1,8}(?:-[a-zA-Z0-9]{1,8})*)(?:\s*;\s*q\s*=\s*(0(?:\.\d{0,3})|1(?:\.0{0,3})))?/', trim($languageRange), $match)) {
            if (!isset($match[2])) {
                $match[2] = '1.0';
            } else {
                $match[2] = (string) floatval($match[2]);
            }
            if (!isset($languages[$match[2]])) {
                $languages[$match[2]] = array();
            }
            $languages[$match[2]][] = strtolower($match[1]);
        }
    }
    krsort($languages);
    return $languages;
}

// compare two parsed arrays of language tags and find the matches
function findMatches($accepted, $available) {
    $matches = array();
    $any = false;
    foreach ($accepted as $acceptedQuality => $acceptedValues) {
        $acceptedQuality = floatval($acceptedQuality);
        if ($acceptedQuality === 0.0) continue;
        foreach ($available as $availableQuality => $availableValues) {
            $availableQuality = floatval($availableQuality);
            if ($availableQuality === 0.0) continue;
            foreach ($acceptedValues as $acceptedValue) {
                if ($acceptedValue === '*') {
                    $any = true;
                }
                foreach ($availableValues as $availableValue) {
                    $matchingGrade = matchLanguage($acceptedValue, $availableValue);
                    if ($matchingGrade > 0) {
                        $q = (string) ($acceptedQuality * $availableQuality * $matchingGrade);
                        if (!isset($matches[$q])) {
                            $matches[$q] = array();
                        }
                        if (!in_array($availableValue, $matches[$q])) {
                            $matches[$q][] = $availableValue;
                        }
                    }
                }
            }
        }
    }
    if (count($matches) === 0 && $any) {
        $matches = $available;
    }
    krsort($matches);
    return $matches;
}

// compare two language tags and distinguish the degree of matching
function matchLanguage($a, $b) {
    $a = explode('-', $a);
    $b = explode('-', $b);
    for ($i=0, $n=min(count($a), count($b)); $i<$n; $i++) {
        if ($a[$i] !== $b[$i]) break;
    }
    return $i === 0 ? 0 : (float) $i / count($a);
}

$accepted = parseLanguageList($_SERVER['HTTP_ACCEPT_LANGUAGE']);
var_dump($accepted);
$available = parseLanguageList('en, fr, it');
var_dump($available);
$matches = findMatches($accepted, $available);
var_dump($matches);

If findMatches returns an empty array, no match was found and you can fall back on the default language.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
47

The existing answers are a little too verbose so I created this smaller, auto-matching version.

function prefered_language(array $available_languages, $http_accept_language) {

    $available_languages = array_flip($available_languages);

    $langs;
    preg_match_all('~([\w-]+)(?:[^,\d]+([\d.]+))?~', strtolower($http_accept_language), $matches, PREG_SET_ORDER);
    foreach($matches as $match) {

        list($a, $b) = explode('-', $match[1]) + array('', '');
        $value = isset($match[2]) ? (float) $match[2] : 1.0;

        if(isset($available_languages[$match[1]])) {
            $langs[$match[1]] = $value;
            continue;
        }

        if(isset($available_languages[$a])) {
            $langs[$a] = $value - 0.1;
        }

    }
    arsort($langs);

    return $langs;
}

And the sample usage:

//$_SERVER["HTTP_ACCEPT_LANGUAGE"] = 'en-us,en;q=0.8,es-cl;q=0.5,zh-cn;q=0.3';

// Languages we support
$available_languages = array("en", "zh-cn", "es");

$langs = prefered_language($available_languages, $_SERVER["HTTP_ACCEPT_LANGUAGE"]);

/* Result
Array
(
    [en] => 0.8
    [es] => 0.4
    [zh-cn] => 0.3
)*/

Full gist source here

Xeoncross
  • 55,620
  • 80
  • 262
  • 364
  • 8
    This is *brilliant* and exactly what I needed for a particular project today. The only addition I made is to allow the function to accept a default language and fall back to that if there's no match between available languages and HTTP_ACCEPT_LANGUAGEs. – Scott Sep 28 '15 at 16:11
  • 8
    Oh, a gist with my changes is here: https://gist.github.com/humantorch/d255e39a8ab4ea2e7005 (I also combined it into one file for simplicity) – Scott Sep 28 '15 at 16:17
  • 2
    Very nice method! Maybe you should check if $langs already contains an entry for the language. happened to me that perferred language was en-US, 2nd de and 3rd en, your method always gave me de, cause the first value of en was overwritten by the 3rd entry – Peter Pint Feb 05 '16 at 15:16
  • 1
    It also produces a PHP warning if no matches are found. Would be nice to handle this gracefully. – Simon East Jan 15 '18 at 03:36
  • not working as expected, my preferred language in the browser is `("en","ar","en-us")` what is happening is that is shows `ar` is the preferred language :\ – shamaseen Aug 08 '20 at 15:28
30

The official way to handle this is using the PECL HTTP library. Unlike some answers here, this correctly handles the language priorities (q-values), partial language matches and will return the closest match, or when there are no matches it falls back to the first language in your array.

PECL HTTP:
http://pecl.php.net/package/pecl_http

How to use:
http://php.net/manual/fa/function.http-negotiate-language.php

$supportedLanguages = [
    'en-US', // first one is the default/fallback
    'fr',
    'fr-FR',
    'de',
    'de-DE',
    'de-AT',
    'de-CH',
];

// Returns the negotiated language 
// or the default language (i.e. first array entry) if none match.
$language = http_negotiate_language($supportedLanguages, $result);
Simon East
  • 55,742
  • 17
  • 139
  • 133
diggersworld
  • 12,770
  • 24
  • 84
  • 119
  • 1
    I found a working link, so updated your answer to include it. – Simon East Jan 15 '18 at 05:12
  • 6
    All three of these links appear to be dead, and they don't seem to have any easily Googleable install instructions (also this function is deprecated according to their page for it) – Brian Leishman Mar 10 '20 at 18:54
15

The problem with the selected answer above is that the user may have their first choice set as a language that's not in the case structure, but one of their other language choices are set. You should loop until you find a match.

This is a super simple solution that works better. Browsers return the languages in order of preference, so that simplifies the problem. While the language designator can be more than two characters (e.g. - "EN-US"), typically the first two are sufficient. In the following code example I'm looking for a match from a list of known languages my program is aware of.

$known_langs = array('en','fr','de','es');
$user_pref_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);

foreach($user_pref_langs as $idx => $lang) {
    $lang = substr($lang, 0, 2);
    if (in_array($lang, $known_langs)) {
        echo "Preferred language is $lang";
        break;
    }
}

I hope you find this a quick and simple solution that you can easily use in your code. I've been using this in production for quite a while.

Darryl
  • 1,451
  • 1
  • 12
  • 19
  • 6
    "Browsers return the languages in order of preference" — They might do, but you should not depend on that. Use `q` values to determine preference, that's what the spec says you should do. – Quentin Oct 01 '16 at 09:17
7

Try this one:

#########################################################
# Copyright © 2008 Darrin Yeager                        #
# https://www.dyeager.org/                               #
# Licensed under BSD license.                           #
#   https://www.dyeager.org/downloads/license-bsd.txt    #
#########################################################

function getDefaultLanguage() {
   if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
      return parseDefaultLanguage($_SERVER["HTTP_ACCEPT_LANGUAGE"]);
   else
      return parseDefaultLanguage(NULL);
   }

function parseDefaultLanguage($http_accept, $deflang = "en") {
   if(isset($http_accept) && strlen($http_accept) > 1)  {
      # Split possible languages into array
      $x = explode(",",$http_accept);
      foreach ($x as $val) {
         #check for q-value and create associative array. No q-value means 1 by rule
         if(preg_match("/(.*);q=([0-1]{0,1}.\d{0,4})/i",$val,$matches))
            $lang[$matches[1]] = (float)$matches[2];
         else
            $lang[$val] = 1.0;
      }

      #return default language (highest q-value)
      $qval = 0.0;
      foreach ($lang as $key => $value) {
         if ($value > $qval) {
            $qval = (float)$value;
            $deflang = $key;
         }
      }
   }
   return strtolower($deflang);
}
user956584
  • 5,316
  • 3
  • 40
  • 50
  • Hey could you explain the regex that should catch the **q** value with `[0-1]{0,1}.\d{0,4}` ? First I guess you mean `\.` instead of `.` right? And isn't **q** always of the form `0.1324` or something? Wouldn't it be then sufficient to write `0\.?\d{0,4}`? If you have `q=1.0` then you can go in the else part. – Adam Sep 22 '17 at 09:35
  • Would be great to see a usage example here. – Simon East Jan 12 '18 at 06:19
  • 2
    @SimonEast `var_dump( getDefaultLanguage());` – jirarium Jul 09 '19 at 05:44
7

Unfortunately, none of the answers to this question takes into account some valid HTTP_ACCEPT_LANGUAGE such as:

  • q=0.8,en-US;q=0.5,en;q=0.3: having the q priority value at first place.
  • ZH-CN: old browsers that capitalise (wrongly) the whole langcode.
  • *: that basically say "serve whatever language you have".

After a comprehensive test with thousands of different Accept-Languages that reached my server, this is my language detection method:

define('SUPPORTED_LANGUAGES', ['en', 'es']);

function detect_language($fallback='en') {
    foreach (preg_split('/[;,]/', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $sub) {
        if (substr($sub, 0, 2) == 'q=') continue;
        if (strpos($sub, '-') !== false) $sub = explode('-', $sub)[0];
        if (in_array(strtolower($sub), SUPPORTED_LANGUAGES)) return $sub;
    }
    return $fallback;
}
Carlos Roldán
  • 902
  • 1
  • 9
  • 19
4

The following script is a modified version of Xeoncross's code (thank you for that Xeoncross) that falls-back to a default language setting if no languages match the supported ones, or if a match is found it replaces the default language setting with a new one according to the language priority.

In this scenario the user's browser is set in order of priority to Spanish, Dutch, US English and English and the application supports English and Dutch only with no regional variations and English is the default language. The order of the values in the "HTTP_ACCEPT_LANGUAGE" string is not important if for some reason the browser does not order the values correctly.

$supported_languages = array("en","nl");
$supported_languages = array_flip($supported_languages);
var_dump($supported_languages); // array(2) { ["en"]=> int(0) ["nl"]=> int(1) }

$http_accept_language = $_SERVER["HTTP_ACCEPT_LANGUAGE"]; // es,nl;q=0.8,en-us;q=0.5,en;q=0.3

preg_match_all('~([\w-]+)(?:[^,\d]+([\d.]+))?~', strtolower($http_accept_language), $matches, PREG_SET_ORDER);

$available_languages = array();

foreach ($matches as $match)
{
    list($language_code,$language_region) = explode('-', $match[1]) + array('', '');

    $priority = isset($match[2]) ? (float) $match[2] : 1.0;

    $available_languages[][$language_code] = $priority;
}

var_dump($available_languages);

/*
array(4) {
    [0]=>
    array(1) {
        ["es"]=>
        float(1)
    }
    [1]=>
    array(1) {
        ["nl"]=>
        float(0.8)
    }
    [2]=>
    array(1) {
        ["en"]=>
        float(0.5)
    }
    [3]=>
    array(1) {
        ["en"]=>
        float(0.3)
    }
}
*/

$default_priority = (float) 0;
$default_language_code = 'en';

foreach ($available_languages as $key => $value)
{
    $language_code = key($value);
    $priority = $value[$language_code];

    if ($priority > $default_priority && array_key_exists($language_code,$supported_languages))
    {
        $default_priority = $priority;
        $default_language_code = $language_code;

        var_dump($default_priority); // float(0.8)
        var_dump($default_language_code); // string(2) "nl"
    }
}

var_dump($default_language_code); // string(2) "nl" 
Noel Whitemore
  • 647
  • 1
  • 9
  • 20
4

Quick and simple:

$language = trim(substr( strtok(strtok($_SERVER['HTTP_ACCEPT_LANGUAGE'], ','), ';'), 0, 5));

NOTE: The first language code is what is being used by the browser, the rest are other languages the user has setup in the browser.

Some languages have a region code, eg. en-GB, others just have the language code, eg. sk.

If you just want the language and not the region (eg. en, fr, es, etc.), you can use:

$language =substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
Justin Levene
  • 1,630
  • 19
  • 17
3

There is a method in php-intl extension:

 locale_accept_from_http($_SERVER['HTTP_ACCEPT_LANGUAGE'])
Pavel Bariev
  • 2,546
  • 1
  • 18
  • 21
2

I think the cleanest way is this!

 <?php
  $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
  $supportedLanguages=['en','fr','gr'];
  if(!in_array($lang,$supportedLanguages)){
     $lang='en';
  }
    require("index_".$lang.".php");
Mike Antoniadis
  • 657
  • 7
  • 12
1

FOR LARAVEL USERS, here's a single line of code that returns a very clean collection (or array) of preferred languages:

$langs = Str::of($_SERVER['HTTP_ACCEPT_LANGUAGE'])
        ->explode(',')
        ->transform(fn($lang) => Str::substr($lang, 0, 2))
        ->unique();
Reza ODB
  • 209
  • 2
  • 10
1

Since PHP 5.3.0 there is a Locale class bundled with the php-intl extension which has a method for this:

echo Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);

or procedural style:

locale_accept_from_http($_SERVER['HTTP_ACCEPT_LANGUAGE']);

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

BadHorsie
  • 14,135
  • 30
  • 117
  • 191
0

All of the above with fallback to 'en':

$lang = substr(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE'])[0],0,2)?:'en';

...or with default language fallback and known language array:

function lang( $l = ['en'], $u ){
    return $l[
        array_keys(
            $l,
            substr(
                explode(
                    ',',
                    $u ?: $_SERVER['HTTP_ACCEPT_LANGUAGE']
                )[0],
                0,
                2
            )
        )[0]
    ] ?: $l[0];
}

One Line:

function lang($l=['en'],$u){return $l[array_keys($l,substr(explode(',',$u?:$_SERVER['HTTP_ACCEPT_LANGUAGE'])[0],0,2))[0]]?:$l[0];}

Examples:

// first known lang is always default
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-us';
lang(['de']); // 'de'
lang(['de','en']); // 'en'

// manual set accept-language
lang(['de'],'en-us'); // 'de'
lang(['de'],'de-de, en-us'); // 'de'
lang(['en','fr'],'de-de, en-us'); // 'en'
lang(['en','fr'],'fr-fr, en-us'); // 'fr'
lang(['de','en'],'fr-fr, en-us'); // 'de'
Toby
  • 2,720
  • 5
  • 29
  • 46
0

Try,

$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0,2);

if ($lang == 'tr') {
include_once('include/language/tr.php');
}elseif ($lang == 'en') {
include_once('include/language/en.php');
}elseif ($lang == 'de') {
include_once('include/language/de.php');
}elseif ($lang == 'fr') {
include_once('include/language/fr.php');
}else{
include_once('include/language/tr.php');
}

Thanks to

Bengi Besçeli
  • 3,638
  • 12
  • 53
  • 87
-1

I've got this one, which sets a cookie. And as you can see, it first checks if the language is posted by the user. Because browser language not always tells about the user.

<?php   
    $lang = getenv("HTTP_ACCEPT_LANGUAGE");
    $set_lang = explode(',', $lang);
    if (isset($_POST['lang'])) 
        {
            $taal = $_POST['lang'];
            setcookie("lang", $taal);
            header('Location: /p/');
        }
    else 
        {
            setcookie("lang", $set_lang[0]);
            echo $set_lang[0];
            echo '<br>';
            echo $set_lang[1];
            header('Location: /p/');
        } 
?>
  • 11
    I guess you can't send headers when you already echoed stuff? –  Jul 19 '12 at 20:31
  • 2
    I think the indention behind this post makes sense, which is to provide the user with a way to switch the language, and remembering this decision. Language detection should only be done once to best guess the first selection. – danijar Nov 04 '13 at 19:24