Laravel怎么配置多语言路由_Laravel国际化URL教程【适配】

1次阅读

laravel多语言路由需将locale作为url首段路径显式定义,通过route::prefix()或{locale}参数+where约束实现,route()必须手动传入locale参数才能生成带前缀的url,且路由组须置于最前避免被泛匹配拦截。

Laravel怎么配置多语言路由_Laravel国际化URL教程【适配】

路由里怎么加语言前缀

Laravel 的多语言路由本质是把 locale 当成 URL 第一段路径来处理,不是靠中间件动态切换,而是靠路由分组显式声明。不这么做,route() 生成的链接永远缺语言段,本地化 URL 就断了。

正确做法是用 Route::prefix() + Route::middleware('localization') 组合,但注意:Laravel 官方没内置 localization 中间件,得自己写或用 laravel-lang/lang 这类包——更稳妥的是直接在 RouteServiceProvider 的 boot() 里按语言循环注册路由组。

  • 别在 web.php 里手动写 /en/xxx/zh/xxx 两套路由,维护爆炸
  • 别用 URL::setRoot() 或改 APP_URL 模拟多语言,生成的 route('home') 仍不带 locale
  • 语言前缀必须和 config('app.locale') 保持一致,否则 trans() 找不到对应语言包

如何让 route() 自动带上当前语言

route() 默认不感知当前请求的语言,它只认命名路由和参数。要让它输出带 /zh//en/ 的 URL,必须把 locale 当作必需参数传进去,且路由定义里得声明它。

比如定义路由时写 Route::get('/news', [NewsController::class, 'index'])->name('news');,那 route('news') 永远是 /news;必须改成 Route::get('/{locale}/news', ...)->where('locale', '[a-z]{2}')->name('news');,再调用 route('news', ['locale' => app()->getLocale()]) 才行。

  • 别依赖“自动推断”,Laravel 不会从 sessioncookie 里猜 locale 并塞进 route()
  • ->where('locale', 'en|zh|ja') 比正则更安全,避免匹配到非法值导致 404
  • 如果用了 fallback_locale,记得在生成 URL 前确认 app()->getLocale() 真是用户选的那个,不是回退后的默认值

为什么 locale 参数总被忽略或 404

常见原因是路由顺序冲突:Laravel 匹配路由是自上而下,一旦有个泛匹配的 /{any} 路由(比如 Vue routercatch-all),它就会吃掉所有带前缀的请求,根本轮不到多语言路由。

另一个坑是 Route::fallback() 放太早,或者用了 Route::any('{any}', ...)->where('any', '.*') 却没加 ->middleware('localization'),导致 locale 段被当普通参数传给控制器,而不是用于切换语言环境。

  • 把多语言路由组放在 routes/web.php 最前面,确保优先匹配
  • 检查 php artisan route:list 输出,确认每条带 locale 的路由 name 都有对应 {locale} 参数,没有漏掉
  • 如果用了子域名方案(如 zh.example.com),就别硬加路径前缀,否则双重 locale 会错乱

语言切换链接怎么写才不丢参数

用户在 /zh/product/123 页面点“切换英文”,目标应该是 /en/product/123,不是 /en/ —— 但 route('product', ['id' => 123, 'locale' => 'en']) 写死 ID 很麻烦,尤其在列表页、搜索页这种动态参数多的场景。

推荐用 request()->url() + 字符串替换,虽然不优雅但最稳:把当前 URL 的第一个路径段(即当前 locale)替换成目标 locale。前提是 URL 结构统一,且 locale 总在第一段。

  • 别用 url()->previous(),它可能跳回登录页或来源站,不是当前页面
  • 别在 Blade 里拼接 {{ str_replace('/'.app()->getLocale().'/','/en/', request()->fullUrl()) }}fullUrl() 含查询参数和哈希,容易出错
  • 更健壮的做法是写个辅助函数,用 parse_url() 拆解 path,再用 explode('/', $path) 替换首段,最后拼回去

语言路由看着只是加个前缀,实际牵扯路由注册时机、参数绑定逻辑、URL 生成机制和请求解析顺序。最容易被忽略的是:你改了路由定义,却忘了同步更新所有 route() 调用处的参数结构——那里才是多语言 URL 真正生效的地方。

text=ZqhQzanResources