Question

I have a multi-languagepage, I want to detect client browser's language then make a 301 home page or other thing. but I am not sure which way is better for seo. I do not know web spider like which one? Or other way?

<?php 
$LG=$_SERVER['HTTP_ACCEPT_LANGUAGE']; 
if (preg_match('/^[zZ][hH]/', $LG)) {
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://mydomain.com/cn/");
exit();} //jump to chinese version
else { 
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://mydomain.com/en/");
exit();} //jump to english version
?>

OR

<?php 
$LG=$_SERVER['HTTP_ACCEPT_LANGUAGE']; 
if (preg_match('/^[zZ][hH]/', $LG)) {
include ("http://mydomain.com/cn/");
} //include chinese version
else { 
header("HTTP/1.1 301 Moved Permanently");
include ("http://mydomain.com/en/");
} //include english version
?>

OR other way? Thanks.

Was it helpful?

Solution

As you already assume in your question, you need to parse the Accept-LanguageHTTP/1.1 header, which is available in PHP in $_SERVER['HTTP_ACCEPT_LANGUAGE']. This first needs to be parsed into a structure you can better deal within PHP, like an array:

/**
 * Convert Accept Language to sorted PHP array
 * 
 * Related HTTP Specs:
 *   <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4>
 *   <http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.9>
 *
 * @param string $accept header value
 * @return array ([language-range] => qvalue, ...)
 */
function http_accept_language_array($accept = NULL)
{
    if (!$accept && isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
        $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
    $accept = (string) $accept;

    $pattern = '/([a-z]{1,8}(-[a-z]{1,8})?)(;q=([01](?:\.[0-9]{0,3})?))?(?=$|,[ ]*)/i';
    preg_match_all($pattern, $accept, $matches);

    $array = array();
    if (count($matches[1]))
    {
        list(, $ranges,,, $qvals) = $matches;
        # normalize ranges
        foreach ($ranges as &$range)
            $range = strtolower($range);
        unset ($range);
        # set default qvalue 1
        foreach ($qvals as &$qval)
            if ('' === $qval) $qval = '1';
        unset ($qval);        
        $array = array_combine($ranges, $qvals);
        arsort($array, SORT_NUMERIC);
    }
    return $array;
}

Which for da, en-gb;q=0.8, en;q=0.7 will return:

array(3) {
  ["da"]    => string(1) "1"
  ["en-gb"] => string(3) "0.8"
  ["en"]    => string(3) "0.7"
}

You then need to parse this sorted array to find your first match, setting your preference with the en default value:

$lang = 'en';
foreach (http_accept_language_array() as $range => $qvalue)
{
    if (preg_match('/^zh[$-]/', $range))
    {
        $lang = 'cn';
        break;
    }
}

Finally you can do the redirect based on $lang (or the include or whatever):

header("HTTP/1.1 301 Moved Permanently");
header("Location: http://mydomain.com/$lang/");

If you're looking for a ready-made library to deal with this, one existing solution is the Symfony's HttpFoundation\Request or in PEAR there is HTTP::negotiateLanguage.

The PHP intl extension has another low-level function that is related, however it's doesn't offer an array but a single value: locale_accept_from_http

Another general resource for more HTTP related information is Advanced handling of HTTP requests in PHP.

OTHER TIPS

I would recommend having a different URL for each language (option 2). It would make analytics much easier (Google Analytics can show which language is more popular if you use the /en, /cn, structure).

Also, users can bookmark and share the proper language and return to it from another computer.

Most importantly, having the same canonical URL serve two different languages will wreak havoc when spiders try to index the page. The indexed content would be unpredictable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top