1

Possible Duplicate:
HTTP_ACCEPT_LANGUAGE

i try to code a language option tool. therefor i use

$default_language = (strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"]));

if (eregi('af', $default_language)) {do something}

now i would like to order the string when i will echo:

$_SERVER["HTTP_ACCEPT_LANGUAGE"]

for example an user has specified a number of languages.

example for chrome with different languages:

 nl,en-gb;q=0.8,en;q=0.6,fr;q=0.4,fr-ca;q=0.2

so how can i read out the string to bring it in a certain order where i can see that nl is the first language that is prefered.

the code should be something like:

if ('nl'== array[0]) {do something}

so if there is someone who could help me out i really would appreciate.

thanks alot.

Community
  • 1
  • 1
bonny
  • 3,147
  • 11
  • 41
  • 61

5 Answers5

5

From HTTP/1.1 Header Field Definitions:

Each language-range MAY be given an associated quality value which represents an estimate of the user's preference for the languages specified by that range. The quality value defaults to "q=1".

You have to loop over languages and select one with highest quality (preferrence); like this:

$preferred = "en"; // default
if(isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
{
    $max   = 0.0;
    $langs = explode(",", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
    foreach($langs as $lang)
    {
        $lang = explode(';', $lang);
        $q    = (isset($lang[1])) ? ((float) $lang[1]) : 1.0;
        if ($q > $max)
        {
            $max = $q;
            $preferred = $lang[0];
        }
    }
    $preferred = trim($preferred);
}
// now $preferred is user's preferred language

If Accept-Language header is not sent, all languages are equally acceptable.

Zaffy
  • 16,801
  • 8
  • 50
  • 77
1

How about explode()?

$array = explode(",",$_SERVER["HTTP_ACCEPT_LANGUAGE"]);

Given your example string, you should end up with the following values

  • $array[0] = "nl"
  • $array[1] = "en-gb;q=0.8"
  • $array[2] = "en;q=0.6"
  • etc.
hall.stephenk
  • 1,175
  • 7
  • 10
1

If you prefer to assume that the string is not always ordered before it is sent by the browser then the following code will parse and sort it. Note that I've changed French's q to 0.9.

<?php
$lang = 'nl,en-gb;q=0.8,en;q=0.6,fr;q=0.9,fr-ca;q=0.2';

$langs = array();

foreach(explode(',', $lang) as $entry) {
    $t1 = explode(';', $entry);
    switch( count($t1) ) {
        case 1:
            $langs[] = array($t1[0], 1.0);
            break;
        case 2:
            $t2 = explode('=', $t1[1]);
            $langs[] = array($t1[0], floatval($t2[1]));
            break;
        default:
            echo("what is this I don't even");
            break;
    }
}

function mysort($a, $b) {
    if( $a[1] == $b[1] ) { return 0; }
    elseif( $a[1] > $b[1] ) { return -1; }
    else { return 1; }
}
usort($langs, 'mysort');

var_dump($langs);

Output:

array(5) {
  [0]=>
  array(2) {
    [0]=>
    string(2) "nl"
    [1]=>
    float(1)
  }
  [1]=>
  array(2) {
    [0]=>
    string(2) "fr"
    [1]=>
    float(0.9)
  }
  [2]=>
  array(2) {
    [0]=>
    string(5) "en-gb"
    [1]=>
    float(0.8)
  }
  [3]=>
  array(2) {
    [0]=>
    string(2) "en"
    [1]=>
    float(0.6)
  }
  [4]=>
  array(2) {
    [0]=>
    string(5) "fr-ca"
    [1]=>
    float(0.2)
  }
}
Sammitch
  • 30,782
  • 7
  • 50
  • 77
0

try this :

<?php
print_r(Get_Client_Prefered_Language(true, $_SERVER['HTTP_ACCEPT_LANGUAGE']));
function Get_Client_Prefered_Language ($getSortedList = false, $acceptedLanguages = false)
{

    if (empty($acceptedLanguages))
        $acceptedLanguages = $_SERVER["HTTP_ACCEPT_LANGUAGE"];

        // regex borrowed from Gabriel Anderson on http://stackoverflow.com/questions/6038236/http-accept-language
    preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $acceptedLanguages, $lang_parse);
    $langs = $lang_parse[1];
    $ranks = $lang_parse[4];

        // (recursive anonymous function)
    $getRank = function ($j)use(&$getRank, &$ranks)
    {
        while (isset($ranks[$j]))
            if (!$ranks[$j])
                return $getRank($j + 1);
            else
                return $ranks[$j];
    };

        // (create an associative array 'language' => 'preference')
    $lang2pref = array();
    for($i=0; $i<count($langs); $i++)
        $lang2pref[$langs[$i]] = (float) $getRank($i);

        // (comparison function for uksort)
    $cmpLangs = function ($a, $b) use ($lang2pref) {
        if ($lang2pref[$a] > $lang2pref[$b])
            return -1;
        elseif ($lang2pref[$a] < $lang2pref[$b])
            return 1;
        elseif (strlen($a) > strlen($b))
            return -1;
        elseif (strlen($a) < strlen($b))
            return 1;
        else
            return 0;
    };

        // sort the languages by prefered language and by the most specific region
    uksort($lang2pref, $cmpLangs);


    if ($getSortedList)
        return $lang2pref;

        // return the first value's key
    reset($lang2pref);
    return key($lang2pref);
}
Shahrokhian
  • 1,100
  • 13
  • 28
0

The languages are ordered as the user prefers them. All you have to do is to split the string at the , symbol and from the parts, get rid off everything from the ; to the end (including the ;) and you have the languages in the user's prefered order.

Ridcully
  • 23,362
  • 7
  • 71
  • 86