Laravel更改区域设置无法正常工作

时间:2016-12-21 15:06:00

标签: php laravel localization

我正在使用语言的下拉列表,包括英语和荷兰语。

<form class="" action="{{url('/locale')}}" method="post">
            Locale:
              <select class="" name="locale" onchange="this.form.submit()">

                <option value="en" >English</option>
                <option value="du" >Dutch</option>
              </select>
          </form>

然后这是我的routes.php,

Route::post('/locale', function(){

     \App::setLocale(Request::Input('locale'));

     return redirect()->back();
});

它不起作用。

在我的项目中,路径就像这样

resources/
 /du
   navigation.php
 /en
  /navigation.php

来自荷兰语(du)'navigation.php'

<?php
return [
  "home" => 'Home-test-dutch',  
];

和英语(en)'navigation.php'

<?php
return [
  "home" => 'Home',  
];

5 个答案:

答案 0 :(得分:27)

App::setLocale()不是持久的,它仅为当前请求(运行时)设置区域设置。你能做什么:

Route::post('/locale', function(){

     session(['my_locale' => Request::Input('locale')]);

     return redirect()->back();
});

这会为当前用户设置 session key 我们需要 Middleware 来检测区域设置

<?php namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Foundation\Application;

class Language {

    public function __construct(Application $app, Request $request) {
        $this->app = $app;
        $this->request = $request;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $this->app->setLocale(session('my_locale', config('app.locale')));

        return $next($request);
    }

}

这将获得当前会话,如果为空,则将回退到默认语言环境,该语言环境在应用程序配置中设置。

app\Http\Kernel.php中添加以前创建的Language中间件:

protected $middleware = [
   \App\Http\Middleware\Language::class,
];

作为全球middlware或仅为web(根据您的需要)。 我希望这会有所帮助,并对事情的运作方式提出一些看法。

情景№2array

内的应用中创建包含所有可用区域设置的app config
'available_locale' => ['fr', 'gr', 'ja'],

如果此段位于en fr gr cy,设置语言

,我们将在中间件内检查网址第一段available_locale
public function handle($request, Closure $next)
{
      if(in_array($request->segment(1), config('app.available_locale'))){
            $this->app->setLocale($request->segment(1));
      }else{
            $this->app->setLocale(config('app.locale'));
      }

      return $next($request);
}

您需要修改app\Providers\RouteServiceProvider以便为所有路线设置前缀。因此,您可以使用domain.com访问domain.com/fr/French language 查找:mapWebRoutes 并将其添加到其中:(在添加use Illuminate\Http\Request;之前)

public function map(Request $request)
    {
        $this->mapApiRoutes();
        $this->mapWebRoutes($request);
    }
    protected function mapWebRoutes(Request $request)
    {
        if(in_array($request->segment(1), config('app.available_locale'))){
          $locale = $request->segment(1);
        }else{
          $locale = null;
        }
        Route::group([
           'middleware' => 'web',
           'namespace' => $this->namespace,
           'prefix' => $locale
        ], function ($router) {
             require base_path('routes/web.php');
        });
    }

这将为您的所有路线添加国家/地区字母前缀,例如'fr gr cy',但非重复内容除外,因此最好不要添加到available_locales_array

答案 1 :(得分:5)

我在本文https://mydnic.be/post/laravel-5-and-his-fcking-non-persistent-app-setlocale

中解决了我的问题

感谢那些贡献“非持久性”一词的人

答案 2 :(得分:2)

App::setLocale()不持久。 我之前遇到过类似的问题所以我创建了一个中间件:

<?php

namespace App\Http\Middleware;

use Closure;

class SetLocale
{
     /**
      * Handle an incoming request.
      *
      * @param  \Illuminate\Http\Request  $request
      * @param  \Closure  $next
      * @return mixed
      */
    public function handle($request, Closure $next)
    {
        if (strpos($request->getHttpHost(), 'fr.') === 0) {
            \App::setLocale('fr');
        } else {
            \App::setLocale('en');
        }
        return $next($request);
    }
}

我在app\Http\Kernel注册了这个中间件:

protected $middlewareGroups = [
    'web' => [
        // ...
        \App\Http\Middleware\SetLocale::class,
        // ...
    ]
];

此脚本适用于两个域:http://example.org(en)和http://fr.example.org(fr)。作为中间件,它会在每个请求上调用,因此根据URL确定区域设置始终为正确的区域设置。

我的路线看起来像:

Route::group(['domain' => 'fr.' . config('app.root-domain')], function () {
    Route::get('a-propos', 'HomeController@about');
    // ...
}
Route::group(['domain' => config('app.root-domain')], function () {
    Route::get('about', 'HomeController@about');
    // ...
}

因此它以正确的语言环境响应:

我使用相同的控制器和相同的视图,只有2条不同的路线+一个全球中间件。

希望它会有所帮助,不确定它是BTW的最佳解决方案。此解决方案在没有sessio的情况下工作,它与域和/或路由匹配。与基于会话的解决方案相比,它具有一些优势:

  • 由于会话使用而没有可能的错误(“魔术”语言切换)
  • 您可以重写路线。法国用户可能希望在他们的网址中看到“/ mon-panier”和英文用户“/ my-cart”。
  • 更好的Google搜索索引(SEO),因为您可以按国家/地区获得具有相关内容的真实索引。
  • 我在制作中使用它!

也可能有它的缺点。

答案 3 :(得分:0)

setLocale只会在此时更改请求其余部分的语言。

因此,为了坚持下去,您可以考虑在会话中设置所选语言(https://laravel.com/docs/session)。 然后,您可以创建一个middeware(https://laravel.com/docs/middleware),您可以在其中检查会话中是否设置了语言,然后将其应用于请求:)

答案 4 :(得分:0)

当用户从下拉菜单中选择语言时,请拨打以下路线将语言保存到 会议

使用Vue.js

LocalizationComponent.vue 更改语言

<template>
<ul>
    <li @click="changeLanguage('en')">
        <a href="javascript:void(0);">
            <img src="/images/flag-1.png"  alt="image description">
            <span>ENG</span>
        </a>
    </li>
    <li @click="changeLanguage('vn')">
        <a href="javascript:void(0);">
            <img src="/images/flag-2.png"  alt="image description">
            <span>Việt</span>
        </a>
    </li>
</ul>

<script>
    export default{
        data(){
            return {
                selected_language:'en',
            }
        },
         methods:{
            changeLanguage(language){
                this.axios.post('/change-locale',{language:language}).then( 
                (response) => {window.location.reload();
            }).catch((error) => {
                console.log(error.response.data.errors)
            });
            localStorage.setItem('selected_language',language);
        }
    }
}
</script>

routes / web.php

Route::post('/change-locale', 'HomeController@changeLocale');

//将语言环境保存到会话中

public function changeLocale(Request $request)
{
    $language = $request->language ?? 'en';
    session(['selected_language' =>$language]);
}

//创建用于设置语言环境的中间件

class Localization
{
    public function handle($request, Closure $next)
    {
        App::setLocale(session()->get('selected_language') ?? 'en');
        return $next($request);
    }
}

在app / Http / Kernel.php中

 protected $middlewareGroups = [
    'web' => [
        ...other middelwares
        Localization::class,  //add your localization middleware here
    ],
    //...
];

完成...