Laravel app()->getLocale() inside routes always print the default "en"
Asked Answered
A

2

8

I encountred a problem when trying to prefixing my routes with new set locale. When I return app()->getLocale() from a controller or a route closure it returns new set locale correctly, but when I put it inside Route prefix I get the default one 'en'. In my case the new locale is 'ar'.

This is my code inside web.php

<?php


//Request to put the choosen locale into the session
Route::get('locale/{locale}', function($locale) {

    session()->put('userLocale', $locale);
    return redirect(app()->getLocale());
});

//Group of routes that are supposed to be prefixed with new set locale 'ar'
Route::group(['prefix' => app()->getLocale(), 'middleware' => 'locale'], function() {

    Route::get('/', function() {
        return app()->getLocale();
    });
});

And this is the middleware:

<?php

namespace App\Http\Middleware;

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

class Locale
{
    protected $app;

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

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

Note the statement "app()->getLocale()" inside Route prefix, this statement's value always is "en". But when I return it from within the closure it prints the new set locale "ar".

What I'm trying to say is that, inside prefix, app()->getLocale()'s value is always "en", but inside the Closure its value is "ar".

So when I run "localehost:8000/locale/ar" in the browser the output is "ar" and that is correct but the url becomes "localehost:8000/en" and that should be "localehost:8000/ar" isn'it ? When I run "localehost:8000/ar" in the browser I get a 404 page.

I tried to set the prefix from within RouteServiceProvider's mapWebRoutes methode but It doesn't work because I think that the service provider is executed before the middlware so It can't recognize the new locale that is set by the middlware.

I hope to get help or another approach to prefix the routes with new locale because maybe I'm doing somthing wrong.

Aldrin answered 20/8, 2018 at 20:43 Comment(0)
G
4

Your locale is not going to be set from the session until your middleware runs. Your routes would have to be defined before the middleware runs, otherwise, the system would have no idea which middleware are supposed to be run on which routes.

Since app()->locale() is going to return 'en' before your middleware runs, all your code is doing is defining a prefix of 'en'.

It seems maybe you want to define a variable for the locale, in that case, you would do something like:

Route::group(['prefix' => '{locale}', 'middleware' => 'locale'], function() {
   ...
});

Or you could use a package that handles localized urls for you like https://github.com/mcamara/laravel-localization

Gunpaper answered 20/8, 2018 at 21:16 Comment(2)
Thank you. I'll give it a tryAldrin
What can I do to get routes defined before middleware runs ?Aldrin
M
0

Make a middleware named SetLocale like below and also register it in kernel.php file:

public function handle($request, Closure $next)
{
    $desiredLocale=$request->segment(1);
    in_array($desiredLocale, ["en", "ar"]) ? app()->setLocale($desiredLocale) : app()->setLocale('en');

    return $next($request);
}

In kernel.php add in $routeMiddleware array like this:

'local.set'=>\App\Http\Middleware\SetLocale::class,

Now, you can apply it on all the routes like this:

Route::group(['prefix' => '{locale}','middleware' => 'local.set'], function () {
......
});
Milligram answered 15/7, 2021 at 5:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.