mvccore / ext-router-localization
MvcCore - 扩展 - 路由 - 媒体与本地化 - 管理网站本地化(语言或语言和区域)的扩展。支持任何HTTP方法,多语言或单语言(或带有区域的语言)模式及其反向,如`/en/path`或`/en-US/path`,非常可配置。
Requires
- php: >=5.4.0
- mvccore/ext-router-extended: ^5.2
- mvccore/mvccore: ^5.2
README
MvcCore 路由扩展,使您的应用程序具有本地化和非本地化URL地址,非常可配置。
URL地址可以包含通过语言代码或语言和区域代码的组合进行本地化(如`/en/custom/path`或
/en-US/custom/path
或`/any/non-localized/path`)。路由器支持任何HTTP方法,以及多语言或单语言路由模式及其反向。
概述
- 安装
- 功能
2.1. 功能 - 路由
2.2. 功能 - URL生成 - 工作原理
3.1. 工作原理 - 路由
3.2. 工作原理 - URL补全 - 使用方法
4.1. 使用方法 -Bootstrap
初始化
4.2. 使用方法 - 默认本地化
4.3. 使用方法 - 允许的本地化
4.4. 使用方法 - 路由配置
4.5. 使用方法 - 允许非本地化路由
4.6. 使用方法 - 仅通过语言检测本地化
4.7. 使用方法 - 本地化等效
4.8. 使用方法 - 根据语言和区域记录路由
4.9. 使用方法 - 在第一次请求中重定向到默认并返回
4.10. 使用方法 - 生成本地化或非本地化URL
4.11. 使用方法 - 在非本地化请求中生成本地化URL - 高级配置
5.1. 高级配置 - 会话过期
5.2. 高级配置 - 严格会话模式
5.3. 高级配置 - 仅路由GET请求
1. 安装
composer require mvccore/ext-router-localization
2. 功能
2.1. 功能 - 路由
- 路由器与请求协同工作,这些请求包含仅在URL地址中包含国际小写语言代码的本地化或同时包含两个代码——国际语言代码、破折号和国际大写区域代码。
- 路由器通过第一个请求中的HTTP头
Accept-Language
识别用户设备的本地化设置。 - 如果需要,路由器将第一个请求重定向到具有更好的本地化前缀或本地化查询字符串参数的URL地址,其中包含来自HTTP头识别的接受语言的内容。
- 路由器将其识别的设备本地化存储在其自己的会话命名空间中,并具有可配置的过期时间(以避免在每次请求中重复处理本地化识别)。
- 路由器将请求路径中可能找到的本地化前缀子串(包含小写国际语言代码和可选的大写国际区域代码)替换为空字符串。它每次都保持请求路径的相同形式,以按常规处理路由。
- 路由器完成
$request->GetLang()
和$request->GetLocale();
(或$router->GetLocalization();
)的值,以便在您的应用程序的任何地方使用它们。 - 本地化版本的会话严格模式(可配置)以通过会话值严格驱动应用程序的本地化。
- 路由器只为默认本地化主页保留一个URL地址版本(在斜杠地址下——
/
或/index.php
)。对默认本地化主页的请求将自动重定向到斜杠URL地址(因此,例如,默认本地化en-US
的地址/en-US/
没有页面,此页面自动重定向到/
)。 - 路由器仅接受允许的语言或它接受在重写URL地址中允许的语言和区域代码对或它接受在
localization
查询字符串参数中允许的本地化,所有其他值都重定向到默认本地化。 - 路由器通过语言键或通过必要时的语言和区域键接受非本地化路由和本地化路由,具有
pattern
和defaults
(或具有显式的match
和reverse
)。 - 路由器为所有非本地化路由从会话首先定义本地化记录到请求对象,然后到自身,如果会话中没有内容,它定义配置的默认本地化。
2.2. 功能 - URL生成
- 路由器通过内置的
Url()
方法完成每个应用程序URL(或配置的每个GET
URL)的生成,仅在开头使用小写国际语言代码,或使用两个代码——国际语言代码与破折号以及开头的大写国际区域代码,这些带有前缀的本地化由当前请求的本地化或作为第二个参数的包含URL参数的本地化自动完成。 - 路由器还可以通过设置
$router->SetLocalization($lang [,$locale]);
来通过非本地化请求生成本地化URL地址。
3. 它是如何工作的
3.1. 它是如何工作的 - 路由
- 路由器从以下来源完成本地化
- 从请求的URL(如果没有本地化前缀在URL中,并且请求的是主页,则将其完成为默认loc.)。
- 从会话(如果没有内容,则保持在
NULL
)。 - 从特殊的
$_GET
参数以在会话严格模式下切换本地化(也可以是NULL
)。
- 如果需要,路由器通过源数据处理预路由重定向
- 如果特殊
$_GET
切换参数中有允许的值:- 新的本地化存储在会话中,并且请求通过特殊切换参数重定向到新的本地化。 - 否则如果没有会话中的本地化来自任何以前的请求:- 有通过发送的
Accept-Language
HTTP头识别的最近本地化并存储在会话中,以供后续请求使用。- 如果检测到的版本与请求版本相同,则存在完成标志;如果检测到的版本是应用程序中允许的本地化版本与HTTP头中高度优先的本地化之间的最佳匹配,则存在标志。
- 如果严格会话模式配置为
FALSE
(默认值)- 如果请求是第一个(会话中没有来自先前请求的内容)
- 如果检测到的本地化匹配不是最佳匹配,或者匹配是最佳匹配但请求的loc.未识别(
NULL
)- 检查是否通过配置将此未知的第一请求重定向到默认本地化主页。
- 如果请求的本地化未识别,则将用户重定向到HTTP头中的本地化。
- 否则,稍后以标准方式路由请求,不处理任何重定向。
- 如果检测到的本地化匹配不是最佳匹配,或者匹配是最佳匹配但请求的loc.未识别(
- 否则,稍后以标准方式路由请求,不处理任何重定向。
- 如果请求是第一个(会话中没有来自先前请求的内容)
- 如果严格会话模式配置为
TRUE
- 如果请求的本地化与会话版本不同
- 将用户重定向到会话版本。
- 否则,稍后以标准方式路由请求,不处理任何重定向。
- 如果请求的本地化与会话版本不同
- 如果特殊
- 路由器删除任何发现的本地化URL前缀,以处理具有相同请求路径的任何本地化的路由。
- 然后路由器以标准方式路由请求。
3.2 工作原理 - URL 完成功能
- 路由器始终以请求的本地化版本生成URL地址
- 对于没有定义的重写路由的地址,将添加到查询字符串中关于本地化的附加参数(
&localization=...
)。 - 对于具有定义的重写路由的地址,路由器配置将预置本地化URL前缀。
- 对于没有定义的重写路由的地址,将添加到查询字符串中关于本地化的附加参数(
- 如果请求的版本是默认本地化,则不需要将任何附加数据放入URL地址中,因此对于默认本地化,总是相同的原始URL字符串,没有任何特殊参数或前缀。
- 如果您在内部
Url()
方法的第二个参数数组中定义了与请求的本地化不同的本地化,则将在结果URL字符串中添加查询参数或本地化URL前缀,该参数值是给定的本地化参数值。 - 如果配置了会话严格模式,将自动添加特殊的
$_GET
切换参数。
4. 使用方法
4.1. 使用方法 - Bootstrap
初始化
将此内容添加到Bootstrap.php
或添加到应用程序非常开始的地方,在应用路由或任何其他使用路由器进行配置的扩展配置之前
$app = \MvcCore\Application::GetInstance(); $app->SetRouterClass('\MvcCore\Ext\Routers\Localization'); ... // to get router instance for next configuration: /** @var \MvcCore\Ext\Routers\Localization $router */ $router = \MvcCore\Router::GetInstance();
4.2. 使用方法 - 默认本地化
默认本地化配置始终是必需的。
$router->SetDefaultLocalization('en-US');
4.3. 使用方法 - 允许的本地化
上面配置的默认本地化en-US
自动允许。
任何其他请求(例如路径:/something
)不会进行本地化,如果没有匹配到非本地化路由,则将其重定向到默认本地化路径,如:/en-US/something
,这可以防止URL拼写错误。
但是,任何其他请求的未允许的本地化(例如路径:/nl-NL/product-lijst
)也不会用于本地化请求,如果没有匹配到非本地化路由,则请求将被重定向到默认本地化路径/en-US/nl-NL/product-lijst
,这可能会生成错误404 - 未找到,因此请确保所有地方都只有您想要的本地化。
$router->SetAllowedLocalizations(/*'en-US', */'en-DE');
4.4. 使用方法 - 路由配置
$router->SetRoutes([ // If you want to add automatically localized route very easily, // you can use only definition like this to define router key with // `Namespace\Controller:Action` and `pattern` as '/something' 'Admin\Index:Index' => '/admin', // Localized route with automatically completed `match` // and `reverse` records from `pattern` record: 'Front\Products:List' => [ 'pattern' => [ 'en' => "/products-list[/<page>]", 'de' => "/produkte-liste[/<page>]", ], 'defaults' => ['page' => 1], 'constraints' => ['page' => '\d+'], ], // Localized route with explicitly defined `match` and `reverse` // records with also localized `defaults` values: 'Front\Products:Detail' => [ 'match' => [ 'en' => '#^/product/(?<id>\d+)(/(?<color>[a-z]+))?/?#', 'de' => '#^/produkt/(?<id>\d+)(/(?<color>[a-z]+))?/?#' ], 'reverse' => [ 'en' => '/product/<id>[/<color>]', 'de' => '/produkt/<id>[/<color>]' ], 'defaults' => [ 'en' => ['color' => 'red'], 'de' => ['color' => 'rot'], ] ], // Automatically localized route, `pattern` record and later // `match` and `reverse` records are defined for all localizations // with the same values `/<path>`, `constraints` are never localized: 'Front\Index:Index' => [ 'pattern' => '/<path>', // constraints are never localized: 'constraints' => ['path' => '[-a-zA-Z0-9_/]+'] ], ]);
4.5. 使用方法 - 允许非本地化路由
默认情况下允许非本地化路由,因此您可以一起路由本地化和非本地化路由。但是,要使所有路由严格本地化并将所有请求重定向到默认本地化前缀或带有默认本地化查询字符串参数值的URL - 其中无法通过查询字符串参数识别本地化,也无法通过URL前缀识别本地化的所有请求 - 您需要通过以下方式配置路由器
$router->SetAllowNonLocalizedRoutes(FALSE);
4.6. 使用方法 - 仅通过语言检测本地化
路由器默认配置为使用TRUE
值,仅通过从Accept-Language
HTTP头记录中检测语言记录来定位化,而不是严格与区域代码结合。默认情况下,解析的国际语言代码足以选择最终目标应用程序的定位化。将首先选择允许列表中检测到的语言的第一种定位化。
如果值为FALSE
,则必须在Accept-Language
HTTP头中发送与应用程序配置在允许的定位化中唯一相同的国际语言代码和国际区域代码组合。
$router->SetDetectLocalizationOnlyByLang(FALSE);
4.7. 使用 - 定位化等效
您可以通过解析第一次请求中的HTTP头Accept-Language
来定义用于定位化检测的定位化等效列表。这可以用于语言非常相似的国家,如乌克兰和俄罗斯、捷克和斯洛伐克...数组中的键是目标定位化,值是目标定位化等效的数组。
$router->->SetLocalizationEquivalents([ // Browsers preferring UK, USA or Canada are considered as `en-US` locale to send 'en-US' => ['en-GB', 'en-CA', 'en-AU'], // Browsers preferring Slovak are considered as `cs-CZ` locale to send 'cs-CZ' => ['sk-SK'], // Czech and Slovak ]); ... $router->AddLocalizationEquivalents(/*... same param syntax as method above*/);
4.8. 使用 - 按语言和区域设置的路由记录
如果定义为TRUE
值(默认为FALSE
),则定义的路由记录(如pattern
、match
、reverse
或defaults
)必须由国际语言代码和国际区域代码定义,而不仅仅是语言代码。如果不同的区域有不同的URL字符串命名,则此选项非常罕见。
$router->SetRouteRecordsByLanguageAndLocale(TRUE);
4.9. 使用 - 第一次请求中重定向到默认和返回
如果为TRUE
(默认为FALSE
),如果请求是历史上的第一次(按会话),如果通过HTTP头进行的定位化不是最佳匹配,或者如果它是最佳匹配但请求的定位化不与HTTP头偏好的相同,则重定向到带有source_url
查询字符串参数的默认定位化主页。
$router->SetRedirectFirstRequestToDefault(TRUE);
4.10. 使用 - 生成本地化URL或非本地化URL
如果您在Url()
方法中将本地化路由名称作为第一个参数放入,则会自动生成本地化URL。
// somewhere in Bootstrap.php: $router ->SetDefaultLocalization('en-US') ->SetAllowedLocalizations('de-DE') ->SetRouteRecordsByLanguageAndLocale(FALSE) ->AddRoutes([ 'Front\Product:Detail' => [ 'pattern' => [ 'en' '/product/<id>', 'de' '/produkt/<id>', ], 'constraints' => [ 'id' => '\d+', ] ] ]); ... // somewhere in template or in controller (if router has matched localization `de-DE`): $this->Url('Front\Product:Detail', [ 'id' => 50 ]); // will return: `/de-DE/produkt/50`
如果放入非本地化路由名称,则返回的是非本地化URL。
// somewhere in Bootstrap.php: $router->AddRoutes([ 'admin' => [ 'pattern' => '/admin/<controller>/<action>[/<id>]', 'constraints' => [ 'controller' => '-a-z0-9', 'action' => '-a-z0-9', 'id' => '\d+', ] ] ]); ... // somewhere in template or in controller (if router has matched any localization): $this->Url('admin', [ 'controller' => 'products', 'action' => 'update', 'id' => 50 ]); // will return: `/admin/products/update/50`
4.11. 使用 - 非本地化请求中的本地化URL
如果请求在任何一个非本地化路由上路由,并且请求对象具有来自会话或默认定位化(如果没有会话中的内容)的一些奇怪的定位化,您仍然可以生成不同的本地化URL地址,例如在CRON脚本中用于电子邮件消息,如下所示。
$router->SetLocalization('de', 'DE'); ... // anywhere you have $router instance: $router->Url('Front\Product:Detail', ['id' => 50]); // `/de-DE/produkt/50` ... // or somewhere in template or in controller: $this->Url('Front\Product:Detail', ['id' => 50]); // `/de-DE/produkt/50`
5. 高级配置
5.1. 高级配置 - 会话过期
可以更改会话过期关于检测到的定位化值,以便在URL中没有前缀的每个请求中不识别定位化,因为解析Accept-Language
HTTP头可能需要一些时间。默认情况下为1小时
。您可以通过以下方式更改它。
$router->SetSessionExpirationSeconds( \MvcCore\Session::EXPIRATION_SECONDS_DAY );
5.2. 高级配置 - 严格会话模式
在会话严格模式下,不能仅通过在URL中请求不同的定位化前缀来更改定位化。严格会话模式是路由器模式,其中定位化由第一次请求HTTP头识别的会话值管理。所有请求到会话中存储的定位化版本的请求都会自动重定向到会话中存储的定位化版本。
通常,只有通过请求不同的定位化版本URL前缀才能获取不同的定位化版本。例如,要获取en-US
定位化版本的不同版本,例如,要获取de-DE
定位化版本,只需要以这种方式请求配置了de-DE
允许定位化的应用程序:/de-DE/any/application/request/path
。
在会话严格模式下,只能通过媒体版本导航中的特殊$_GET
参数更改定位化版本。例如,要获取与en-US
不同的定位化版本,例如de-DE
定位化版本,需要将以下查询字符串参数添加到其中:/any/application/request/path?switch_localization=de-DE
然后,会更改存储在会话中的定位化版本,并且用户将被重定向到带有de-DE
URL前缀的新定位化版本。
要启用此会话严格模式,您只需通过以下方式配置路由器:
$router->SetStricModeBySession(TRUE);
5.3. 高级配置 - 仅路由 GET
请求
路由器仅管理 GET
请求的本地化版本。这意味着在会话严格模式下重定向到适当的版本,或者在第一次请求中重定向到已识别的本地化版本。对于管理本地化版本的 POST
请求和其他请求方法没有意义。对于这些请求,你仍然会在会话中保留本地化版本记录,并且可以在任何时候使用它。但为了处理所有请求方法,你可以配置路由器以这样做,如下所示
$router->SetRouteGetRequestsOnly(FALSE);