web-dev-qa-db-ja.com

Laravelロケールの変更が機能しない

英語とオランダ語で構成される言語のドロップダウンリストを使用しています。

<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',  
];
14
Vahn Marty

この記事から問題を解決しました https://mydnic.be/post/laravel-5-and-his-fcking-non-persistent-app-setlocale

「非永続的」という言葉を提供してくれた人々に感謝

6
Vahn Marty

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,
];

グローバルなミッドウェアとして、またはWeb専用(ニーズに基づいて)。これがお役に立てば幸いです。

シナリオ№2app config内のアプリで利用可能なすべてのロケールでarrayを作成します

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

ミドルウェア内では、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);
}

すべてのルートにプレフィックスを設定するには、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');
        });
    }

これは、重複しないコンテンツを除くenを除くすべてのルートに「fr gr cy」のような国名を付けるため、available_locales_arrayに追加しない方が良い

29
Froxz

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,
        // ...
    ]
];

このスクリプトは、2つのドメイン 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つの異なるルートとグローバルミドルウェアを使用しています。

それが助けになることを願っていますが、それが最善の解決策であるかどうかはわかりません。このソリューションはsessioなしで機能し、ドメインやルートと一致します。セッションベースのソリューションに勝るいくつかの利点があります。

  • セッションの使用による可能性のあるバグはありません(「マジック」言語切り替え)
  • ルートを書き換えることができます。フランスのユーザーは、URLに「/ mon-panier」と英語のユーザー「/ my-cart」を表示できます。
  • 関連コンテンツを使用して国ごとに実際のインデックスを作成できるため、Google(SEO)のインデックス作成が改善されます。
  • 本番で使用します!

短所もあるかもしれません。

3
rap-2-h

setLocaleは、それ以降のリクエストの残りの言語のみを変更します。

したがって、それを永続化するには、セッションで選択した言語の設定を調べることができます( https://laravel.com/docs/session )。次に、middeware( https://laravel.com/docs/middleware )を作成して、セッションで言語が設定されているかどうかを確認し、リクエストに適用できます:)

0
martindilling