Как определить язык пользователя на стороне сервера (в PHP)?
Один из часто используемых вариантов - использовать Geo IP и дальше уже по стране определять язык.
Но на мой взгляд более правильный способ - это использовать заголовки, которые для этого предназначены, а именно Accept-Language, в котором перечислены с указанием приоритета предпочитаемые языки.
Ниже представлена функция на PHP, которая парсит заголовок Accept-Language и находит наиболее подходящий язык для пользователя из тех, что переданы массивом (параметр $languages).
При этом, если ни одного языка не нашлось в заголовке, то будет использоваться первый из массива $languages.
function getAcceptLanguage($languages)
{
if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ||
!$_SERVER['HTTP_ACCEPT_LANGUAGE']) {
return $languages[0];
}
/*
* Разбираем заголовок Accept-Language
*
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
* 14.4 Accept-Language
* Accept-Language = "Accept-Language" ":"
* 1#( language-range [ ";" "q" "=" qvalue ] )
* language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
*
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.9
* 3.9 Quality Values
* qvalue = ( "0" [ "." 0*3DIGIT ] )
* | ( "1" [ "." 0*3("0") ] )
*/
preg_match_all("/([a-z]{1,8})(?:-([a-z]{1,8}))?(?:\s*;\s*q\s*=\s*(1|1\.0{0,3}|0|0\.[0-9]{0,3}))?\s*(?:,|$)/i",
$_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
// Результат по умолчанию - первый из доступных языков
$result = $languages[0];
$max_q = 0;
for ($i = 0; $i < count($matches); $i++) {
// Выделяем очередной язык
$lang = $matches[1][$i];
if (!empty($matches[2][$i])) {
// Переводим ru-RU в ru_RU (т.к. локаль ru_RU)
$lang .= '_'.$matches[2][$i];
}
// Определяем приоритет
if (!empty($matches[3][$i])) {
$q = (float)$matches[3][$i];
} else {
$q = 1.0;
}
// Проверяем есть ли проверяемый язык в массиве доступных
if (in_array($lang, $languages) && ($q > $max_q)) {
$result = $lang;
$max_q = $q;
}
// Если язык только из первой части (например, просто ru, а не ru-RU) и более приоритетный язык еще не найден,
// то пробуем найти в массиве доступых языков тот, который начинается так же
elseif (empty($matches[2][$i]) && ($q * 0.8 > $max_q)) {
$n = strlen($lang);
foreach ($languages as $l) {
if (!strncmp($l, $lang, $n)) {
$result = $l;
// Поскольку не точное совпадение, то уменьшаем q на 20%
$max_q = $q * 0.8;
break;
}
}
}
}
return $result;
}
Пример использования:
$locale = getAcceptLanguage(array('en_US', 'ru_RU', 'de_DE'));
Комментариев нет:
Отправить комментарий