'Laravel Multi-language routes without prefix

Currently, my system is using 2 languages which is English and German. my goal is to browse following routes by switching between the mentioned language -

base-url/contact - for english
base-url/kontakte - for german

Currently, I have required routes file in the resource folder, where I have put the necessary translated words.

resources/lang/en/routes.php
resources/lang/de/routes.php

In web.php I have currently -

Route::get(r('contact'), 'TestController@index')->name('contact');

by r() helper function I am getting the active translated word.

On my user table, I have locale column where I am storing the active language when I am updating the language from user profile -

\Session::put('locale', $request->input('locale'));

I have created a middleware Localization where I have currently -

public function handle($request, Closure $next)
    {
        if ( \Session::has('locale')) {
            \App::setLocale(\Session::get('locale'));
            Carbon::setLocale(\Session::get('locale'));
        }

        return $next($request);
    }

Currently, the code is working fine for blade translated word. but the translated routes are not working. whenever I switch and visit any route, it gives me 404 error. but if I restart the server by PHP artisan serve, it works with changed language.

So how fix the issue?



Solution 1:[1]

:) Try to put \App::setLocale(\Session::get('locale') in the beginning of the routes file (routes.php, or web.php/api.php)

Solution 2:[2]

With PHP 8.1.0, Laravel 9.x

resources/lang/en/routes.php:

return [
    'post' => '/post/',
    'product' => '/product/',
    'contact' => '/contact/',
    'aboutUs' => '/about-us/'
];

Create LanguageType enum:

enum LanguageType: string
{
    case EN = 'en';
    case DE = 'de';

    public function label(): string
    {
        return trans(match ($this) {
            self::EN => 'English',
            self::DE => 'German',
        });
    }
}

In web.php:

Route::get('{contactTranslation}', [ContactController::class, 'index']);
Route::get('{aboutUsTranslation}', [AboutUsController::class, 'index']);
Route::get('{productTranslation}', [ProductController::class, 'index']);
Route::get('{postTranslation}', [PostController::class, 'index']);
//...

In RouteServiceProvider.php/boot(), add:

foreach (trans('routes') as $key => $value) {
    Route::pattern($key . 'Translation', $this->getTranslation($key));
}

And function:

private function getTranslation($slug): string
{
    $slugList = collect();
    foreach (LanguageType::cases() as $language) {
        $slugList = $slugList->merge(trim(trans('routes.' . $slug, [], $language->value), '/'));
    }

    return $slugList->implode('|');
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rob Mkrtchyan
Solution 2