# Detect locale with PHP

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:

1. We look if user has active language in $_SESSION; 2. If not, we look in the database to detect user preference; 3. If nothing in the database, we look on the domain name and try to detect locale from domain name and superglobal$_SERVER;

4. If we failed, we look at user's browser locale ($_SERVER again) and try to detect from it. 5. 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! - Can you check if the locale is available/valid? If yes then I'd check $lang and only return if it's accepted and otherwise fall through to the subsequent tests. I'd also move the language-from-host detection code to it's own function to allow for easier testing and extension. – user786653 Nov 9 '11 at 16:53

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:

// 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; } }  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;  - Thank you! That's a sweet idea about more detailed parsing of ACCEPT_LANGUAGE. With the link you gave, always wondered, is there some sort of sacred knowledge behind using$_COOKIE instead of $_SESSION for language setting? – paulus Nov 11 '11 at 0:10 @paulus$_COOKIE is stored by the browser whereas \$_SESSION is stored on the server. The different lifetimes might make COOKIE a better choice for language in a lot of situations. This describes it well: buildinternet.com/2010/07/when-to-use-_session-vs-_cookie – Paul Nov 11 '11 at 2:23