skip to Main Content

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 AppHttpMiddlewareLocalizationMiddleware::setLanguage() in Localization


Here is my LocalizationController Controller

    {
        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.

2

Answers


  1. In your route, it should be LocalizationController instead. Try:

    Route::get('locale/{locale}',[LocalizationController::class, 'setLanguage'])->name('locale');
    
    Login or Signup to reply.
  2. I see some confusion regarding the use of different modules: Middleware, Controller

    Middleware

    The Middleware runs before the task associated with the route is executed.. This includes starting a Session or checking authentication for an /admin route.

    Controller

    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.

    enter image description here

    Setting the Language

    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' => [
            // ...
            AppHttpMiddlewareLocalizationMiddleware::class,
        ],
        // ...
    ];
    

    Summary

    How will the code run?

    1. By default, there is no language set, so every route where LocalizationMiddleware is set will prioritize English language (see code).
    2. I choose the German language: 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.
    3. Due to the redirection, the previous link (from where I called the language change) is reloaded, but now the 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.

    Extra

    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)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search