我正在 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>
我不明白为什么会这样。
在你的路线中,它应该是 LocalizationController 而不是。尝试:
Route::get('locale/{locale}',[LocalizationController::class, 'setLanguage'])->name('locale');
我看到关于使用不同模块的一些混淆:Middleware,Controller
中间件在与路由关联的任务执行之前运行。。这包括启动
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,
],
// ...
];
代码将如何运行?
LocalizationMiddleware
的每条路线都将优先使用英语(见代码)。de
,实际上我调用了/locale/de
路由,触发了LocalizationController
setLanguage
函数。在我的会话中,locale
键的值被设置为 de
,在函数结束时,我被重定向回上一个链接。所以,作为用户,我什么都没注意到。LocalizationMiddleware
再次运行,其中与locale
键关联的值是de
,因此中间件覆盖默认值语言为德语,最后,内容从 /lang
文件夹中以德语加载。如果您将语言存储在 cookie 而不是会话中,则下次访问该页面时,它将根据所选语言加载。
会话在 X 时间不活动后被删除。 (在
config/session.php
中lifetime
配置,2小时后默认删除)