2

I use this guide: https://mydnic.be/post/how-to-build-an-efficient-and-seo-friendly-multilingual-architecture-in-laravel-v2

I have these routes and middleware:

$locale = request()->segment(1);

Route::middleware('localized')->prefix($locale)->group(function() {
     Route::get('/contacts', 'ContactController@index');
     Route::get('/page/{page}', 'PageController@index');
});

And middleware localized from Kernel.php -> routeMiddleware:

public function handle(Request $request, Closure $next)
{
    if (!array_key_exists($request->segment(1), config('translatable.locales'))) {
        $segments = $request->segments();

        $segments = Arr::prepend($segments, config('app.fallback_locale'));

        if($request->session()->has('language')) {
            $segments[0] = session('language');
        }

        return redirect()->to(implode('/', $segments));
    }
    
    return $next($request);
}

When I access to: site.test/contacts he redirect me on locale: site.com/en/contacts When I access to site.test/page/test I got 404 not found, If I access to: site.com/en/page/test then page working. Problem with redirect on locale with route model binding.

In Controller Page I have:

public function index(Page $page) 
{
    return view('page', compact('page'));
}

In translatable.php:

'locales' => [
    'de' => 'Deutsch',
    'en' => 'English',
],

In AppServiceProvider:

public function boot()
{
    if(array_key_exists(request()->segment(1), config('translatable.locales'))) {
        app()->setLocale(request()->segment(1));
    }
}
2
  • Are you sure the above example code works? as I'm trying to replicate "When I access to: site.test/contacts he redirect me on locale: site.com/en/contacts" but it's not working for me unless I add the locale site.test/fr/contacts .. then it works. How is your translatable.php config file setup? Commented Nov 17, 2020 at 10:34
  • @KolawoleEmmanuelIzzy I updated my question with config and provider. Yep my code works Commented Nov 17, 2020 at 10:45

1 Answer 1

0

I was able to work around this but this cost us access to the session, which you checked for to know if the session has "language" if yes, then prepend locale value should be set to the language value in the session. Below is what I did;

In Routes File

$locale = request()->segment(1);

Route::prefix($locale)->group(function() {
     Route::get('/contacts', function(){
         echo "hello contact";
     });
     Route::get('/page/{page}', function(Request $request, $page){
        return "hello Page {$page}";
     });
});

In MiddleWare File I did

public function handle(Request $request, Closure $next)
{
    if (!array_key_exists($request->segment(1), config('translatable.locales'))) {
    $segments = $request->segments();

    $segments = Arr::prepend($segments, config('app.fallback_locale'));
    
    // Remove the session check as we don't have access to session yet
    /*if($request->session()->has('language')) {
        $segments[0] = session('language');
    }*/

    return redirect()->to(implode('/', $segments));
}

    return $next($request);
}

Now in Kennel.php File for Middleware, Add your middleware class in the $middleware array

/**
 * The application's global HTTP middleware stack.
 *
 * These middleware are run during every request to your application.
 *
 * @var array
 */
protected $middleware = [
    ...
    \App\Http\Middleware\Localized::class, //This is the Localized Middlewere class
];

Then try access site.test/page/1000 ... it will be redirected to site.test/{app.fallback_locale}/page/1000. In my case site.test/en/page/1000

UPDATE

After reading through this issue on git for laravel, I then thought of adding the session before the Localized middle class and it worked. I'm not sure if this is good practice but it got the job done.

In MiddleWare File I did

public function handle(Request $request, Closure $next)
{
    if (!array_key_exists($request->segment(1), config('translatable.locales'))) {
    $segments = $request->segments();

    $segments = Arr::prepend($segments, config('app.fallback_locale'));
    
    // We can have session back on
    if($request->session()->has('language')) {
        $segments[0] = session('language');
    }

    return redirect()->to(implode('/', $segments));
}

    return $next($request);
}

Now in Kennel.php File for Middleware, Add Session middleware before Localized Middleware class

/**
 * The application's global HTTP middleware stack.
 *
 * These middleware are run during every request to your application.
 *
 * @var array
 */
protected $middleware = [
    ...
    \Illuminate\Session\Middleware\StartSession::class,
    \App\Http\Middleware\Localized::class, //This is the Localized Middlewere class
];
Sign up to request clarification or add additional context in comments.

6 Comments

But I need save session :)) And your solution will affect all routes, but I need affect only routes, which I want.
Yep, but problem with routes still exists, I don't need affect all routes. I have routes from laravel nova, And my nova is not work.
When I access to: site.com/nova he redirect's me on site.com/en/nova. And I get 404 not found... On /nova I don't need middleware
You can use if check to exclude those routes (you already have access to Nova in the Middleware (i.e $segments[1] )
No.. I have routes that should not be involved, I cannot check them all
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.