You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 09:06:01