简体   繁体   中英

How to set default locale without prefix in Laravel 8

I write a multilanguage application. I don't want to use locale prefix for the default language, so for example my URL structure should be like this:

https://example.com/about-us
https://example.com/contant
https://example.com/es/about-us
https://example.com/es/contant
https://example.com/de/about-us
https://example.com/de/contant

I use Route::group to group my routes by locale prefix:

Route::group([
    'prefix' => '{locale}',
    'where' => ['locale' => '[a-z]{2}'],
    'middleware' => 'setlocale'
], function () {
    Route::get('/{page}', [PageController::class, 'show'])->name('page');
});

in my middleware setlocale I set locale and prefix for URLs:

    public function handle(Request $request, Closure $next)
    {
        if (in_array($request->segment(1), ['es', 'de'])) {
            URL::defaults(['locale' => $request->segment(1)]);
            app()->setLocale($request->segment(1));
        } else {
            URL::defaults(['locale' => 'en']);
            app()->setLocale('en');
        }
        return $next($request);
    }

and then my controller prints the data:

class PageController extends Controller
{
    public function show($lang, Page $page)
    {
        dd($page);
    }
}

This works well with de and es prefixes, but not without them - for English lang. I tried to copy Route::get('/{page}', [PageController::class, 'show'])->name('page'); & paste it outside the Route::group , but then just one argument is passed to PageController and I get following error:

Too few arguments to function App\Http\Controllers\PageController::show(), 1 passed in /Users/mati/Sites/laravel-app/vendor/laravel/framework/src/Illuminate/Routing/Controller.php on line 54 and exactly 2 expected

You could do something like this.

Check that first slug is language prefix and is not default language then use it like prefix, else use nothing (null).

Route::prefix(parseLocale())->group(function () {
     Route::get('/{page}', [PageController::class, 'show'])->name('page');
}

function parseLocale(){
    $locale = request()->segment(1);
    $locales = config('translatable.locales');
    $default = config('app.fallback_locale');

    if ($locale !== $default && in_array($locale, $locales)) {
        app()->setLocale($locale);
        return $locale;
    }
}

In this example config('translatable.locales') is array of locales.

Then drop useless $lang param from controller:

class PageController extends Controller
{
    public function show(Page $page)
    {
        dd($page);
    }
}

This full solution:

https://example.com/
https://example.com/contact
https://example.com/en/
https://example.com/en/contact

file 'routes/web.php'

if(!function_exists('parseLocale')) {
    function parseLocale()
    {
        $locale = request()->segment(1);
        if (in_array($locale, ['js', 'css'])) // for speed up :)
            return $locale;
        if (array_key_exists($locale, config('languages'))) {
            app()->setLocale($locale);
            return $locale;
        }
        app()->setLocale('es');  // this default locale
        return '/';
    }
}

/** Here route */
Route::prefix(parseLocale())->group(function () {

Route::get('/', [App\Http\Controllers\PropertiesController::class, 'home']);
Route::get('/contact', function () {
        return view('contact');
    });

});

file 'config/languages.php'

<?php

return [
    'en' => [
        'display' => 'English',
    ],
    'es' => [
        'display' => 'Español',
    ],
];

files *.blade.php

<a href="{{ $init['lang'] }}">Home</a>
<a href="{{ $init['lang'] }}contact">Contact</a>

file 'app/Providers/AppServiceProvider.php'

public function boot()
    {
        View::composer('*', function ($view) {
                $view->with('init', $this->loadTranslate());
        });
    }

 private function loadTranslate()
    {
$locale = app()->getLocale();
        if ($locale == 'es') $lang = '';
        else $lang = $locale . '/';

return [
            'lang' => '/' . $lang,
        ];
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM