Osw Osw - 1 year ago 32
PHP Question

Need an example on how to get preferred language from Accept-Language request header

I need a code example or library which would parse

header and return me preferred language.
RFC2616 states that:

The Accept-Language request-header field is similar to Accept, but
restricts the set of natural languages that are preferred as a
response to the request. Language tags are defined in section 3.10.

Accept-Language = "Accept-Language" ":"
1#( language-range [ ";" "q" "=" qvalue ] )
language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )

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".

Further reading shows that there are too many "optional", "should", "may" and other turns of speech that prevent me from reinventing the wheel - all I want to know is what language user prefers, any browser answers this question billion times a day.

Any code snippet in any language (except Lisp and Assembler please) would be helpful.

Many thanks in advance!

Answer Source

Try this, its in PHP but using the same regex i'm sure its adaptable to any language :

$langs = array(); // used to store values

    // 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);

produces a sorted array with preferred language first :

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

From example ACCEPT_LANGUAGE header : en-ca,en;q=0.8,en-us;q=0.6,de-de;q=0.4,de;q=0.2

Working example here