theupriser / laravel-localization
为Laravel提供便捷的本地化
Requires
- php: >=7.1.0||^8.0
- laravel/framework: ~5.2.0||~5.3.0||~5.4.0||~5.5.0||~5.6.0||~5.7.0||~5.8.0||^6.0||^7.0||^8.0||^9.0|^10.0||^11.0
Requires (Dev)
- orchestra/testbench-browser-kit: ~3.4|~3.8|~4.0|^7.12|^8.5
- phpunit/phpunit: 6.0.*|^8.0|^9.5.10|^10.0
Suggests
- ext-intl: *
This package is auto-updated.
Last update: 2024-09-11 12:29:46 UTC
README
为Laravel提供易于使用的国际化本地化,是一个与Laravel本地化类结合使用的有用工具。
该包提供以下功能
- 从浏览器检测语言
- 智能重定向(将本地存储在会话/cookie中)
- 智能路由(只需定义一次路由,无论使用多少种语言)
- 可翻译的路由
- 支持缓存与测试
- 可选择在URL中隐藏默认本地化
- 许多代码片段和辅助函数(如语言选择器)
目录
Laravel兼容性
安装
通过composer安装包: composer require mcamara/laravel-localization
对于Laravel 5.4及以下版本,需要注册服务提供者。
配置文件
要编辑默认配置,您可能需要执行以下操作
php artisan vendor:publish --provider="Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider"
之后,将创建config/laravellocalization.php。
配置选项包括
- supportedLocales 您的应用程序语言(默认:英语和西班牙语)。
- useAcceptLanguageHeader 如果为true,则自动从浏览器检测语言。
- hideDefaultLocaleInURL 如果为true,则不在URL中显示默认本地化。
- localesOrder 按自定义顺序排序语言。
- localesMapping 重命名URL本地化。
- utf8suffix 允许更改CentOS等系统的utf8suffix。
- urlsIgnored 忽略特定URL。
注册中间件
您可以在app/Http/Kernel.php文件中注册包中间件
<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { /** * The application's route middleware. * * @var array */ protected $middlewareAliases = [ /**** OTHER MIDDLEWARE ****/ 'localize' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class, 'localizationRedirect' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class, 'localeSessionRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class, 'localeCookieRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class, 'localeViewPath' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class ]; }
使用
将以下内容添加到您的路由文件中
// routes/web.php Route::group(['prefix' => LaravelLocalization::setLocale()], function() { /** ADD ALL LOCALIZED ROUTES INSIDE THIS GROUP **/ Route::get('/', function() { return View::make('hello'); }); Route::get('test',function(){ return View::make('test'); }); }); /** OTHER PAGES THAT SHOULD NOT BE LOCALIZED **/
一旦将此路由组添加到路由文件,用户就可以访问在supportedLocales中添加的所有本地化(默认为en和es)。例如,上面的路由文件创建以下地址
// Set application language to English
http://url-to-laravel/en
http://url-to-laravel/en/test
// Set application language to Spanish
http://url-to-laravel/es
http://url-to-laravel/es/test
// Set application language to English or Spanish (depending on browsers default locales)
// if nothing found set to default locale
http://url-to-laravel
http://url-to-laravel/test
该包根据您的URL设置应用程序的本地化App::getLocale()。然后可以使用它进行Laravel的本地化功能。
您可以为组添加中间件,如下所示
Route::group( [ 'prefix' => LaravelLocalization::setLocale(), 'middleware' => [ 'localeSessionRedirect', 'localizationRedirect', 'localeViewPath' ] ], function(){ //... });
推荐
1.:强烈建议使用重定向中间件。不带本地化的URL应仅用于确定浏览器/默认本地化,并将其重定向到本地化URL。否则,当搜索引擎机器人爬取例如http://url-to-laravel/test时,它们可能会在每次访问时获得不同语言的内容。另外,为同一内容创建多个URL会导致SEO重复内容问题。
2.:强烈建议本地化您的链接,即使您使用重定向中间件。否则,每次用户点击链接时,都会至少导致一次重定向。此外,从表单提交中获取的任何动作URL都必须进行本地化,以防止它被重定向到GET请求。
重定向中间件
以下重定向中间件依赖于config/laravellocalization.php中的hideDefaultLocaleInURL和useAcceptLanguageHeader的设置。
LocaleSessionRedirect
只要URL中存在区域设置,该中间件就会将其存储在会话中。
如果URL中没有区域设置,则此中间件将检查以下内容:
- 如果没有在会话中保存区域设置且
useAcceptLanguageHeader设置为true,则从浏览器计算区域设置并重定向到带有区域设置的URL。 - 如果会话中保存了区域设置,则重定向到带有区域设置的URL,除非它是默认区域设置且
hideDefaultLocaleInURL设置为true。
例如,如果用户导航到http://url-to-laravel/test且当前区域设置为en,则会自动将其重定向到http://url-to-laravel/en/test。
LocaleCookieRedirect
与LocaleSessionRedirect类似,但它将值存储在cookie中而不是会话中。
只要URL中存在区域设置,该中间件就会将其存储在cookie中。
如果URL中没有区域设置,则此中间件将检查以下内容:
- 如果没有在cookie中保存区域设置且
useAcceptLanguageHeader设置为true,则从浏览器计算区域设置并重定向到带有区域设置的URL。 - 如果cookie中保存了区域设置,则重定向到带有区域设置的URL,除非它是默认区域设置且
hideDefaultLocaleInURL设置为true。
例如,如果用户导航到http://url-to-laravel/test且当前区域设置为de,则会自动将其重定向到http://url-to-laravel/de/test。
LaravelLocalizationRedirectFilter
当默认区域设置存在于URL中且hideDefaultLocaleInURL设置为true时,则中间件将重定向到不带区域设置的URL。
例如,如果默认区域设置为es,则http://url-to-laravel/es/test将被重定向到http://url-to-laravel/test,并且App::getLocale()将设置为es。
辅助函数
此软件包附带了一些辅助函数。
本地化URL
在生成本地化路由时,本地化URL考虑了路由模型绑定,以及hideDefaultLocaleInURL和本地化路由设置。
获取本地化URL
// If current locale is Spanish, it returns `/es/test` <a href="{{ LaravelLocalization::localizeUrl('/test') }}">@lang('Follow this link')</a>
获取特定区域设置的本地化URL
获取特定区域设置的当前URL
// Returns current url with English locale. {{ LaravelLocalization::getLocalizedURL('en') }}
获取干净路由
返回任何本地化之外的URL。
// Returns /about {{ LaravelLocalization::getNonLocalizedURL('/es/about') }}
获取特定翻译密钥的URL
返回一个路由,本地化到所需的区域设置。如果翻译密钥在给定的区域设置中不存在,此函数将返回false。
// Returns /es/acerca {{ LaravelLocalization::getURLFromRouteNameTranslated('es', 'routes.about') }}
使用带有属性的路线获取本地化链接的示例
// An array of attributes can be provided. // Returns /en/archive/ghosts, /fr/archive/fantômes, /pt/arquivo/fantasmas, etc. <a href="{{ LaravelLocalization::getURLFromRouteNameTranslated( App::currentLocale(), 'routes.archive', array('category' => 'ghosts')) }}">Ghost Stories</a>
获取支持的区域设置
以数组的形式返回所有支持的区域设置及其属性。
{{ LaravelLocalization::getSupportedLocales() }}
获取支持的区域设置自定义顺序
返回所有支持的区域设置,但按配置文件中指定的顺序返回。您可以使用此函数在语言选择器中打印区域设置。
{{ LaravelLocalization::getLocalesOrder() }}
获取支持的区域设置密钥
返回一个包含所有支持的区域设置密钥的数组。
{{ LaravelLocalization::getSupportedLanguagesKeys() }}
获取当前区域设置
返回当前区域设置的键。
{{ LaravelLocalization::getCurrentLocale() }}
获取当前区域设置名称
返回当前区域设置名称的字符串(英语/西班牙语/阿拉伯语/等等)。
{{ LaravelLocalization::getCurrentLocaleName() }}
获取当前区域设置的本地名称
将当前区域设置的本地名称作为字符串返回(英语/Español/عربى/等等)。
{{ LaravelLocalization::getCurrentLocaleNative() }}
获取当前区域设置的区域名称
将当前区域设置的区域名称作为字符串返回(en_GB/en_US/fr_FR/等等)。
{{ LaravelLocalization::getCurrentLocaleRegional() }}
获取当前区域设置的书写方向
将当前区域设置的书写方向作为字符串返回(ltr/rtl)。
{{ LaravelLocalization::getCurrentLocaleDirection() }}
获取当前区域设置的脚本
将当前区域设置脚本的ISO 15924代码作为字符串返回;“Latn”,“Cyrl”,“Arab”等等。
{{ LaravelLocalization::getCurrentLocaleScript() }}
将视图基本路径设置为当前区域设置
将中间件LaravelLocalizationViewPath注册到当前区域设置,以设置视图基本路径。
现在您可以在基于语言的文件夹中包裹您的视图,就像翻译文件一样。
resources/views/en/,resources/views/fr,...
映射您自己的自定义语言URL段
由于您可以修改支持的区域设置,甚至通过更改它们的键来修改,因此可以使用字符串uk而不是en-GB来提供自定义语言URL段。当然,您需要防止与已经存在的键发生冲突,并尽可能遵循约定。但是,如果您使用此类自定义键,则必须将映射存储在localesMapping数组中。这个 localesMapping是必需的,以便使语言协商器能够根据HTTP Accept Language标头正确分配所需的区域设置。以下是一个将HTTP Accept Language标头'en-GB'映射到URL段'uk'的快速示例
// config/laravellocalization.php 'localesMapping' => [ 'en-GB' => 'uk' ],
之后,http://url-to-laravel/en-GB/a/b/c变为http://url-to-laravel/uk/a/b/c。
LaravelLocalization::getLocalizedURL('en-GB', 'a/b/c'); // http://url-to-laravel/uk/a/b/c LaravelLocalization::getLocalizedURL('uk', 'a/b/c'); // http://url-to-laravel/uk/a/b/c
创建语言选择器
如果您在项目中支持多个区域设置,您可能希望为用户提供更改语言的方法。以下是一个简单的blade模板代码示例,您可以使用它来创建自己的语言选择器。
<ul> @foreach(LaravelLocalization::getSupportedLocales() as $localeCode => $properties) <li> <a rel="alternate" hreflang="{{ $localeCode }}" href="{{ LaravelLocalization::getLocalizedURL($localeCode, null, [], true) }}"> {{ $properties['native'] }} </a> </li> @endforeach </ul>
这里默认语言将在getLocalizedURL()中强制出现在URL中,即使hideDefaultLocaleInURL = true。
注意,支持路由模型绑定。
已翻译的路由
您可以翻译您的路由。例如,http://url/en/about 和 http://url/es/acerca (acerca是西班牙语中的关于)或 http://url/en/article/important-article 和 http://url/es/articulo/important-article (article是西班牙语中的articulo)将被重定向到以下相同的控制器/视图
必须在您的Route::group中间件中加载至少localize中间件(参见安装说明)。
对于每种语言,在resources/lang/**/routes.php文件夹中添加一个routes.php文件。该文件包含一个包含所有可翻译路由的数组。例如,如下所示
<?php // resources/lang/en/routes.php return [ "about" => "about", "article" => "article/{article}", ];
<?php // resources/lang/es/routes.php return [ "about" => "acerca", "article" => "articulo/{article}", ];
您可以在routes/web.php中添加路由,如下所示
Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => [ 'localize' ]], function () { Route::get(LaravelLocalization::transRoute('routes.about'), function () { return view('about'); }); Route::get(LaravelLocalization::transRoute('routes.article'), function (\App\Article $article) { return $article; }); //,... });
保存文件后,您可以无问题地访问http://url/en/about , http://url/es/acerca , http://url/en/article/important-article 和 http://url/es/articulo/important-article 。
可翻译路由参数
也许您在先前的示例中注意到了西班牙语URL中的英语缩写
http://url/es/articulo/important-article
可以拥有翻译后的缩写,例如
http://url/en/article/important-change
http://url/es/articulo/cambio-importante
但是,为了做到这一点,每个文章都必须有许多缩写(每个区域设置一个)。这取决于您如何实现这种关系。可翻译路由参数的唯一要求是,相关的模型实现了接口LocalizedUrlRoutable。
实现 LocalizedUrlRoutable
要实现 \Mcamara\LaravelLocalization\Interfaces\LocalizedUrlRoutable 接口,需要创建一个名为 getLocalizedRouteKey($locale) 的函数,该函数必须返回给定区域设置的翻译后的 slug。在上面的示例中,在文章模型内部,getLocalizedRouteKey('en') 应返回 important-change,而 getLocalizedRouteKey('es') 应返回 cambio-importante。
路由模型绑定
要使用 路由模型绑定,应在模型中重写 resolveRouteBinding($slug) 函数。该函数应返回属于翻译后的 slug $slug 的模型。例如
public function resolveRouteBinding($slug) { return static::findByLocalizedSlug($slug)->first() ?? abort(404); }
教程视频
您可以查看这个 视频,它演示了如何设置可翻译的路由参数。
事件
如果您希望在翻译过程中捕获 URL 参数,请创建一个名为 routes.translation 的事件监听器
Event::listen('routes.translation', function($locale, $attributes) { // Do your magic return $attributes; });
请确保将区域设置和属性作为参数传递给闭包。您还可以使用事件订阅者,请参阅:https://laravel.net.cn/docs/events#event-subscribers
缓存路由
要缓存您的路由,请使用
php artisan route:trans:cache
... 而不是正常的 route:cache 命令。使用 artisan route:cache 将无法正确工作!
为了让路由缓存解决方案正常工作,需要对您的应用程序路由配置进行微小调整。
在您的 App 的 RouteServiceProvider 中,使用 LoadsTranslatedCachedRoutes 特性
<?php class RouteServiceProvider extends ServiceProvider { use \Mcamara\LaravelLocalization\Traits\LoadsTranslatedCachedRoutes;
更多详细信息请见 这里。
常见问题
POST请求不工作
如果您的 Routes::group 中的动作路由没有本地化,可能会发生这种情况。这可能会导致重定向,然后会将 POST 请求转换为 GET 请求。为了防止这种情况,请简单使用 本地化辅助函数。
例如,如果您使用 Auth::routes() 并将其放入您的 Route::group,那么
<form action="/logout" method="POST">
<button>Logout</button>
</form>
将不会工作。相反,必须使用
<form action="{{ \LaravelLocalization::localizeURL('/logout') }} " method="POST">
<button>Logout</button>
</form>
另一种解决方法是将 HTTP 方法配置为 'laravellocalization.httpMethodsIgnored' 以防止处理此类型的请求
MethodNotAllowedHttpException
如果您没有本地化您的 POST URL 并使用重定向中间件,那么 POST 请求会被重定向为 GET 请求。如果您没有定义这样的 GET 路由,您将引发此异常。
要本地化您的 POST URL,请参阅 POST 不工作 的示例。
验证消息仅在默认区域设置中
如果未对 POST URL 进行本地化,也会发生这种情况。如果您没有本地化 POST URL,则在验证时设置默认区域设置,当使用 back() 返回时,将显示默认区域设置的验证消息。
要本地化您的 POST URL,请参阅 POST 不工作 的示例。
测试
在测试设置期间,调用的路由尚未确定。这意味着无法设置语言。当测试期间发出请求时,这会导致 404 - 如果未设置前缀,则本地化路由似乎不存在。
要修复此问题,您可以使用此函数手动设置语言前缀
// TestCase.php protected function refreshApplicationWithLocale($locale) { self::tearDown(); putenv(LaravelLocalization::ENV_ROUTE_KEY . '=' . $locale); self::setUp(); } protected function tearDown(): void { putenv(LaravelLocalization::ENV_ROUTE_KEY); parent::tearDown(); } // YourTest.php public function testBasicTest() { $this->refreshApplicationWithLocale('en'); // Testing code }
协作者
如果您想成为其中之一,请咨询 mcamara!
更新日志
查看更改日志 -> 更改日志
许可协议
Laravel Localization 是一个开源的 Laravel 包,许可协议为 MIT。