Search code examples
phplaravelurl-routinglaravel-blade

Laravel language switcher, pass additional parameters to a route


I really can't think of an elegant solution to fix this problem so here it is:

I followed this tutorial https://www.youtube.com/watch?v=KqzGKg8IxE4 to create a localization option for my website. However, integrating the auth was cancer and now I'm faced with an even greater issue regarding the routing for pages that require a get parameter.

Here is my blade code inside the app.blade.php for the language switcher:

                            <language-switcher
                                locale="{{ app()->getLocale() }}"
                                link-en="{{ route(Route::currentRouteName(), 'en') }}"
                                link-bg="{{ route(Route::currentRouteName(), 'bg') }}"
                            ></language-switcher>

And here are some of my routes

Route::redirect('/', '/en');

Route::get('email/verify', 'Auth\VerificationController@show')->name('verification.notice');
Route::get('email/verify/{id}/{hash}', 'Auth\VerificationController@verify')->name('verification.verify');
Route::get('email/resend', 'Auth\VerificationController@resend')->name('verification.resend');


Route::group([
    "prefix" => '{language}',
    'where' => ['language' => '(en||bg)'],
], function () {

    //Auth routes
    Auth::routes();

    //Returns to home
    Route::get('/', 'HomeController@index')->name('home');

    //Handles the faq routes
    Route::resource('faq', 'FaqController');

});


Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
Route::post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update');

});

It works well for pages that don't require any get parameters to work with ex: Login / Register / Home page, however if i use something that requires like, faq.edit, which takes an {id} parameters - the language switcher will throw an error because I haven't passed an {id} parameter to it.

The only solution I can think of is adding the language-switcher inside the child blade view and from there I pass the required parameters, however that implies that I have to add the language-switcher to every child view instead of only once at the parent.


Solution

  • You can achieve it with the following steps:

    • Implement a URL generator macro which will make much easier to generate your URLs which must be identical except language
    • Get the current route's parameters
    • Merge the chosen language into them
    <?php
    
    namespace App\Providers;
    
    use Illuminate\Routing\UrlGenerator;
    use Illuminate\Support\ServiceProvider;
    
    class AppServiceProvider extends ServiceProvider
    {
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
            UrlGenerator::macro('toLanguage', function (string $language) {
                $currentRoute = app('router')->current();
                $newRouteParameters = array_merge(
                    $currentRoute->parameters(), compact('language')
                );
                return $this->route($currentRoute->getName(), $newRouteParameters);
            });
        }
    }
    

    And in your Blade file

    @inject('app', 'Illuminate\Contracts\Foundation\Application')
    @inject('urlGenerator', 'Illuminate\Routing\UrlGenerator')
    
    <language-switcher
        locale="{{ $app->getLocale() }}"
        link-en="{{ $urlGenerator->toLanguage('en') }}"
        link-bg="{{ $urlGenerator->toLanguage('bg') }}"
    ></language-switcher>
    

    You'll notice I used contracts injection instead of using facades. More informations here https://laravel.com/docs/7.x/contracts#contracts-vs-facades

    And if you don't known Laravel macros, more informations here https://tighten.co/blog/the-magic-of-laravel-macros