Skip to content
Advertisement

Redirect to default locale if not given and fortify routes

I made a middleware to change the language of my website but now I am facing two problems, so I would like your help to solve them:

  1. when the user types for instance http://mywebiste/en/operations the site is displayed in English, but if I omit the locale on the URL a 404 page is thrown. My intention is to automatically redirect my routes with a default locale or the last locale set by the user, for instance, if the user type http://mywebiste/operations, then it should directly go to http://mywebiste/en/operations.

  2. The second problem is regarding some Fortify routes. One case is the 2F auth, I managed to implement the two-factor authentification with Fortify prior I set the language switcher functionality, but now when the button “enable” 2F it asks for the password confirmation screen, however since it is registered under the locale group it gives me a 404 page as well (http://mywebiste/user/confirm-password) and not (http://mywebiste/en/user/confirm-password). The same applies to other routes, so I would like to manipulate this redirection handled automatically with Fortify.

The relevant code I changed so far…

My middleware setLocale.php

    public function handle(Request $request, Closure $next)
    {
        if (empty($request->locale)) 
        {
            URL::defaults(['locale' => app()->getLocale()]);        
            return redirect(config('app.locale') . '/' . request()->path());
        }
        App::setLocale($request->locale);
        return $next($request);
    }

web.php

Route::group([
    'prefix' => '{locale?}',
    'where' => ['locale' => '[a-zA-Z]{2}'],
    'middleware' => 'setlocale'
], function () {
    // routes from fortify
    require(base_path('vendor/laravel/fortify/routes/routes.php'));

    Route::get('operations', 'EcmrController@view_records');

    //... other routes
});

Kernel.php

protected $middlewareGroups = [
        'web' => [
          ...
            AppHttpMiddlewareSetLocale::class,
        ],

        'api' => [
            LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            IlluminateRoutingMiddlewareSubstituteBindings::class,
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
       ...
        'setlocale' => AppHttpMiddlewareSetLocale::class,
    ];

    /**
     * The priority-sorted list of middleware.
     *
     * Manually copied from IlluminateFoundationHttpKernel class and edited accordingly
     *
     * @var array
     */
    protected $middlewarePriority = [
       ...
        AppHttpMiddlewareSetLocale::class,
        IlluminateRoutingMiddlewareSubstituteBindings::class,
        IlluminateAuthMiddlewareAuthorize::class,
    ];

Advertisement

Answer

After some research I got the second problem done.

Firstly I copied the Fortify routes on my web.php and added the following code on the FortifyServiceProvider.php.

public function register()
{
    Fortify::ignoreRoutes();
}

Then I had to create a new middleware to handle the password confirmation before the user enable/disable the 2F function and register it on the Kernel.php.

protected $routeMiddleware = [
    'auth' => AppHttpMiddlewareAuthenticate::class,
    'auth.basic' => IlluminateAuthMiddlewareAuthenticateWithBasicAuth::class,
    'cache.headers' => IlluminateHttpMiddlewareSetCacheHeaders::class,
    'can' => IlluminateAuthMiddlewareAuthorize::class,
    'guest' => AppHttpMiddlewareRedirectIfAuthenticated::class,
    // edited the password.confirm middleware to redirect to the locale + url 
    'password.confirm' => AppHttpMiddlewareRequirePassword::class,
    'setlocale' => AppHttpMiddlewareSetLocale::class,
    ...
];

This new RequirePassword.php middleware redirects the user to the route + the locale, so it successfully goes to the desired path.

The Require Password I copied and edited only the handle method

public function handle($request, Closure $next, $redirectToRoute = null)
{
    if ($this->shouldConfirmPassword($request)) {
        if ($request->expectsJson()) {
            return $this->responseFactory->json([
                'message' => 'Password confirmation required.',
            ], 423);
        }

        return $this->responseFactory->redirectGuest(
            $this->urlGenerator->route($redirectToRoute ?? 'password.confirm', app()->getLocale())
        );
    }

    return $next($request);
}

It helped on other problems I had using Fortify and locale, such as the email verification. I repeated the same process for it as well:

  1. copied the middleware,
  2. changed the handle method,
  3. registered the new one on Kernel.php.
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement