patternphpMinor
Detect locale with PHP
Viewed 0 times
withphpdetectlocale
Problem
I am developing a multilingual site, so i needed some sort of a function to detect user locale, as well as not to scare away search engines, so I wrote this kind of a method to detect locale.
The priority is as following:
-
We look if user has active language in $_SESSION;
-
If not, we look in the database to detect user preference;
-
If nothing in the database, we look on the domain name and try to detect locale from domain name and superglobal $_SERVER;
-
If we failed, we look at user's browser locale ($_SERVER again) and try to detect from it.
-
If we are totally a failure, we fallback to English.
This method is called on every page of a website.
I see it as a pretty straightforward solution, but something in the back of my mind says that there might be some flaws. Are there any or am I just paranoid?
Thank you!
The priority is as following:
-
We look if user has active language in $_SESSION;
-
If not, we look in the database to detect user preference;
-
If nothing in the database, we look on the domain name and try to detect locale from domain name and superglobal $_SERVER;
-
If we failed, we look at user's browser locale ($_SERVER again) and try to detect from it.
-
If we are totally a failure, we fallback to English.
This method is called on every page of a website.
public static function detect_locale() {
if(isset($_SESSION["lang"])){
$lang = $_SESSION["lang"];
return $lang;
}
if(isset($_SESSION["id"])){
$user = new User($_SESSION["id"]);
$lang = $user->get_locale();
return $lang;
}
if($_SERVER["HTTP_HOST"] == "ru.mysupersite.com" || $_SERVER["HTTP_HOST"] == "www.mysupersite.ru"){
$lang = "ru";
return $lang;
}
if(isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])){
$lang = substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2);
return $lang;
}
$lang = "en";
return $lang;
}I see it as a pretty straightforward solution, but something in the back of my mind says that there might be some flaws. Are there any or am I just paranoid?
Thank you!
Solution
Your basic hierarchy seems fairly solid. There is just one thing - HTTP_ACCEPT_LANGUAGE is not so simple. I wrote an answer on it here. What follows is the relevant code from that:
You would need to define website languages or just set the most preferred language.
Also as a very minor point I would change:
To:
// Parse the Accept-Language according to:
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
preg_match_all(
'/([a-z]{1,8})' . // M1 - First part of language e.g en
'(-[a-z]{1,8})*\s*' . // M2 -other parts of language e.g -us
// Optional quality factor M3 ;q=, M4 - Quality Factor
'(;\s*q\s*=\s*((1(\.0{0,3}))|(0(\.[0-9]{0,3}))))?/i',
$_SERVER['HTTP_ACCEPT_LANGUAGE'],
$langParse);
$langs = $langParse[1]; // M1 - First part of language
$quals = $langParse[4]; // M4 - Quality Factor
$numLanguages = count($langs);
$langArr = array();
for ($num = 0; $num 1, 'ES' => 0.5)
arsort($langArr, SORT_NUMERIC);
// The languages the client accepts in order of preference.
$acceptedLanguages = array_keys($langArr);
// Set the most preferred language that we have a translation for.
foreach ($acceptedLanguages as $preferredLanguage)
{
if (in_array($preferredLanguage, $websiteLanguages))
{
$_SESSION['lang'] = $preferredLanguage;
return $preferredLanguage;
}
}You would need to define website languages or just set the most preferred language.
Also as a very minor point I would change:
$lang = xxx;
return $lang;To:
return xxx;Code Snippets
// Parse the Accept-Language according to:
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
preg_match_all(
'/([a-z]{1,8})' . // M1 - First part of language e.g en
'(-[a-z]{1,8})*\s*' . // M2 -other parts of language e.g -us
// Optional quality factor M3 ;q=, M4 - Quality Factor
'(;\s*q\s*=\s*((1(\.0{0,3}))|(0(\.[0-9]{0,3}))))?/i',
$_SERVER['HTTP_ACCEPT_LANGUAGE'],
$langParse);
$langs = $langParse[1]; // M1 - First part of language
$quals = $langParse[4]; // M4 - Quality Factor
$numLanguages = count($langs);
$langArr = array();
for ($num = 0; $num < $numLanguages; $num++)
{
$newLang = strtoupper($langs[$num]);
$newQual = isset($quals[$num]) ?
(empty($quals[$num]) ? 1.0 : floatval($quals[$num])) : 0.0;
// Choose whether to upgrade or set the quality factor for the
// primary language.
$langArr[$newLang] = (isset($langArr[$newLang])) ?
max($langArr[$newLang], $newQual) : $newQual;
}
// sort list based on value
// langArr will now be an array like: array('EN' => 1, 'ES' => 0.5)
arsort($langArr, SORT_NUMERIC);
// The languages the client accepts in order of preference.
$acceptedLanguages = array_keys($langArr);
// Set the most preferred language that we have a translation for.
foreach ($acceptedLanguages as $preferredLanguage)
{
if (in_array($preferredLanguage, $websiteLanguages))
{
$_SESSION['lang'] = $preferredLanguage;
return $preferredLanguage;
}
}$lang = xxx;
return $lang;return xxx;Context
StackExchange Code Review Q#5918, answer score: 2
Revisions (0)
No revisions yet.