Как определить язык пользователя на стороне сервера (в 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'));