Setting a Multilanguage URL for a custom 404 page in a Laravel project
Hello!
I'm currently working on a project in Laravel. I've customized the SetLanguage.php middleware to be able to redirect user in case of a wrongly entered URL address in my website. However, the 404 page remains a huge problem. I have to find a way how to make it so that when my website changes its language from its language bar, the URL of the 404 page also changes to the current locale.
Here's my code so far (they are two classes:)
SetLanguage.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Helpers\ErrorRedirectHelper;
use App\Services\EntityPageService;
class SetLanguage
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// Checking the user's selected language and storing it in a cookie
$language = $request->language;
$langPrimary = config('site_vars.lang_primary');
$langSecondary = config('site_vars.lang_secondary');
$supportedLanguages = [$langPrimary, $langSecondary];
foreach($supportedLanguages as $supportedLanguage) {
if (in_array($language, $supportedLanguages)) {
setcookie("lang", $language, time() + 18000, "/");
app()->setLocale($language);
}
}
$prefixes = explode("/", $request->path());
$supportedPrefixes = ["/", "livewire", "update", "/$langPrimary", $langPrimary, "/$langSecondary", $langSecondary, "index", "contact", "content", "development", "contact-form", "createCategory", "category", "subcategory"];
if (isset($prefixes[0])) {
if (in_array($prefixes[0], $supportedPrefixes) || $prefixes[0] === "") {
return $next($request);
} else {
$id = config('site_vars.404_NOT_FOUND_PAGE');
$errorHelper = new ErrorRedirectHelper(app(EntityPageService::class));
$params = $errorHelper->fetchErrorPageData($id);
$errorPageUrl = $errorHelper->toErrorPage($params);
return redirect($errorPageUrl);
}
}
return $next($request);
}
}
Helpers\ErrorRedirectHelper.php
<?php
namespace App\Helpers;
use App\Services\EntityPageService;
class ErrorRedirectHelper
{
protected $entityPageService;
public function __construct(EntityPageService $entityPageService)
{
$this->entityPageService = $entityPageService;
}
public function fetchErrorPageData($pageId, $locale = null) {
$productURL = '';
$productURLSecondaryLang = '';
$lang = $_COOKIE['lang'] ?? config('site_vars.lang_primary');
$chosenEntity = $this->entityPageService->loadChosenEntity($pageId);
if (isset($chosenEntity[0])) {
$chosenEntityId = $chosenEntity[0]['id'];
$categoryTableCol = $lang === config('site_vars.lang_primary') ? 'name' : 'nameEN';
$subcategoryTableCol = $lang === config('site_vars.lang_primary') ? 'name' : 'nameEN';
$entityTableCol = $lang === config('site_vars.lang_primary') ? 'contentBG' : 'contentEN';
if (!empty($chosenEntity[0]['productURL'])) {
$productURLSegments = explode('/', trim($chosenEntity[0]['productURL'], '/'));
if (count($productURLSegments) >= 2) {
$productURL = $productURLSegments[count($productURLSegments) - 2];
}
}
if (!empty($chosenEntity[0]['productURLSecondaryLang'])) {
$productURLSegments = explode('/', trim($chosenEntity[0]['productURLSecondaryLang'], '/'));
if (count($productURLSegments) >= 2) {
$productURLSecondaryLang = $productURLSegments[count($productURLSegments) - 2];
}
}
$customEntityURL = $lang === config('site_vars.lang_primary') ? $productURL : $productURLSecondaryLang;
// These are user-defined parameters for the 404 page. The user can customize them at will and even pick 2 language variants for them.
$chosenCategories = $this->entityPageService->loadChosenCategories($chosenEntity[0]['categoryId']);
$chosenSubcategories = $this->entityPageService->loadChosenSubcategories($chosenEntity[0]['subcategoryId']);
$chosenEntityElements = $this->entityPageService->loadChosenEntityElements($chosenEntity[0]['id']);
$chosenEntityTitle = $chosenEntityElements->firstWhere('elementId', 9);
$category = isset($chosenCategories[$categoryTableCol])
? $chosenCategories[$categoryTableCol]
: (isset($chosenCategories[0][$categoryTableCol]) ? $chosenCategories[0][$categoryTableCol] : 'ERRORS');
$subcategory = $chosenSubcategories[0][$subcategoryTableCol] ?? '404_-_NON-EXISTENT_CONTENT';
$entity = !empty($customEntityURL)
? $customEntityURL
: (!empty($chosenEntityTitle?->$entityTableCol)
? $chosenEntityTitle->$entityTableCol
: 'The_requested_page_does_not_exist');
return [
'lang' => $lang,
'category' => str_replace([' ', '%20'], '_', $category),
'subcategory' => str_replace([' ', '%20'], '_', $subcategory),
'entity' => str_replace([' ', '%20'], '_', $entity),
'id' => $pageId ?? 121,
];
}
// fallback if no entity is found
return [
'lang' => $_COOKIE['lang'] ?? config('site_vars.lang_primary'),
'category' => 'ERRORS',
'subcategory' => '404_-_NON-EXISTENT_CONTENT',
'entity' => 'The_requested_page_does_not_exist',
'id' => $pageId ?? 121,
];
}
public function toErrorPage(array $params = [])
{
$lang = $params['lang'];
$category = $params['category'];
$subcategory = $params['subcategory'];
$entity = $params['entity'];
$id = $params['id'];
return "/$lang/$category/$subcategory/$entity/$id";
}
}
I'm open to any suggestions if anyone would be able to help. Here's some more info about my intent in case the logic is confusing: I'm intending to check if the user is entering wrong URL addresses in my website and then redirect them to my custom 404 page. The user would probably enter something like 'www.mywebsite.com/jfkjfejk', 'www.mywebsite.com/en/jfkjfejk', 'www.mywebsite.com/jfkjfejk/htththth' and during all of these similiar cases, the website should always redirect to my 404 page which is linked to an existing controller method. My task is to find how to change my code so that it can surely save the preferred user language even if the page's URL looks something like this 'www.mywebsite.com/a/jfkjfejk/0'. My project has its routes configured like this:
-- routes/web.php
...
Route::group(['prefix' => '{language}'], function () {
Route::get('index', [App\Http\Controllers\HomeController::class, 'index']);
});
Route::fallback(function () {
return redirect('/{language}/ERRORS/404_-_NON-
EXISTENT_CONTENT/The_requested_page_does_not_exist/121');
});
Please or to participate in this conversation.