Reputation: 47
I am developing a localization in Laravel 10. When I triggered to change the flag of Localization Then Error Show in Page.
Can anyone tell Just where is the problem?
Error Message
Call to undefined method App\Http\Middleware\LocalizationMiddleware::setLanguage() in Localization
Here is my LocalizationController
Controller
public function setLanguage($locale)
{
App::setLocale($locale);
Session::put('locale', $locale);
return redirect()->back();
}
Here is my LocalizationMiddleware
public function handle(Request $request, Closure $next): Response
{
// Set Locale in this Middleware
App::setLocale(session()->get('selected_language') ?? 'en');
return $next($request);
}
Here is my route
Route::get('locale/{locale}',[LocalizationMiddleware::class, 'setLanguage'])->name('locale');
And here is my Blade code
<div class="dropdown ms-1 topbar-head-dropdown header-item">
<button type="button" class="btn btn-icon btn-topbar btn-ghost-secondary rounded-circle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img id="header-lang-img" src="{{ asset('/') }}els/images/flags/us.svg" alt="Header Language" height="20" class="rounded">
</button>
<div class="dropdown-menu dropdown-menu-end">
<!-- English language -->
<a href="locale/en" class="dropdown-item notify-item language py-2" data-lang="en" title="English">
<img src="{{ asset('/') }}els/images/flags/us.svg" alt="user-image" class="me-2 rounded" height="18">
<span class="align-middle">English</span>
</a>
<!-- German Language -->
<a href="{{ url('locale/de') }}" class="dropdown-item notify-item language" data-lang="gr" title="German">
<img src="{{ asset('/') }}els/images/flags/germany.svg" alt="user-image" class="me-2 rounded" height="18"> <span class="align-middle">Deutsche</span>
</a>
</div>
</div>
I don't understand why is this happening.
Upvotes: -1
Views: 6104
Reputation: 7532
I see some confusion regarding the use of different modules: Middleware, Controller
The Middleware runs before the task associated with the route is executed.. This includes starting a Session
or checking authentication for an /admin
route.
The Controller is the last thing that runs when a route is called. For example, displaying a blade, saving a record in the database, querying some data, etc.
Now, let's focus on the original problem: you want to set the language so that the appropriate language content is loaded on the website.
You want the page to switch to English when a link like /locale/en
is called. So, you want to do this after the link is called: using a Controller is recommended.
You can pass variables to the Controller, so you can also pass the language.
app/Http/Controllers/LocalizationController.php
// ...
class LocalizationController extends Controller
{
public function setLanguage (Request $request)
{
// Save selected Locale to current "Session"
$locale = $request->locale ?? 'en';
// App::setLocale($locale); --> There is no need for this here, as the middleware will run after the redirect() where it has already been set.
$request->session()->put('locale', $locale);
return redirect()->back();
}
}
Then in the route, you need to call the setLanguage
function of LocalizationController::class
and pass the language.
routes/web.php
Route::get(
'locale/{locale}',
[LocalizationController::class, 'setLanguage']
)->name('locale');
If you want to solve it with middleware, you won't have the opportunity to pass such variables. You need to know that the set language is en
from somewhere. It's a good idea to save the set language in the session because you can access the stored values in the middleware. However, be careful in the future not to look for the selected language as selected_language
if you saved it as locale
before.
app/Http/Middlewares/LocalizationMiddleware.php
// ...
class LocalizationMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Set Locale in this "Request"
$locale = $request->session()->get('locale') ?? 'en';
app()->setLocale($locale);
return $next($request);
}
}
How can you set a middleware to run for a specific route in Laravel?
By default, all middleware specified in the web
middleware group declared in app/Http/Kernel.php
will run for every route. (Why? See boot()
function in app/Providers/RouteServiceProvider.php
, where we load routes/web.php
)
So, you need to add your own LocalizationMiddleware
to the web
group as follows:
app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
// ...
\App\Http\Middleware\LocalizationMiddleware::class,
],
// ...
];
How will the code run?
LocalizationMiddleware
is set will prioritize English language (see code).de
, in reality, I called the /locale/de
route, which triggered the LocalizationController
setLanguage
function. In my session, the value of the locale
key was set to de
, and at the end of the function, I was redirected back to the previous link. So, as a user, I didn't notice anything.LocalizationMiddleware
runs again where the value associated with the locale
key is de
, so the middleware overrides the default language to German, and finally, the content is loaded in German from the /lang
folder.If you store the language in a cookie instead of a session, the next time you visit the page, it will be loaded based on the selected language.
The session is deleted after X time of inactivity. (It is configured in config/session.php
in lifetime
and deleted by default after 2 hours)
Upvotes: 2
Reputation: 2315
In your route, it should be LocalizationController instead. Try:
Route::get('locale/{locale}',[LocalizationController::class, 'setLanguage'])->name('locale');
Upvotes: 1