Определить язык браузера на PHP
Я использую следующий PHP-скрипт в качестве индекса для моего сайта.
этот скрипт должен включать в себя определенную страницу в зависимости от языка браузера (автоматически).
этот скрипт не работает хорошо со всеми браузерами, поэтому он всегда включает index_en.php для любого обнаруженного языка (причиной проблемы, скорее всего, является проблема с некоторым заголовком Accept-Language, который не рассматривается).
не могли бы вы предложить мне более надежный решение?
<?php
// Open session var
session_start();
// views: 1 = first visit; >1 = second visit
// Detect language from user agent browser
function lixlpixel_get_env_var($Var)
{
if(empty($GLOBALS[$Var]))
{
$GLOBALS[$Var]=(!empty($GLOBALS['_SERVER'][$Var]))?
$GLOBALS['_SERVER'][$Var] : (!empty($GLOBALS['HTTP_SERVER_VARS'][$Var])) ? $GLOBALS['HTTP_SERVER_VARS'][$Var]:'';
}
}
function lixlpixel_detect_lang()
{
// Detect HTTP_ACCEPT_LANGUAGE & HTTP_USER_AGENT.
lixlpixel_get_env_var('HTTP_ACCEPT_LANGUAGE');
lixlpixel_get_env_var('HTTP_USER_AGENT');
$_AL=strtolower($GLOBALS['HTTP_ACCEPT_LANGUAGE']);
$_UA=strtolower($GLOBALS['HTTP_USER_AGENT']);
// Try to detect Primary language if several languages are accepted.
foreach($GLOBALS['_LANG'] as $K)
{
if(strpos($_AL, $K)===0)
return $K;
}
// Try to detect any language if not yet detected.
foreach($GLOBALS['_LANG'] as $K)
{
if(strpos($_AL, $K)!==false)
return $K;
}
foreach($GLOBALS['_LANG'] as $K)
{
//if(preg_match("/[[( ]{$K}[;,_-)]/",$_UA)) // matching other letters (create an error for seo spyder)
return $K;
}
// Return default language if language is not yet detected.
return $GLOBALS['_DLANG'];
}
// Define default language.
$GLOBALS['_DLANG']='en';
// Define all available languages.
// WARNING: uncomment all available languages
$GLOBALS['_LANG'] = array(
'af', // afrikaans.
'ar', // arabic.
'bg', // bulgarian.
'ca', // catalan.
'cs', // czech.
'da', // danish.
'de', // german.
'el', // greek.
'en', // english.
'es', // spanish.
'et', // estonian.
'fi', // finnish.
'fr', // french.
'gl', // galician.
'he', // hebrew.
'hi', // hindi.
'hr', // croatian.
'hu', // hungarian.
'id', // indonesian.
'it', // italian.
'ja', // japanese.
'ko', // korean.
'ka', // georgian.
'lt', // lithuanian.
'lv', // latvian.
'ms', // malay.
'nl', // dutch.
'no', // norwegian.
'pl', // polish.
'pt', // portuguese.
'ro', // romanian.
'ru', // russian.
'sk', // slovak.
'sl', // slovenian.
'sq', // albanian.
'sr', // serbian.
'sv', // swedish.
'th', // thai.
'tr', // turkish.
'uk', // ukrainian.
'zh' // chinese.
);
// Redirect to the correct location.
// Example Implementation aff var lang to name file
/*
echo 'The Language detected is: '.lixlpixel_detect_lang(); // For Demonstration
echo "<br />";
*/
$lang_var = lixlpixel_detect_lang(); //insert lang var system in a new var for conditional statement
/*
echo "<br />";
echo $lang_var; // print var for trace
echo "<br />";
*/
// Insert the right page iacoording with the language in the browser
switch ($lang_var){
case "fr":
//echo "PAGE DE";
include("index_fr.php");//include check session DE
break;
case "it":
//echo "PAGE IT";
include("index_it.php");
break;
case "en":
//echo "PAGE EN";
include("index_en.php");
break;
default:
//echo "PAGE EN - Setting Default";
include("index_en.php");//include EN in all other cases of different lang detection
break;
}
?>
10 ответов:
почему бы вам не сохранить его простым и чистым
<?php $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); $acceptLang = ['fr', 'it', 'en']; $lang = in_array($lang, $acceptLang) ? $lang : 'en'; require_once "index_{$lang}.php"; ?>
Принять-Язык список взвешенных значений (см. q
существующие ответы немного слишком многословны, поэтому я создал эту меньшую, автоматически соответствующую версию.
function prefered_language(array $available_languages, $http_accept_language) { $available_languages = array_flip($available_languages); $langs; preg_match_all('~([\w-]+)(?:[^,\d]+([\d.]+))?~', strtolower($http_accept_language), $matches, PREG_SET_ORDER); foreach($matches as $match) { list($a, $b) = explode('-', $match[1]) + array('', ''); $value = isset($match[2]) ? (float) $match[2] : 1.0; if(isset($available_languages[$match[1]])) { $langs[$match[1]] = $value; continue; } if(isset($available_languages[$a])) { $langs[$a] = $value - 0.1; } } arsort($langs); return $langs; }и пример использования:
//$_SERVER["HTTP_ACCEPT_LANGUAGE"] = 'en-us,en;q=0.8,es-cl;q=0.5,zh-cn;q=0.3'; // Languages we support $available_languages = array("en", "zh-cn", "es"); $langs = prefered_language($available_languages, $_SERVER["HTTP_ACCEPT_LANGUAGE"]); /* Result Array ( [en] => 0.8 [es] => 0.4 [zh-cn] => 0.3 )*/
официальный способ справиться с этим с помощью PECL HTTP library. В отличие от некоторых ответов здесь, это правильно обрабатывает языковые приоритеты (q-значения), частичные языковые совпадения и возвращает самое близкое совпадение, или когда нет совпадений, он возвращается к первому языку в вашем массиве.
PECL HTTP:
http://pecl.php.net/package/pecl_httpКак использование:
http://php.net/manual/fa/function.http-negotiate-language.php$supportedLanguages = [ 'en-US', // first one is the default/fallback 'fr', 'fr-FR', 'de', 'de-DE', 'de-AT', 'de-CH', ]; // Returns the negotiated language // or the default language (i.e. first array entry) if none match. $language = http_negotiate_language($supportedLanguages, $result);
проблема с выбранным ответом выше заключается в том, что пользователь может иметь свой первый выбор в качестве языка, который не входит в структуру case, но один из их других вариантов языка установлен. Вы должны цикл, пока не найдете совпадение.
Это супер простое решение, которое работает лучше. Браузеры возвращают языки в порядке предпочтения, так что упрощает проблему. Хотя обозначение языка может быть более двух символов (например - "EN-US"), обычно первые два хватать. В следующем примере кода я ищу совпадение из списка известных языков, о которых знает моя программа.
$known_langs = array('en','fr','de','es'); $user_pref_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); foreach($user_pref_langs as $idx => $lang) { $lang = substr($lang, 0, 2); if (in_array($lang, $known_langs)) { echo "Preferred language is $lang"; break; } }Я надеюсь, что вы найдете это быстрое и простое решение, которое вы можете легко использовать в своем коде. Я использую это в течение довольно долгое время.
попробуй это:
######################################################### # Copyright © 2008 Darrin Yeager # # https://www.dyeager.org/ # # Licensed under BSD license. # # https://www.dyeager.org/downloads/license-bsd.txt # ######################################################### function getDefaultLanguage() { if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) return parseDefaultLanguage($_SERVER["HTTP_ACCEPT_LANGUAGE"]); else return parseDefaultLanguage(NULL); } function parseDefaultLanguage($http_accept, $deflang = "en") { if(isset($http_accept) && strlen($http_accept) > 1) { # Split possible languages into array $x = explode(",",$http_accept); foreach ($x as $val) { #check for q-value and create associative array. No q-value means 1 by rule if(preg_match("/(.*);q=([0-1]{0,1}.\d{0,4})/i",$val,$matches)) $lang[$matches[1]] = (float)$matches[2]; else $lang[$val] = 1.0; } #return default language (highest q-value) $qval = 0.0; foreach ($lang as $key => $value) { if ($value > $qval) { $qval = (float)$value; $deflang = $key; } } } return strtolower($deflang); }
следующий скрипт-это модифицированная версия кода Xeoncross (спасибо за этот Xeoncross), которая возвращается к настройкам языка по умолчанию, если ни один язык не соответствует поддерживаемым, или если найдено совпадение, он заменяет настройку языка по умолчанию на новую в соответствии с приоритетом языка.
в этом сценарии браузер пользователя устанавливается в порядке приоритета для испанского, голландского, американского английского и английского языков, а приложение поддерживает английский и голландский языки только без региональных вариации и английский язык является языком по умолчанию. Порядок значений в строке "HTTP_ACCEPT_LANGUAGE" не имеет значения, если по какой-либо причине браузер не упорядочивает значения правильно.
$supported_languages = array("en","nl"); $supported_languages = array_flip($supported_languages); var_dump($supported_languages); // array(2) { ["en"]=> int(0) ["nl"]=> int(1) } $http_accept_language = $_SERVER["HTTP_ACCEPT_LANGUAGE"]; // es,nl;q=0.8,en-us;q=0.5,en;q=0.3 preg_match_all('~([\w-]+)(?:[^,\d]+([\d.]+))?~', strtolower($http_accept_language), $matches, PREG_SET_ORDER); $available_languages = array(); foreach ($matches as $match) { list($language_code,$language_region) = explode('-', $match[1]) + array('', ''); $priority = isset($match[2]) ? (float) $match[2] : 1.0; $available_languages[][$language_code] = $priority; } var_dump($available_languages); /* array(4) { [0]=> array(1) { ["es"]=> float(1) } [1]=> array(1) { ["nl"]=> float(0.8) } [2]=> array(1) { ["en"]=> float(0.5) } [3]=> array(1) { ["en"]=> float(0.3) } } */ $default_priority = (float) 0; $default_language_code = 'en'; foreach ($available_languages as $key => $value) { $language_code = key($value); $priority = $value[$language_code]; if ($priority > $default_priority && array_key_exists($language_code,$supported_languages)) { $default_priority = $priority; $default_language_code = $language_code; var_dump($default_priority); // float(0.8) var_dump($default_language_code); // string(2) "nl" } } var_dump($default_language_code); // string(2) "nl"
Я думаю, что самый чистый способ-это!
<?php $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); $supportedLanguages=['en','fr','gr']; if(!in_array($lang,$supportedLanguages)){ $lang='en'; } require("index_".$lang.".php");
все вышеперечисленное с резервным вариантом 'en':
$lang = substr(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE'])[0],0,2)?:'en';...или с резервным языком по умолчанию и известным языковым массивом:
function lang( $l = ['en'], $u ){ return $l[ array_keys( $l, substr( explode( ',', $u ?: $_SERVER['HTTP_ACCEPT_LANGUAGE'] )[0], 0, 2 ) )[0] ] ?: $l[0]; }Одна Строка:
function lang($l=['en'],$u){return $l[array_keys($l,substr(explode(',',$u?:$_SERVER['HTTP_ACCEPT_LANGUAGE'])[0],0,2))[0]]?:$l[0];}примеры:
// first known lang is always default $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-us'; lang(['de']); // 'de' lang(['de','en']); // 'en' // manual set accept-language lang(['de'],'en-us'); // 'de' lang(['de'],'de-de, en-us'); // 'de' lang(['en','fr'],'de-de, en-us'); // 'en' lang(['en','fr'],'fr-fr, en-us'); // 'fr' lang(['de','en'],'fr-fr, en-us'); // 'de'
У меня есть один, который устанавливает куки. И как вы можете видеть, он сначала проверяет, размещен ли язык пользователем. Потому что язык браузера не всегда говорит о пользователе.
<?php $lang = getenv("HTTP_ACCEPT_LANGUAGE"); $set_lang = explode(',', $lang); if (isset($_POST['lang'])) { $taal = $_POST['lang']; setcookie("lang", $taal); header('Location: /p/'); } else { setcookie("lang", $set_lang[0]); echo $set_lang[0]; echo '<br>'; echo $set_lang[1]; header('Location: /p/'); } ?>
Comments