php PHP语言检测

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1352130/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:09:07  来源:igfitidea点击:

PHP language detection

php

提问by Pascal MARTIN

I'm trying to build multilangual site.

我正在尝试构建多语言站点。

I use this piece of code to detect users language. If you havent chosen a language, it will include your language file based on HTTP_ACCEPT_LANGUAGE.

我使用这段代码来检测用户语言。如果您尚未选择语言,它将包含基于HTTP_ACCEPT_LANGUAGE.

I don't know where it gets it from though:

我不知道它从哪里得到它:

session_start();

if (!isset($_SESSION['lang'])) {
   $_SESSION['lang'] = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
}

elseif (isset($_GET['setLang']) && $_GET['setLang'] == 'en') $_SESSION['lang'] = "en";
elseif (isset($_GET['setLang']) && $_GET['setLang'] == 'sv') $_SESSION['lang'] = "sv";
elseif (isset($_GET['setLang']) && $_GET['setLang'] == 'pl') $_SESSION['lang'] = "pl";
elseif (isset($_GET['setLang']) && $_GET['setLang'] == 'fr') $_SESSION['lang'] = "fr";

include('languages/'.$_SESSION['lang'].'.php');

It works for me and includes the polish lang file. But is this code accurate? Or is there another way?

它对我有用,并包含波兰语 lang 文件。但是这段代码准确吗?或者还有其他方法吗?

回答by Pascal MARTIN

The browser generally sends a HTTP header, name Accept-Language, that indicates which languages the user is willing to get.

浏览器通常会发送一个名为 Accept-Language 的 HTTP 标头,指示用户愿意使用哪些语言。

For instance, this header can be :

例如,此标头可以是:

Accept-Language: en-us,en;q=0.5

There is notion of priority in it, btw ;-)

其中有优先级的概念,顺便说一句;-)

In PHP, you can get this in the $_SERVERsuper global :

在 PHP 中,你可以在$_SERVERsuper global 中得到这个:

var_dump($_SERVER['HTTP_ACCEPT_LANGUAGE']);

will get me :

会得到我:

string 'en-us,en;q=0.5' (length=14)

Now, you have to parse that ;-)

现在,您必须解析它;-)


If I edit my preferences in the browser's option to say "I want french, and if you don't can't serve me french, get me english from the US ; and if you can't get me that either, just get me english), the header will be :


如果我在浏览器的选项中编辑我的首选项说“我想要法语,如果你不能为我提供法语,请从美国给我英语;如果你也不能让我,就让我英语),标题将是:

Accept-Language: fr-fr,en-us;q=0.7,en;q=0.3

And, from PHP :

而且,从 PHP :

string 'fr-fr,en-us;q=0.7,en;q=0.3' (length=26)


For more informations, you can take a look at section 14.4 of the HTTP RFC.


有关更多信息,您可以查看HTTP RFC 的第 14.4 节

And you probably can find lots of code example in PHP to parse that header ; for instance : Parse Accept-Language to detect a user's language

您可能会在 PHP 中找到很多代码示例来解析该标头;例如:解析接受语言以检测用户的语言

Have fun !

玩得开心 !

回答by Imran

Here's the script I used for a bi-lingual site. It is to be used as index.phpof mysite.com. Based on the user's browser's language preference, it would redirect to desired language version of the site or the default language site if the site in user's preferred langauge was not available.

这是我用于双语网站的脚本。它index.phpmysite.com. 根据用户浏览器的语言首选项,如果用户首选语言的站点不可用,它将重定向到所需语言版本的站点或默认语言站点。

<?php
// List of available localized versions as 'lang code' => 'url' map
$sites = array(
    "en" => "http://en.mysite.com/",
    "bn" => "http://bn.mysite.com/",
);

// Get 2 char lang code
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

// Set default language if a `$lang` version of site is not available
if (!in_array($lang, array_keys($sites)))
    $lang = 'en';

// Finally redirect to desired location
header('Location: ' . $sites[$lang]);
?>

回答by Serhii Polishchuk

I know there already many good solutions, but have found my own way to solve this problem.

我知道已经有很多好的解决方案,但是找到了我自己的方法来解决这个问题。

<?php
  $prefLocales = array_reduce(
    explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']), 
      function ($res, $el) { 
        list($l, $q) = array_merge(explode(';q=', $el), [1]); 
        $res[$l] = (float) $q; 
        return $res; 
      }, []);
    arsort($prefLocales);
    /*
    This get you from headers like this
      string 'en-US,en;q=0.8,uk;q=0.6,ru;q=0.4' (length=32)
    array like this
    array (size=4)
      'en-US' => float 1
      'en' => float 0.8
      'uk' => float 0.6
      'ru' => float 0.4
    */

Code will convert HTTP_ACCEPT_LANGUAGE string to array with locales as keys and weight as values, sorted from high value to low. So you can just get one by one with array_shift to get the best match with your site locales.

代码会将 HTTP_ACCEPT_LANGUAGE 字符串转换为以语言环境为键、权重为值的数组,从高值到低值排序。所以你可以一一使用 array_shift 来获得与你的站点语言环境的最佳匹配。

回答by miralong

You can use: Locale::acceptFromHttp().

您可以使用:Locale::acceptFromHttp()

Tries to find locale that can satisfy the language list that is requested by the HTTP "Accept-Language" header.

尝试查找可以满足 HTTP“Accept-Language”标头请求的语言列表的语言环境。

回答by djn

Your code looks just fine. You might want to add a final elsedefault choice if the visitor asks for a language you aren't providing. Also, if the visitor himself selects a language you should save that choice in a persistent cookie and check its value, giving it precedence over HTTP_ACCEPT_LANGUAGE.

你的代码看起来很好。else如果访问者要求使用您未提供的语言,您可能希望添加最终默认选项。此外,如果访问者自己选择了一种语言,您应该将该选择保存在持久性 cookie 中并检查其值,使其优先于 HTTP_ACCEPT_LANGUAGE。

As far as I can tell Youtube does use HTTP_ACCEPT_LANGUAGE, but at the same time uses IP geolocation to suggest a change in language if the langauge of the visitor's country doesn't match that. Definitely annoying.

据我所知,Youtube 确实使用 HTTP_ACCEPT_LANGUAGE,但同时如果访问者所在国家/地区的语言不匹配,则使用 IP 地理定位建议更改语言。肯定烦人。

Just nitpicking: if you're gonna add languages to the list a switch()statement might be more readable.

只是吹毛求疵:如果您要将语言添加到列表中,则switch()语句可能更具可读性。

回答by Sinus Mackowaty

Here's a function for selecting the best out of a group of supported languages. It extracts languages from Accept-Language, then sorts the given array of languages according to their priority.

这是从一组支持的语言中选择最佳语言的功能。它从 中提取语言Accept-Language,然后根据它们的优先级对给定的语言数组进行排序。

function select_best_language($languages) {
    if (!$_SERVER['HTTP_ACCEPT_LANGUAGE']) return $languages[0];
    $default_q=100;
    foreach (explode(",",$_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lqpair) {
        $lq=explode(";q=",$lqpair);
        if ($lq[1]) $lq[1]=floatval($lq[1]); else $lq[1]=$default_q--;
        $larr[$lq[0]]=$lq[1];
    }
    usort($languages,function($a,$b) use ($larr) { return $larr[$b]<=>$larr[$a]; });
    return $languages[0];
}

$lang = select_best_language(['en','fr','it']);

回答by Chirag Dj

Try This

尝试这个

function getUserLanguage() {
    $langs = array();

    if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
        // break up string into pieces (languages and q factors)
        preg_match_all(
            '/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i',
            $_SERVER['HTTP_ACCEPT_LANGUAGE'],
            $lang_parse
        );

        if (count($lang_parse[1])) {
            // create a list like 'en' => 0.8
            $langs = array_combine($lang_parse[1], $lang_parse[4]);

            // set default to 1 for any without q factor
            foreach ($langs as $lang => $val) {
                if ($val === '') {
                    $langs[$lang] = 1;
                }
            }
            // sort list based on value
            arsort($langs, SORT_NUMERIC);
        }
    }
    //extract most important (first)
    reset($langs);
    $lang = key($langs);

    //if complex language simplify it
    if (stristr($lang, '-')) {
        list($lang) = explode('-', $lang);
    }

    return $lang;
}

回答by njank

This is also possible. It will use english as default if .php is not available.

这也是可能的。如果 .php 不可用,它将使用英语作为默认值。

$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
(@include_once 'languages/'.$lang.'.php') or (@include_once 'languages/en.php'); 

回答by Коля Бреславський

if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
    $parts=explode(';',$_SERVER['HTTP_ACCEPT_LANGUAGE']);
    $langs=explode(',',$parts[0]);
    var_dump($langs);
}