Laravel change locale not working Laravel change locale not working php php

Laravel change locale not working


App::setLocale() is not persistent, and sets locale only for current request(runtime). You can achieve persistent in multiple ways (example of 2):

Route::post('/locale', function(){     session(['my_locale' => app('request')->input('locale')]);     return redirect()->back();});

This will set session key with lang value from request for current user. Next create a Middleware to set locale based on user session language

<?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.php add previously created Language middleware:

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 №2 - Lang based on URL pathCreate an array with all available locales on your app inside app config

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

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

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\RouteServiceProvider for setting prefix to all your routes. so you can access them domain.com or domain.com/fr/ with French languageFind: mapWebRoutesAnd add this to it: (before add use Illuminate\Http\Request;)

public function map(Request $request)    {        $this->mapApiRoutes();        $this->mapWebRoutes($request);    }    protected function mapWebRoutes(Request $request)    {        $locale = null;        if(in_array($request->segment(1), config('app.available_locale'))){          $locale = $request->segment(1);        }        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


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

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


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

<?phpnamespace 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:

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.

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.

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:

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

It may have it's cons too.