Laravel 5 如何在Laravel 5中检测语言偏好

Laravel 5 如何在Laravel 5中检测语言偏好,laravel-5,locale,Laravel 5,Locale,我想通过获取浏览器推荐的语言来检测我的客户端语言 例如,如果你在日本打开浏览器,它会给我当前用户打开的国家代码或国家名称,如“en-jp”或“Japan” 我尝试了这段代码,但它似乎显示了我以前选择的语言,默认情况下是英语 我设置了一个中间件,我需要排除api部分,因为我有一些路由器ping这个地址,而路由器浏览器没有构建系统的语言信息 class BeforeMiddleware { /** * Handle an incoming request. * * @param \Illu

我想通过获取浏览器推荐的语言来检测我的客户端语言

例如,如果你在日本打开浏览器,它会给我当前用户打开的国家代码或国家名称,如“en-jp”或“Japan”

我尝试了这段代码,但它似乎显示了我以前选择的语言,默认情况下是英语

我设置了一个中间件,我需要排除api部分,因为我有一些路由器ping这个地址,而路由器浏览器没有构建系统的语言信息

class BeforeMiddleware
{

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request $request
 * @param  \Closure $next
 * @return mixed
 */

protected $except_urls = [
    'api/*'
];

public function handle($request, Closure $next)
{
    $langArr = array("en", "fr");
    if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
        $languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
    } else {
        $languages[0] = "en";
    }
    if (Session::has('locale')) {
        App::setLocale(Session::get('locale'));
    } else {
        if (in_array($languages[0], $langArr))
            App::setLocale($languages[0]);
    }
    return $next($request);
}


} /* end class */

感谢您的帮助。

要简单地从标题中获取区域设置,您可以从请求中获取
httpaccept language
值。这可以通过门面访问,也可以在中间件中使用请求变量:

Request::server('HTTP_ACCEPT_LANGUAGE')

// OR

$request->server('HTTP_ACCEPT_LANGUAGE');
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Session\Session;
use Illuminate\Http\Request;

class Locale {

  const SESSION_KEY = 'locale';
  const LOCALES = ['en', 'cs'];

  public function handle(Request $request, Closure $next) {
    /** @var Session $session */
    $session = $request->getSession();

    if (!$session->has(self::SESSION_KEY)) {
      $session->put(self::SESSION_KEY, $request->getPreferredLanguage(self::LOCALES));
    }

    if ($request->has('lang')) {
      $lang = $request->get('lang');
      if (in_array($lang, self::LOCALES)) {
        $session->put(self::SESSION_KEY, $lang);
      }
    }

    app()->setLocale($session->get(self::SESSION_KEY));

    return $next($request);
  }
}
这将返回一个如下所示的字符串:
en-GB,en;q=0.8
。然后可以解析它(可能使用
explode()
?)并从中获取语言

然而,这类事情有时会变得复杂。如果您需要做更高级的事情,有一个软件包可以为您完成所有这些:


我刚刚为此制作了一个中间件,它可能很有用

首先设置应用程序中可用语言的数组
$availableLangs
,您可以使用
config\app.php
,而不是像我那样在中间件中初始化数组

如果第一种语言在请求语言数据中可用,它将设置语言环境,如果不可用,它将搜索下一种语言,依此类推

class GetRequestLanguage
{

    public function handle($request, Closure $next)
    {
        if (Session::has('locale')) {
            App::setLocale(Session::get('locale'));
        } else {
            $availableLangs = ['pt', 'en'];
            $userLangs = preg_split('/,|;/', $request->server('HTTP_ACCEPT_LANGUAGE'));

            foreach ($availableLangs as $lang) {
                if(in_array($lang, $userLangs)) {
                    App::setLocale($lang);
                    Session::push('locale', $lang);
                    break;
                }
            }
        }

        return $next($request);
    }
}

或者您可以使用
illumb\Http\Request::getPreferredLanguage

这样,在中间件中:

Request::server('HTTP_ACCEPT_LANGUAGE')

// OR

$request->server('HTTP_ACCEPT_LANGUAGE');
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Session\Session;
use Illuminate\Http\Request;

class Locale {

  const SESSION_KEY = 'locale';
  const LOCALES = ['en', 'cs'];

  public function handle(Request $request, Closure $next) {
    /** @var Session $session */
    $session = $request->getSession();

    if (!$session->has(self::SESSION_KEY)) {
      $session->put(self::SESSION_KEY, $request->getPreferredLanguage(self::LOCALES));
    }

    if ($request->has('lang')) {
      $lang = $request->get('lang');
      if (in_array($lang, self::LOCALES)) {
        $session->put(self::SESSION_KEY, $lang);
      }
    }

    app()->setLocale($session->get(self::SESSION_KEY));

    return $next($request);
  }
}
在中间件中执行以下操作:

$acceptableLocales=config('app.available_locales');
$userLocales=$request->getLanguages();
如果(!empty($userLocales)){
foreach($lang形式的userLocales){
$langToSearch=str_替换(“',“-”,$lang);
if(在数组中($langToSearch,$acceptableLocales)){
app('translator')->setLocale($langToSearch);
打破
}
}
}
返回$next($request);
如果要在对客户端的响应中返回语言,请创建另一个中间件并执行以下操作:

/**@var-Response$Response*/
$response=$next($request);
$response->header('Content-Language',app('translator')->getLocale();
返回$response;

我也使用中间件,但稍微小一点

<?php

namespace Transfer\Http\Middleware;

use Closure;

class SetLanguage
{
    public function handle($request, Closure $next)
    {
        $locale = $request->getLocale();

        if ($request->session()->has('locale')) {
            $locale = $request->session()->get('locale');
        }

        config(['app.locale' => $locale]);

        return $next($request);
    }
}

它可以工作,但问题是您使用
$availableLangs
强制区域设置顺序,而不是使用
$userLangs
中定义的顺序。通过
$userLangs
循环并检查
$availableLangs
中是否定义了,应该可以工作。我们应该始终遵循浏览器首选的语言选择。如果您的文件夹名称使用下划线,则不需要str_替换。这只是因为我的实现,即en GB而不是en_GB,
getPreferredLanguage
的使用是完美的,因为它是内置的。它是Symphony
框架的一部分,是自动提供的。@Timviseée谢谢Tim,我很好奇这是在哪里记录的,在Laravel中找不到它。参见symphony:解析这一点很棘手,这就是为什么它认为Daniels的答案更可取的原因。