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

问题描述 投票:0回答:2

我正在 Laravel 10 中开发本地化。当我触发更改 Localization 的标志时,然后在页面中显示错误。

谁能告诉我问题出在哪里?


错误信息

在本地化中调用未定义的方法 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');

这是我的 Blade 代码

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

我不明白为什么会这样。

laravel localization laravel-middleware laravel-localization
2个回答
1
投票

在你的路线中,它应该是 LocalizationController 而不是。尝试:

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

1
投票

我看到关于使用不同模块的一些混淆:MiddlewareController

中间件

中间件在与路由关联的任务执行之前运行。。这包括启动

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

然后在路由中,需要调用

setLanguage
LocalizationController::class
函数,传递语言

routes/web.php

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

如果要用中间件解决,就没有机会传递这样的变量。您需要知道设置的语言是来自某处的

en
。最好在会话中保存设置的语言,因为您可以在中间件中访问存储的值。但是,如果您之前将其保存为
selected_language
,以后请注意不要将所选语言查找为
locale

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 中设置一个中间件为特定路由运行?

默认情况下,

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

app/Http/Kernel.php

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

总结

代码将如何运行?

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

额外

如果您将语言存储在 cookie 而不是会话中,则下次访问该页面时,它将根据所选语言加载。
会话在 X 时间不活动后被删除。 (在

config/session.php
lifetime
配置,2小时后默认删除)

© www.soinside.com 2019 - 2024. All rights reserved.