php Laravel 更改语言环境不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41265880/
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-26 02:21:35  来源:igfitidea点击:

Laravel change locale not working

phplaravellocalization

提问by Vahn Marty

I am using a dropdown lists for the languages, consisting of english and dutch.

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

<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>

Then this is my routes.php,

然后这是我的routes.php,

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

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

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

And it is not working.

它不工作。

In my project, the path is like this

在我的项目中,路径是这样的

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

From the Dutch(du) 'navigation.php'

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

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

and for the English(en) 'navigation.php'

和英语(en)'navigation.php'

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

采纳答案by Vahn Marty

I solved my problem from this article https://mydnic.be/post/laravel-5-and-his-fcking-non-persistent-app-setlocale

我从这篇文章https://mydnic.be/post/laravel-5-and-his-fcking-non-persistent-app-setlocale解决了我的问题

Thanks to the people who contributed the word 'non persistent'

感谢贡献“非坚持”一词的人

回答by Froxz

App::setLocale()is not persistent, it set locale only for current request(runtime). What you can do:

App::setLocale()不是持久的,它只为当前请求(运行时)设置语言环境。你可以做什么:

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

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

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

This will set session keyfor current user After we will need a Middlewareto detect locale

这将为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);
    }

}

This will get current session and if is empty will fallback to default locale, which is set in your app config.

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

In app\Http\Kernel.phpadd previously created Languagemiddleware:

app\Http\Kernel.php先前创建的Language中间件:

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

As global middlware or just for web (based on your needs). I hope this helps, and gives an idea on how things are working.

作为全球中间件或仅用于网络(根据您的需要)。我希望这会有所帮助,并提供有关事情如何运作的想法。

Scenario №2Create an arraywith all available locales on your app inside app config

场景 №2array在您的应用程序中 创建一个包含所有可用区域设置的文件app config

'available_locale' => ['fr', 'gr', 'ja'],

Inside the Middleware we will check the URL first segment en fr gr cyif this segment is in available_locale, set language

在中间件内部,我们将检查 URL 第一段,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);
}

You will need to modify app\Providers\RouteServiceProviderfor setting prefix to all your routes. so you can access them domain.comor domain.com/fr/with French languageFind: mapWebRoutesAnd add this to it: (before add use Illuminate\Http\Request;)

您将需要修改app\Providers\RouteServiceProvider以设置所有路由的前缀。因此您可以访问它们domain.comdomain.com/fr/使用French languageFind: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');
        });
    }

This will prefix all your routes with country letter like 'fr gr cy' except en for non-duplicate content, so is better to not add into available_locales_array

这将为您的所有路线加上国家字母,如“fr gr cy”,除了 en 用于非重复内容,所以最好不要添加到 available_locales_array

回答by rap-2-h

App::setLocale()is not persistent. I had a similar problem before so I created a middleware:

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);
    }
}

And I registered this middleware in app\Http\Kernel:

我在app\Http\Kernel以下位置注册了这个中间件:

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

This script works for two domains: http://example.org(en) and http://fr.example.org(fr). As a middleware, it's called on every request, so the locale is always set as the right locale according to the url.

此脚本适用于两个域:http: //example.org(en) 和http://fr.example.org(fr)。作为一个中间件,它在每个请求上都会被调用,所以语言环境总是根据 url 设置为正确的语言环境。

My routes looked like:

我的路线看起来像:

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');
    // ...
}

So it responds with the correct locale to:

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

And I use the same controller and same view, just 2 different routes + a global middleware.

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

Hope it will help, not sure it's the best solution BTW. This solution works without sessio, it matches with domain and/or routes. It has some advantages over session-based solutions:

希望它会有所帮助,但不确定这是最好的解决方案。此解决方案无需 sessio,它与域和/或路由匹配。与基于会话的解决方案相比,它具有一些优势:

  • No possible bugs due to session usage ("magic" language switch)
  • You can rewrite your routes. A french user may want to see "/mon-panier" and english user "/my-cart" in their url.
  • Better indexing in google (SEO), because you can have a real index by country with relevant content.
  • I use it in production!
  • 由于会话使用(“魔术”语言切换),没有可能的错误
  • 你可以重写你的路线。法国用户可能希望在其 URL 中看到“/mon-panier”和英语用户“/my-cart”。
  • 在谷歌 (SEO) 中建立更好的索引,因为您可以按国家/地区获得包含相关内容的真实索引。
  • 我在生产中使用它!

It may have it's cons too.

它也可能有它的缺点。

回答by Afraz Ahmad

When user selects language from dropdown, call below route to save language in session

当用户从下拉列表中选择语言时,调用下面的路由以在会话中保存语言

Using Vue.js

使用 Vue.js

LocalizationComponent.vuechange language

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

路线/ web.php

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

//save locale to session

//保存区域设置到会话

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

//create middleware to set locale

//创建中间件来设置语言环境

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

In app/Http/Kernel.php

在 app/Http/Kernel.php

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

Done...

完毕...

回答by martindilling

setLocalewill only change the language for the rest of the request from that point on.

setLocale从那时起,只会更改其余请求的语言。

So to persist it, you could look into setting the selected language in a session (https://laravel.com/docs/session). Then you can create a middeware (https://laravel.com/docs/middleware) where you can check if a language is set in the session and then apply it for the request :)

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