この間の続きを面倒臭いながら実装中。

Accept-Languageヘッダフィールドの書式はRFC2616のSection14で定義されてるようです。

[RFC 2616] Hypertext Transfer Protocol—HTTP/1.1

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””. For example,

Accept-Language: da, en-gb;q=0.8, en;q=0.7

なるほど。これにそってgetLocales, getLocaleを実装してみました。

<?php
class RequestUtil {
    function getLocale() {
        return array_shift(RequestUtil::getLocales());
    }

    function getLocales() {
        foreach (split(",", $_SERVER["HTTP_ACCEPT_LANGUAGE"]) as $value) {
            list($name, $pri) = split(";", trim($value));
            $num = preg_replace("/^q=/", "", $pri);
            $langs[($num ? $num : 1)] = $name;
        }
        arsort($langs);
        foreach ($langs as $value) {
            $locales[] = $value;
        }
        return $locales;
    }    
}
?>

Firefoxでは仕様通りこんなのが来るのでちゃんと取れます。

ja,en-us;q=0.7,en;q=0.3

IEではこんな感じ。

ja

quality valueを省略した場合は1ということになっているのでこれも問題なさそう。

でもOperaのこれは間違ってないのかな

ja, en

両方1だとどちらを選んでいいのかわからない!
現在の実装だと上記の場合、getLocale()はenが返って来てしまいます。かといって左側優先なんてルールを勝手に実装したくない。

・・・と書いていたらyoshukiさんから情報が。

[RFC 3282] Content Language Headers

The syntax and semantics of language-range is defined in [TAGS]. The Accept-Language header may list several language-ranges in a comma- separated list, and each may include a quality value Q. If no Q values are given, the language-ranges are given in priority order, with the leftmost language-range being the most preferred language; this is an extension to the HTTP/1.1 rules, but matches current practice.

If Q values are given, refer to HTTP/1.1 [RFC 2616] for the details on how to evaluate it.

Accept-LanguageヘッダはRFC3282で再定義されていてquality valueが無い場合は左優先となっているそうです!

さっそくさっきのヤツを左優先に修正。

<?php
class RequestUtil {
    function getLocale() {
        return array_shift(RequestUtil::getLocales());
    }

    function getLocales() {
        foreach (<strong>array_reverse(</strong>split(",", $_SERVER["HTTP_ACCEPT_LANGUAGE"])<strong>)</strong> as $value) {
            list($name, $pri) = split(";", trim($value));
            $num = preg_replace("/^q=/", "", $pri);
            $langs[($num ? $num : 1)] = $name;
        }
        arsort($langs);
        foreach ($langs as $value) {
            $locales[] = $value;
        }
        return $locales;
    }    
}
?&gt;

これで安心です。

Comments


Option