How to get the language value from $_SERVER['HTTP_ACCEPT_LANGUAGE'] using PHP?
Yes, the value of $_SERVER['HTTP_ACCEPT_LANGUAGE']
is a string -- see $_SERVER
.
Its content is sent by the browser -- which explains why you get different results depending on the browser you are using : most likely, your Firefox is configured to request pages in english (high priority) or japanese (low priority), while your IE is configured to request pages in chinese.
This is because that HTTP header can contain :
- a list of languages
- optionnaly, with region codes
- with associated priorities.
The idea being that the server should respond, using the language that suits "the best" what's requested by the user.
About parsing that header, this blog-post might be a interesting read : Parse Accept-Language to detect a user's language
There is a portion of code proposed to parse that HTTP header -- and it generates an array that looks like this (quoting) :
Array
(
[en-ca] => 1
[en] => 0.8
[en-us] => 0.6
[de-de] => 0.4
[de] => 0.2
)
Which is an array of languages, sorted by priority, in descending order -- which is probably what you want.
Google crawl error with HTTP_ACCEPT_LANGUAGE
$browser_lang = !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? strtok(strip_tags($_SERVER['HTTP_ACCEPT_LANGUAGE']), ',') : '';
$browser_lang = substr($browser_lang, 0,2);
// Now check if you support this language and set it
if(array_key_exists($browser_lang, $this->languages /* define this array to compare */))
return $browser_lang;
else{
// return default lang
}
how to order string from HTTP_ACCEPT_LANGUAGE
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.
undefined server variable error (in the google cache)
This:
else {
$locale = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
}
change to:
else if (array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) {
$locale = substr((string) $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
}
Language redirect works on desktop but not mobile browser
UPDATE to my previous answer
The HTTP_ACCEPT_LANGUAGE is set via headers and will give different values for everyone.
In my case I am in south america on an computer setup in english so my lang headers have english and spanish
settings with a bias towards english.
session_start();
function redirectToLang($langCode){
// use if's instead of switch so that you can
// check exact matches and presence of a substring
if ($langCode == 'sv'){
$langPath = 'sv';
}else if (strpos($langCode, 'en') !== false){ // this would match en, en-CA, en-US
$langPath = 'en';
}else if ($langCode == 'no'){
$langPath = 'no';
}else{
$langPath = 'en';
}
// you should have no output from the server before this line!
// that is no echoes, print_r, var_dumps, headers, etc
header( 'Location: http://www.example.com/' . $langPath .'/' );
die();
}
function parseLang(){
// echo $_SERVER['HTTP_ACCEPT_LANGUAGE']; in my case
// Chrome Mac OS: en,es;q=0.8
// Chrome Android 5.1: en-US;en;q=0.8,es;q=0.6
// IE Windows Phone 8.1: en-US,en;q=0.5
// Safari iOS: en-US
// Chrome iOS: en-US,en;q=0.8
// get the lang and set a default
$lang = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : 'en';
// parse the lang code. This can be as simple or as complex as you want
// Simple
$langCode = substr($lang, 0, 2); // in my case 'en'
// Semi Complex (credits to http://www.thefutureoftheweb.com/blog/use-accept-language-header)
$languages = array();
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $lang, $parsed);
if (count($parsed[1])) {
$languages = array_combine($parsed[1], $parsed[4]);
foreach ($languages as $lang => $val) {
if ($val === '') $languages[$lang] = 1;
}
arsort($languages, SORT_NUMERIC);
}
// var_dump($languages); in my case
// array (size=2)
// 'en' => int 1
// 'es' => string '0.8'
$langCode = key($languages); // in my case 'en'
return $langCode;
}
if (!isset($_SESSION['lang'])){
$langCode = parseLang();
$_SESSION['lang'] = $langCode;
redirectToLang($langCode);
}else{
// we already know the language and it is in $_SESSION
// no need to parseLang nor redirect
}
In my case, all devices redirect correctly. My guess is that there is something happening on the logic that calls redirect()
// this part
if ( strlen($url) < 4 ) {
session_start();
if ( empty($_SESSION[ 'language' ]) ) {
$_SESSION[ 'language' ] = true;
redirect();
}
}
and the session var
is bypassing the redirect logic. Try the code above and clear all cookies and sessions from all devices so that the $_SESSION['language']
var you have
set during testing wont mess up the results. Let us know what happens on your end.
Related Topics
Concatenation with Addition in It Doesn't Work as Expected
PHP Is Not Recognized as an Internal or External Command in Command Prompt
How to Solve Time Out in PHPmyadmin
Wamp/MySQL Errors Not in Correct Language
Should My PHP Functions Accept an Array of Arguments or Should I Explicitly Request Arguments
Why I Can Not Login to Magento Backend Using Google Chrome
Notice: Undefined Offset: 0 In
How to Embed Images in a Single HTML/PHP File
Intl Extension PHP_Intl.Dll with Wamp
Handling Big User Ids Returned by Fql in PHP
Mysqli_Query() Expects at Least 2 Parameters, 1 Given In
How to Add a Line Break Within Echo in PHP
When Should I Use Stdclass and When Should I Use an Array in PHP Oo Code
PHP Cli: How to Read a Single Character of Input from the Tty (Without Waiting for the Enter Key)
PHP Return 500 Error But No Error Log
Should I Use Prepared Statements for MySQL in PHP Performance-Wise