Bea*_*nie 26 php http internationalization
我创建了一个PHP脚本,HTTP_ACCEPT_LANGUAGE
使用前两个字符中的相应语言检查并加载网站:
$http_lang = substr($_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2);
switch ($http_lang) {
case 'en':
$SESSION->conf['language'] = 'english';
break;
case 'es':
$SESSION->conf['language'] = 'spanish';
break;
default:
$SESSION->conf['language'] = $PREFS->conf['languages'][$SESSION->conf['language_id']];
}
Run Code Online (Sandbox Code Playgroud)
如果我在Firefox中将语言更改为西班牙语,则网站会以西班牙语加载.不过,我有几份报告称哥伦比亚人民用英文看网站.
详细信息:"es-co"LCID = 9226西班牙语(哥伦比亚)
任何人都有任何关于为什么会这样的想法?我认为这是检查用户支持的语言的最佳方式.
mar*_*rio 16
更现代的方法是使用http_negotiate_language()
:
$map = array("en" => "english", "es" => "spanish");
$conf_language= $map[ http_negotiate_language(array_keys($map)) ];
Run Code Online (Sandbox Code Playgroud)
如果您没有安装http扩展(而不是intl),则评论中还有另一种解决方法(用户注释#86787(2008年11月;匿名)):
<?php
/*
determine which language out of an available set the user prefers most
$available_languages array with language-tag-strings (must be lowercase) that are available
$http_accept_language a HTTP_ACCEPT_LANGUAGE string (read from $_SERVER['HTTP_ACCEPT_LANGUAGE'] if left out)
*/
function prefered_language ($available_languages,$http_accept_language="auto") {
// if $http_accept_language was left out, read it from the HTTP-Header
if ($http_accept_language == "auto") $http_accept_language = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : '';
// standard for HTTP_ACCEPT_LANGUAGE is defined under
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
// pattern to find is therefore something like this:
// 1#( language-range [ ";" "q" "=" qvalue ] )
// where:
// language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
// qvalue = ( "0" [ "." 0*3DIGIT ] )
// | ( "1" [ "." 0*3("0") ] )
preg_match_all("/([[:alpha:]]{1,8})(-([[:alpha:]|-]{1,8}))?" .
"(\s*;\s*q\s*=\s*(1\.0{0,3}|0\.\d{0,3}))?\s*(,|$)/i",
$http_accept_language, $hits, PREG_SET_ORDER);
// default language (in case of no hits) is the first in the array
$bestlang = $available_languages[0];
$bestqval = 0;
foreach ($hits as $arr) {
// read data from the array of this hit
$langprefix = strtolower ($arr[1]);
if (!empty($arr[3])) {
$langrange = strtolower ($arr[3]);
$language = $langprefix . "-" . $langrange;
}
else $language = $langprefix;
$qvalue = 1.0;
if (!empty($arr[5])) $qvalue = floatval($arr[5]);
// find q-maximal language
if (in_array($language,$available_languages) && ($qvalue > $bestqval)) {
$bestlang = $language;
$bestqval = $qvalue;
}
// if no direct hit, try the prefix only but decrease q-value by 10% (as http_negotiate_language does)
else if (in_array($langprefix,$available_languages) && (($qvalue*0.9) > $bestqval)) {
$bestlang = $langprefix;
$bestqval = $qvalue*0.9;
}
}
return $bestlang;
}
?>
Run Code Online (Sandbox Code Playgroud)
我使用了来自@GabrielAnderson的正则表达式并设计了这个根据RFC 2616行为的函数(当没有给出语言的质量值时,它默认为1).
当多种语言共享相同的质量值时,最具体的语言优先于不太具体的语言.(此行为不是RFC的一部分,不提供此特定情况的建议)
function Get_Client_Prefered_Language ($getSortedList = false, $acceptedLanguages = false)
{
if (empty($acceptedLanguages))
$acceptedLanguages = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
// regex inspired from @GabrielAnderson on http://stackoverflow.com/questions/6038236/http-accept-language
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})*)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $acceptedLanguages, $lang_parse);
$langs = $lang_parse[1];
$ranks = $lang_parse[4];
// (create an associative array 'language' => 'preference')
$lang2pref = array();
for($i=0; $i<count($langs); $i++)
$lang2pref[$langs[$i]] = (float) (!empty($ranks[$i]) ? $ranks[$i] : 1);
// (comparison function for uksort)
$cmpLangs = function ($a, $b) use ($lang2pref) {
if ($lang2pref[$a] > $lang2pref[$b])
return -1;
elseif ($lang2pref[$a] < $lang2pref[$b])
return 1;
elseif (strlen($a) > strlen($b))
return -1;
elseif (strlen($a) < strlen($b))
return 1;
else
return 0;
};
// sort the languages by prefered language and by the most specific region
uksort($lang2pref, $cmpLangs);
if ($getSortedList)
return $lang2pref;
// return the first value's key
reset($lang2pref);
return key($lang2pref);
}
Run Code Online (Sandbox Code Playgroud)
例:
print_r(Get_Client_Prefered_Language(true, 'en,en-US,en-AU;q=0.8,fr;q=0.6,en-GB;q=0.4'));
Run Code Online (Sandbox Code Playgroud)
输出:
Array
(
[en-US] => 1
[en] => 1
[en-AU] => 0.8
[fr] => 0.6
[en-GB] => 0.4
)
Run Code Online (Sandbox Code Playgroud)
正如你所注意到的那样,'en-US'出现在第一位,尽管'en'是给定字符串中的第一个.
所以你可以使用这个函数,只需用你的第一行代码替换:
$http_lang = substr(Get_Client_Prefered_Language(),0,2);
Run Code Online (Sandbox Code Playgroud)
您知道哥伦比亚的所有访问者是否都会这样做?用户通常可以自由地更改其浏览器的语言设置 - 或者由负责计算机的任何人更改它们.正如zerkms建议的那样,尝试记录IP地址及其标题.
如果您安装了intl扩展,则可以使用Locale::lookup
和Locale::acceptFromHttp
从用户浏览器设置中获得最合适的语言选择以及可用的翻译列表.
Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']); # e.g. "en_US"
Run Code Online (Sandbox Code Playgroud)