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:
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 typehttp://mywebiste/operations
, then it should directly go tohttp://mywebiste/en/operations
.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:
- copied the middleware,
- changed the handle method,
- registered the new one on Kernel.php.