如何在Laravel中实现双语言切换及切换按钮动态展示功能
Laravel双语言切换功能实现方案
1. 新增Locale设置中间件,优化路由冗余
首先解决你现有路由重复编写locale判断的问题,统一用中间件处理全局语言设置。
1.1 创建中间件
运行命令:php artisan make:middleware SetLocale
编辑app/Http/Middleware/SetLocale.php代码:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class SetLocale { public function handle(Request $request, Closure $next): Response { $locale = $request->route('locale'); $availableLocales = config('app.available_locales'); // 校验locale合法性 if ($locale && in_array($locale, $availableLocales)) { app()->setLocale($locale); session()->put('applocale', $locale); } else { // 无合法locale时优先读取session存储值,否则用系统默认语言 $defaultLocale = session()->get('applocale', config('app.fallback_locale')); app()->setLocale($defaultLocale); } // 移除路由参数中的locale,避免后续控制器需要强制接收该参数 $request->route()->forgetParameter('locale'); return $next($request); } }
1.2 注册中间件
编辑app/Http/Kernel.php,在web中间件组的数组中追加条目:
\App\Http\Middleware\SetLocale::class,
1.3 重构路由
替换你现有的重复路由为统一前缀的路由组,同时新增语言切换路由:
// 语言切换路由,不需要locale前缀 Route::get('/switch-lang/{lang}', [\App\Http\Controllers\LanguageController::class, 'switchLang'])->name('switch.lang'); // 带locale前缀的业务路由组 Route::prefix('{locale?}')->group(function () { Route::get('/', function () { return view('home'); }); Route::get('/contact', function () { return view('contact'); }); // 其余业务路由都可以放在这个组里,不需要再单独处理locale逻辑 });
2. 修正LanguageController代码
你原有控制器的配置读取逻辑、跳转逻辑不符合当前需求,修改为以下代码:
<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Redirect; use Illuminate\Support\Facades\Session; class LanguageController extends Controller { public function switchLang($lang) { $availableLocales = Config::get('app.available_locales'); if (in_array($lang, $availableLocales)) { Session::put('applocale', $lang); } // 替换当前URL中的locale部分,实现切换语言后停留在当前页面 $segments = collect(request()->segments()); $availableLocaleValues = array_values($availableLocales); if (in_array($segments->first(), $availableLocaleValues)) { $segments->shift(); } $newUrl = url($lang . '/' . $segments->implode('/')); return Redirect::to($newUrl); } }
3. 全局共享切换按钮所需数据
因为导航栏是所有页面通用的,在app/Providers/AppServiceProvider.php的boot方法中新增全局视图数据共享逻辑,不需要每个页面单独传参:
public function boot() { view()->composer('*', function ($view) { $currentLocale = app()->getLocale(); $availableLocales = config('app.available_locales'); // 因为仅支持两种语言,直接过滤掉当前语言即可拿到待切换的语言信息 $targetLangInfo = collect($availableLocales)->reject(function ($code) use ($currentLocale) { return $code === $currentLocale; }); $view->with([ 'targetLangCode' => $targetLangInfo->first(), 'targetLangName' => $targetLangInfo->keys()->first(), ]); }); }
4. 编写导航栏切换按钮
在你的公共导航栏blade模板中直接插入以下代码即可:
<a href="{{ route('switch.lang', $targetLangCode) }}" class="lang-switch">{{ $targetLangName }}</a>
效果验证
- 访问
/en路径时,按钮显示German,点击后跳转到/de对应页面,按钮自动变更为English - 访问
/de/contact路径时,按钮显示English,点击后跳转到/en/contact页面,完全符合你的需求。
内容的提问来源于stack exchange,提问作者bobderbaumeister
相关产品推荐
相关产品推荐

