Laravel 的简单 i18n 本地化,这是与 Laravel 本地化类结合的有用工具。
该套餐提供以下内容:
拉维尔 | laravel 本地化 |
---|---|
4.0.x | 0.13.x |
4.1.x | 0.13.x |
4.2.x | 0.15.x |
5.0.x/5.1.x | 1.0.x |
5.2.x-5.4.x(不需要 PHP 7) | 1.2. |
5.2.0-6.x(需要 PHP 版本 >= 7) | 1.4.x |
6.x-10.x(需要 PHP 版本 >= 7) | 1.8.x |
10.x-11.x(需要 PHP 版本 >= 8.2) | 2.0.x |
通过composer安装包: composer require mcamara/laravel-localization
对于 Laravel 5.4 及以下版本,需要注册服务提供商。
为了编辑默认配置,您可以执行:
php artisan vendor:publish --provider="McamaraLaravelLocalizationLaravelLocalizationServiceProvider"
之后,将创建config/laravellocalization.php
。
配置选项有:
您可以在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
];
}
如果你使用 Laravel 11,你可以在bootstrap/app.php
文件中注册withMiddleware
闭包:
return Application:: configure (basePath: dirname ( __DIR__ ))
// Other application configurations
-> withMiddleware ( function ( Middleware $ middleware ) {
$ middleware -> alias ([
/**** OTHER MIDDLEWARE ALIASES ****/
' 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. :强烈建议本地化您的链接,即使您使用重定向中间件。否则,每次用户单击链接时,您都会导致至少一次重定向。此外,来自 post 表单的任何操作 URL 都必须本地化,以防止它被重定向到 get 请求。
以下重定向中间件依赖于config/laravellocalization.php
中hideDefaultLocaleInURL
和useAcceptLanguageHeader
的设置:
每当 url 中出现语言环境时,该中间件就会将其存储在会话中。
如果 url 中不存在区域设置,则此中间件将检查以下内容
useAcceptLanguageHeader
设置为 true,则从浏览器计算区域设置并重定向到包含区域设置的 url。hideDefaultLocaleInURL
设置为 true。例如,如果用户导航到 http://url-to-laravel/test 并且en
是当前语言环境,它会自动将他重定向到 http://url-to-laravel/en/test。
与 LocaleSessionRedirect 类似,但它将值存储在 cookie 而不是会话中。
每当 url 中出现语言环境时,该中间件就会将其存储在 cookie 中。
如果 url 中不存在区域设置,则此中间件将检查以下内容
useAcceptLanguageHeader
设置为 true,则从浏览器计算区域设置并重定向到带有区域设置的 url。hideDefaultLocaleInURL
设置为 true。例如,如果用户导航到 http://url-to-laravel/test 并且de
是当前语言环境,它会自动将他重定向到 http://url-to-laravel/de/test。
当 url 中存在默认区域设置且hideDefaultLocaleInURL
设置为 true 时,中间件将重定向到不带区域设置的 url。
例如,如果es
是默认语言环境,则 http://url-to-laravel/es/test 将被重定向到 http://url-to-laravel/test 并且App::getLocale()
将被设置到es
。
这个包附带了很多助手。
本地化 URL 在生成本地化路由时考虑了路由模型绑定,以及hideDefaultLocaleInURL
和 Translated Routes 设置。
// If current locale is Spanish, it returns `/es/test`
<a href="{{ LaravelLocalization:: localizeUrl ( ' /test ' ) }}">@ lang ( ' Follow this link ' )</a>
获取特定区域设置中的当前 URL:
// Returns current url with English locale.
{{ LaravelLocalization:: getLocalizedURL ( ' en ' ) }}
返回没有任何本地化内容的 URL。
// Returns /about
{{ LaravelLocalization:: getNonLocalizedURL ( ' /es/about ' ) }}
返回一条路由,本地化为所需的区域设置。如果给定的语言环境中不存在翻译键,则该函数将返回 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 () }}
以字符串形式返回当前语言环境的本机名称(英语/西班牙语/法语/..等)。
{{ LaravelLocalization:: getCurrentLocaleNative () }}
以字符串形式返回当前语言环境的区域名称(en_GB/en_US/fr_FR/ ..etc)。
{{ LaravelLocalization:: getCurrentLocaleRegional () }}
以字符串形式返回当前语言环境的方向 (ltr/rtl)。
{{ LaravelLocalization:: getCurrentLocaleDirection () }}
以字符串形式返回当前语言环境脚本的 ISO 15924 代码; “拉丁”、“西尔”、“阿拉伯”等
{{ LaravelLocalization:: getCurrentLocaleScript () }}
注册中间件LaravelLocalizationViewPath
以将当前语言环境设置为 view-base-path。
现在,您可以将视图包装在基于语言的文件夹中,例如翻译文件。
resources/views/en/
, resources/views/fr
, ...
由于您甚至可以通过重命名其键来修改supportedLocales,因此可以使用字符串uk
而不是en-GB
来提供自定义lang url段。当然,您需要防止与现有密钥发生任何冲突,并应尽可能长时间地遵守约定。但如果您使用此类自定义键,则必须将映射存储到localesMapping
数组。需要此localesMapping
来使 LanguageNegotiator 能够根据 HTTP 接受语言标头正确分配所需的区域设置。下面是一个如何将 HTTP 接受语言标头“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
如果您在项目中支持多种语言环境,您可能希望为用户提供一种更改语言的方法。以下是刀片模板代码的简单示例,您可以使用它来创建自己的语言选择器。
< 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 >
这里,即使hideDefaultLocaleInURL = true
也会强制 getLocalizedURL() 中的默认语言出现在 URL 中。
请注意,支持路由模型绑定。
您可以翻译您的路线。例如,http://url/en/about 和 http://url/es/acerca(acerca 是西班牙语的 about)或 http://url/en/article/important-article 和 http://url/ es/articulo/important-article(文章是西班牙语的 articulo)将被重定向到相同的控制器/视图,如下所示:
至少必须在Route::group
中间件中加载localize
中间件(请参阅安装说明)。
对于每种语言,将routes.php
添加到resources/lang/**/routes.php
文件夹中。该文件包含一个包含所有可翻译路由的数组。例如,像这样:
请记住:从 Laravel 9 开始,
resources/lang
文件夹现在位于根项目文件夹(lang
)中。如果您的项目根目录中有lang
文件夹,则必须将routes.php
添加到lang/**/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/文章/重要文章没有任何问题。
也许您在前面的示例中注意到西班牙语 url 中的英语 slug:
http://url/es/articulo/important-article
可以有翻译后的 slugs,例如这样:
http://url/en/article/important-change
http://url/es/articulo/cambio-importante
然而,为了做到这一点,每篇文章必须有许多 slugs(每个语言环境一个)。这取决于你想如何实现这种关系。可翻译路由参数的唯一要求是相关模型实现接口LocalizedUrlRoutable
。
要实现McamaraLaravelLocalizationInterfacesLocalizedUrlRoutable
,必须创建函数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 ;
});
确保将语言环境和属性作为参数传递给闭包。您还可以使用事件订阅者,请参阅:http://laravel.com/docs/events#event-subscribers
要缓存您的路线,请使用:
php artisan route:trans:cache
...而不是正常的route:cache
命令。使用artisan route:cache
将无法正常工作!
为了使路由缓存解决方案发挥作用,需要对您的应用程序路由配置进行细微调整。
Laravel 11 之前
在应用程序的RouteServiceProvider
中,使用LoadsTranslatedCachedRoutes
特征:
<?php
class RouteServiceProvider extends ServiceProvider
{
use Mcamara LaravelLocalization Traits LoadsTranslatedCachedRoutes;
Laravel 11 之后
在您的应用程序的AppServiceProvider
中,在注册方法中使用CachedTranslatedRouteLoader
类:
<?php
class AppServiceProvider extends ServiceProvider
{
use Mcamara LaravelLocalization Traits LoadsTranslatedCachedRoutes;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
RouteServiceProvider:: loadCachedRoutesUsing ( fn () => $ this -> loadCachedRoutes ());
. . .
}
有关更多详细信息,请参见此处。
如果您没有本地化Routes::group
内的操作路线,则可能会发生这种情况。这可能会导致重定向,然后将 post 请求更改为 get 请求。为了防止这种情况,只需使用 localize 助手即可。
例如,如果您使用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”,以防止处理此类请求
如果您没有本地化您的 post url 并使用重定向中间件,那么 post 请求将被重定向为 get 请求。如果你没有定义这样的get路由,就会导致这个异常。
要本地化您的帖子网址,请参阅 POST 中的示例不起作用。
如果您没有本地化您的帖子网址,也会发生这种情况。如果您没有本地化您的帖子网址,则会在验证时设置默认区域设置,并且当返回back()
时,它会显示默认区域设置中的验证消息。
要本地化您的帖子网址,请参阅 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 是一个根据 MIT 许可证授权的开源 Laravel 包