在PHP中检测浏览器语言

174

我使用以下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;
}
?>

6
PHP 5.3.0+ 版本新增了 locale_accept_from_http() 函数,它可以从 Accept-Language 头部中获取用户首选语言。您应该优先使用此方法而不是自行编写的方法。将结果与正则表达式列表进行匹配以确定页面语言。有关示例,请参见 PHP-I18N - caw
3
locale_accept_from_http() 的问题在于您可能不支持它返回的最佳结果,因此仍然需要自己解析标头,以找到次佳的结果。 - Xeoncross
接受的答案应该修改为考虑多种语言的答案之一。 - Pekka
include和require在PHP的编译时发生,因此基本上您包含所有的index*.php并仅显示一个-浪费资源。 - Michael
除了真正的问题之外,关于上面的代码,我不建议为每种语言使用不同的索引页面。用户希望在每种语言中看到相同的页面布局和内容。您只需要在一个index.php页面中加载适当的文本/图片即可。内容可以组织在一个XML文件中,例如[item]->[lang]部分- <div><?php echo $xml->item [0]-> lang [0];?></div>,或者在SQL等中。 - Hristo
16个回答

2
我认为最简洁的方式是这样的!
 <?php
  $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
  $supportedLanguages=['en','fr','gr'];
  if(!in_array($lang,$supportedLanguages)){
     $lang='en';
  }
    require("index_".$lang.".php");

1
这并没有考虑头文件中的语言优先级。 - Simon East

1
自 PHP 5.3.0 开始,php-intl 扩展中捆绑了一个 Locale 类,其中包含了一个用于此目的的方法:

echo Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);

或者过程式风格:

locale_accept_from_http($_SERVER['HTTP_ACCEPT_LANGUAGE']);

https://www.php.net/manual/en/locale.acceptfromhttp.php


1

对于Laravel用户,以下单行代码将返回一个非常干净的首选语言集合(或数组):

$langs = Str::of($_SERVER['HTTP_ACCEPT_LANGUAGE'])
        ->explode(',')
        ->transform(fn($lang) => Str::substr($lang, 0, 2))
        ->unique();

0
以上所有,如无法匹配则使用英语。
$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'

0

试一下,

$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0,2);

if ($lang == 'tr') {
include_once('include/language/tr.php');
}elseif ($lang == 'en') {
include_once('include/language/en.php');
}elseif ($lang == 'de') {
include_once('include/language/de.php');
}elseif ($lang == 'fr') {
include_once('include/language/fr.php');
}else{
include_once('include/language/tr.php');
}

感谢


-1
我有这个函数,它设置一个cookie。正如你所看到的,它首先检查用户是否发布了语言。因为浏览器语言并不总是能准确反映用户的语言。
<?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/');
        } 
?>

11
当已经输出内容时,我猜你不能发送标头? - user1539061
2
我认为这篇文章背后的缩进是有意义的,它提供了用户切换语言并记住这个决定的方法。语言检测应该只在最初选择时进行一次以猜测最佳选择。 - danijar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接