如何在Laravel中的每个请求中通过Session设置“app.locale”?

dohp0rv5  于 2023-04-22  发布在  其他
关注(0)|答案(2)|浏览(133)

我正在Laravel 10中开发本地化。当我触发更改本地化标志时,页面中显示错误。
谁能告诉我问题出在哪里?
错误信息

本地化调用未定义的方法App\Http\Middleware\LocalizationMiddleware::setLanguage()

这是我的LocalizationController控制器

{
        App::setLocale($locale);
        Session::put('locale', $locale);

        return redirect()->back();
    }

这是我的LocalizationMiddleware

public function handle(Request $request, Closure $next): Response
    {
        // Set Locale in this Middleware
        App::setLocale(session()->get('selected_language') ?? 'en');

        return $next($request);
    }

这是我的路线

Route::get('locale/{locale}',[LocalizationMiddleware::class, 'setLanguage'])->name('locale');

这是我的刀锋密码

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

我不明白为什么会这样。

vojdkbi0

vojdkbi01#

在您的路由中,它应该是LocalizationController。请尝试:

Route::get('locale/{locale}',[LocalizationController::class, 'setLanguage'])->name('locale');
58wvjzkj

58wvjzkj2#

我看到一些关于不同模块的使用的混淆:中间件控制器

中间件

中间件在路由关联任务执行前运行,包括启动Session或检查/admin路由的鉴权。

控制器

**Controller是调用路由时最后运行的东西。**例如,显示刀片,保存数据库中的记录,查询一些数据等。

设置语言

现在,让我们专注于最初的问题:您希望设置语言,以便在网站上加载相应的语言内容

您希望在调用类似/locale/en的链接时,页面切换为英语,因此,您希望在调用链接后执行此操作:建议使用Controller

你可以把变量传递给Controller,所以你也可以传递语言。

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();
     }
}

然后在路由中,需要调用LocalizationController::classsetLanguage函数,并传递语言。

routes/web.php

Route::get(
    'locale/{locale}',
    [LocalizationController::class, 'setLanguage']
)->name('locale');

如果你想用中间件来解决,你就没有机会传递这样的变量了,你需要从某个地方知道set语言是en,在session中保存set语言是个好主意,因为你可以访问中间件中存储的值,但是,如果您以前将所选语言保存为locale,请注意以后不要将其查找为selected_language

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);
    }
}

如何在Laravel中设置中间件为特定路由运行?

默认情况下,在app/Http/Kernel.php中声明的web中间件组中指定的所有中间件都将为每个路由运行。(为什么?请参见app/Providers/RouteServiceProvider.php中的boot()函数,我们在其中加载routes/web.php)因此,您需要将自己的LocalizationMiddleware添加到web组,如下所示:

app/Http/Kernel.php

protected $middlewareGroups = [
    'web' => [
        // ...
        \App\Http\Middleware\LocalizationMiddleware::class,
    ],
    // ...
];

摘要

代码将如何运行?
1.默认情况下,没有设置语言,因此设置了LocalizationMiddleware的每个路由都将优先考虑英语语言(参见代码)。
1.我选择德语:de,实际上,我调用了/locale/de路由,这触发了LocalizationControllersetLanguage函数。在我的会话中,locale键的值被设置为de,在函数结束时,我被重定向回上一个链接。所以,作为用户,我没有注意到任何事情。
1.由于重定向,重新加载了之前的链接(从我调用语言更改的地方),但是现在LocalizationMiddleware再次运行,其中与locale键关联的值是de,因此中间件将默认语言覆盖为德语,最后,从/lang文件夹以德语加载内容。

额外

如果您将语言存储在cookie而不是会话中,则下次访问该页面时,将根据所选语言加载该页面。
会话不活动X小时后删除(lifetimeconfig/session.php配置,默认2小时后删除)

相关问题