
Composer在线学习地址:学习地址
国际化应用中的路由之痛
想象一下,你正在构建一个面向全球用户的 Laravel 网站。你的网站需要支持英语、法语、德语等多种语言。这意味着,对于同一个页面,比如“关于我们”,你可能需要这样的 URL:
/en/about-us/fr/a-propos/de/ueber-uns
如果你的应用中有几十个甚至上百个页面,每个页面都需要为每种语言定义一套路由,那么你的 routes/web.php 文件很快就会变得像一团乱麻。手动管理这些路由不仅效率低下,还容易出现以下问题:
代码重复与臃肿: 为每种语言复制粘贴相似的路由定义。URL 生成复杂: 在视图或控制器中生成特定语言的 URL 时,需要手动拼接语言前缀,或者使用复杂的条件判断。路由参数翻译: 如果路由中包含像 posts/{post:slug} 这样的参数,而 slug 本身也需要根据语言进行翻译,那处理起来更是麻烦。404 页面本地化: 当用户访问不存在的页面时,如何确保 404 页面也是当前语言的?维护成本高: 增加或删除一种语言,或者修改某个路由,都需要改动大量文件。
这些问题让我在国际化开发的道路上举步维艰,直到我遇到了 codezero/laravel-localized-routes。
遇见救星:codezero/laravel-localized-routes
codezero/laravel-localized-routes 是一个专为 Laravel 设计的 Composer 包,它提供了一种优雅且便捷的方式来设置、管理和使用本地化路由。它将多语言路由的复杂性封装起来,让你能够以更简洁、更直观的方式定义和使用路由。
它的核心理念是:你只需定义一次路由,这个包就会自动为所有支持的语言生成对应的本地化路由,并处理好语言前缀、域名甚至路由参数的翻译。
如何使用 Composer 解决问题?
首先,我们通过 Composer 将这个强大的工具引入到我们的项目中:
composer require codezero/laravel-localized-routes
安装完成后,Laravel 会自动注册其 ServiceProvider。接下来,我们需要进行一些简单的配置。
1. 发布配置文件
运行以下命令发布其配置文件,你会在 config/localized-routes.php 找到它:
php artisan vendor:publish --provider="CodeZeroLocalizedRoutesLocalizedRoutesServiceProvider" --tag="config"
2. 配置支持的语言环境
在 config/localized-routes.php 中,你可以定义你的应用支持哪些语言。这非常灵活:
简单语言前缀:
// config/localized-routes.php'supported_locales' => ['en', 'nl', 'fr'],这会将
/en/about、/nl/about等作为路由前缀。自定义语言 Slug:
如果你想让语言前缀更具描述性,或者与语言代码不同:
'supported_locales' => [ 'en' => 'english-slug', 'nl' => 'dutch-slug',],自定义域名:
对于更复杂的国际化策略,你甚至可以为每种语言指定独立的域名:
'supported_locales' => [ 'en' => 'english-domain.test', 'nl' => 'dutch-domain.test',],主语言省略 Slug:
为了让主语言的 URL 更简洁,你可以配置省略其语言前缀:
'omitted_locale' => 'en', // 英语路由将没有 /en 前缀这样,
en.example.com/about就会变成example.com/about。3. 添加中间件自动更新应用语言环境
为了让 Laravel 应用的语言环境(
App::getLocale())根据 URL 自动切换,你需要注册SetLocale中间件。请确保它在StartSession之后,SubstituteBindings之前运行,这对于路由模型绑定中的本地化参数解析至关重要。Laravel 11 及更高版本:
// bootstrap/app.php->withMiddleware(function (Middleware $middleware) { $middleware->web(remove: [ IlluminateRoutingMiddlewareSubstituteBindings::class, ]); $middleware->web(append: [ CodeZeroLocalizedRoutesMiddlewareSetLocale::class, IlluminateRoutingMiddlewareSubstituteBindings::class, ]);})Laravel 10:
// app/Http/Kernel.phpprotected $middlewareGroups = [ 'web' => [ //... IlluminateSessionMiddlewareStartSession::class, // <= 在此之后 //... CodeZeroLocalizedRoutesMiddlewareSetLocale::class, IlluminateRoutingMiddlewareSubstituteBindings::class, // <= 在此之前 ],];4. 注册本地化路由
现在,最核心的部分来了。你只需将路由定义放在
Route::localized()闭包中,该包就会自动为每种支持的语言注册相应的路由:// routes/web.phpuse AppHttpControllersAboutController;Route::localized(function () { Route::get('about', [AboutController::class, 'index'])->name('about');});有了这个简单的定义,如果你的
supported_locales是['en', 'nl'],并且omitted_locale是en,那么它会自动生成:
/about(en.about)/nl/about(nl.about)这大大减少了路由文件的重复代码!
5. 翻译路由参数(Route Model Binding)
如果你的路由参数也需要本地化,比如
posts/{post:slug},其中slug是多语言的,你需要在模型中重写resolveRouteBinding方法:// AppModelsPost.phpuse IlluminateSupportFacadesApp;class Post extends Model{ public function resolveRouteBinding($value, $field = null) { $field = $field ?: $this->getRouteKeyName(); if ($field === 'slug') { // 假设你的 slug 存储在 JSON 字段中,例如 ['en' => 'my-post', 'nl' => 'mijn-bericht'] $field .= '->' . App::getLocale(); } return $this->where($field, $value)->firstOrFail(); }}这样,当访问
/en/posts/my-post或/nl/posts/mijn-bericht时,Laravel 就能正确解析到对应的Post模型。6. 翻译硬编码的 URI Slugs
对于像
about/us这样硬编码的 URI 段,你可能希望它们也能被翻译(例如over/ons)。这个包集成了codezero/laravel-uri-translator,提供了Lang::uri()宏:首先,创建语言文件来存储路由翻译:
// lang/nl/routes.phpreturn [ 'about' => 'over', 'us' => 'ons',];然后,在路由定义中使用它:
use AppHttpControllersAboutController;use IlluminateSupportFacadesLang;Route::localized(function () { Route::get(Lang::uri('about/us'), [AboutController::class, 'index'])->name('about');});现在,
en.about可能是/about/us,而nl.about就会是/nl/over/ons。7. 生成本地化 URL
生成 URL 也变得非常简单和智能:
生成当前语言的 URL:
$url = route('about'); // 如果当前语言是 'en' 且省略了前缀,则返回 '/about'生成特定语言的 URL:
Laravel 的
route()助手函数被扩展,支持额外的语言参数:$url = route('about', [], true, 'nl'); // 返回 '/nl/about'生成当前路由的本地化版本(非常适合语言切换器):
Route::localizedUrl()宏能自动识别当前路由和参数,并生成指定语言的 URL:// 假设当前路由是 /en/posts/my-post$enUrl = Route::localizedUrl('en'); // /posts/my-post$nlUrl = Route::localizedUrl('nl'); // /nl/posts/mijn-bericht// 如果路由有多个参数,模型可以实现 ProvidesRouteParameters 接口// 从 getRouteParameters() 方法返回参数值。这使得构建语言切换器变得异常简单:
@if (Route::isLocalized() || Route::isFallback())
- @foreach(LocaleConfig::getLocales() as $locale) @if ( ! App::isLocale($locale))
- {{ strtoupper($locale) }} @endif @endforeach
8. 本地化 404 页面和自动重定向
为了确保 404 页面也是本地化的,并且可以将非本地化 URL 自动重定向到其本地化版本,你可以在 routes/web.php 的末尾注册一个回退路由:
// routes/web.phpRoute::fallback(CodeZeroLocalizedRoutesControllersFallbackController::class);并在配置文件中开启自动重定向:
// config/localized-routes.php'redirect_to_localized_urls' => true,这样,如果用户访问
/about-us(非本地化 URL),它会根据当前语言环境自动重定向到/en/about-us或/nl/about-us。优势与实际应用效果
使用
codezero/laravel-localized-routes之后,我的开发体验得到了显著提升:极简的路由定义: 告别了为每种语言重复定义路由的噩梦,
routes/web.php变得干净整洁。自动化的语言切换: 中间件自动处理语言环境的检测和设置,无需手动干预。智能的 URL 生成:route()助手函数和Route::localizedUrl()宏让生成特定语言的 URL 变得轻而易举,尤其在构建语言切换器时,效率倍增。无缝的路由参数本地化: 通过模型绑定和 URI 翻译,轻松处理多语言的路由参数和 URI 段。更好的用户体验和 SEO: 统一且友好的多语言 URL 结构,有助于提升用户体验和搜索引擎优化。降低维护成本: 增删语言或修改路由,只需改动少数地方,大大减少了出错的可能性。这个包让 Laravel 的国际化路由管理从一个令人头疼的难题,变成了一个优雅且高效的解决方案。如果你正在开发一个多语言的 Laravel 应用,我强烈推荐你尝试一下
codezero/laravel-localized-routes,它绝对能让你的开发工作事半功倍!以上就是Laravel多语言路由头疼?codezero/laravel-localized-routes助你优雅实现国际化的详细内容,更多请关注php中文网其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/136352.html
微信扫一扫
支付宝扫一扫