mmaturax / yii2-localeurls
为URL自动管理语言/地区。
Requires
- yiisoft/yii2: *
This package is not auto-updated.
Last update: 2024-09-21 02:24:39 UTC
README
为Yii 2提供通过URL自动管理语言/地区的扩展。
重要:如果您已从版本1.0.*升级,您必须修改您的配置。请参阅下文关于升级的部分。
特性
使用此扩展,您可以使用包含语言代码的URL,例如
/en/some/page
/de/some/page
http://www.example.com/en/some/page
http://www.example.com/de/some/page
如果您想的话,也可以配置友好的名称
http://www.example.com/english/some/page
http://www.example.com/deutsch/some/page
语言代码将在创建URL时自动添加,并在解析URL时读取。为了获得最佳用户体验,如果URL中没有使用语言,语言将自动从浏览器设置中检测到。但是,用户仍然可以通过调用另一个语言代码的URL来访问其他语言。
最后请求的语言也将持久化在用户会话和cookie中。因此,如果用户尝试访问您的网站且URL中没有语言代码,他将被重定向到最后一次访问时使用的语言。
当然,所有上述内容(以及更多)都是可配置的。
安装
通过composer安装此包
composer require codemix/yii2-localeurls
然后将其添加到您的应用程序配置中
<?php return [ // ... 'components' => [ // ... // Override the urlManager component 'urlManager' => [ 'class' => 'codemix\localeurls\UrlManager', // List all supported languages here // Make sure, you include your app's default language. 'languages' => ['en-US', 'en', 'fr', 'de', 'es-*'], ] // ... ] ];
现在您已准备好使用此扩展了。
注意:您仍然可以像往常一样配置自定义URL规则。只需忽略您URL规则中的任何
language
参数,因为它在解析之前将被删除,在创建URL之后将被添加。
注意2:语言代码将从pathInfo中删除。
操作模式和配置
创建URL
所有创建的URL都将包含当前应用语言代码。因此,如果检测到语言为de
,并且您使用
<?php $url = Url::to(['demo/action']) ?> <?= Html::a('Click', ['demo/action']) ?>
您将得到类似以下URL
/de/demo/action
要创建一个链接以将应用程序切换到不同的语言,您可以显式添加language
URL参数
<?= $url = Url::to(['demo/action', 'language' => 'fr']) ?> <?= Html::a('Click', ['demo/action', 'language' => 'fr']) ?>
这将给您一个类似以下URL
/fr/demo/action
注意:如果使用自定义URL规则,URL可能看起来不同。在这种情况下,语言参数始终添加到最终的相对/绝对URL之前/之后。
如果出于某种原因您想为该URL参数使用除language
之外的其他名称,您可以通过urlManager
组件的languageParam
选项进行配置。
默认语言
默认语言通过应用程序配置中的language参数进行配置。您必须始终将此语言包含在$languages
配置中(见下文)。
默认情况下,默认语言的URL不会包含任何语言代码。例如
/
/some/page
如果网站使用包含默认语言代码的URL访问,访问者将被重定向到不带语言代码的URL。例如,如果默认语言是fr
/fr/ -> Redirect to /
/fr/some/page -> Redirect to /some/page
如果将enableDefaultLanguageUrlCode
更改为true
,则反之亦然。现在,默认语言被像任何其他配置的语言一样对待。不包含语言代码的请求不再可访问
/fr
/fr/some/page
/ -> Redirect to /fr
/some/page -> Redirect to /fr/some/page
语言配置
必须将所有语言(包括默认语言)配置在localeUrls
组件的languages
参数中。您应该在看起来类似的通用代码之前列出更具体的语言代码(即,'en-US'在'en'之前)
'languages' => ['en-US', 'en-UK', 'en', 'fr', 'de-AT', 'de'],
注意:如果使用国家代码,它们应始终配置为大写字母,如上所示。URL仍然始终使用小写代码。如果使用像
en-US
这样的带大写代码的URL,用户将被重定向到小写的en-us
变体。应用程序语言将始终使用正确的en-US
代码。如果您不想重定向带小写国家代码的URL,可以将keepUppercaseLanguageCode
选项设置为true
。
如果您想您的URL可选地包含任何国家变体,您也可以使用通配符模式
'languages' => ['en-*', 'de-*'],
现在任何匹配en-??
或de-??
的URL都可以使用,例如en-us
或de-at
。没有国家代码的URL,如en
和de
,也将继续工作
/en/demo/action
/en-us/demo/action
/en-en/demo/action
/de/demo/action
/de-de/demo/action
/de-at/demo/action
带有国家代码的URL将设置完整的ll-CC
代码作为Yii语言,而只有语言代码的URL将导致配置为语言。
注意:如果您只想将浏览器设置中检测到的语言从
de-AT
回退到de
,则不需要此功能。请参阅下面的语言检测部分。
您还可以在URL中使用更友好的名称或别名,配置如下
'languages' => ['en', 'german' => 'de', 'br' => 'pt-BR'],
<?= Url::to(['demo/action', 'language' => 'de']) ?>
这将为您提供类似以下URL
/german/demo/action
/br/demo/action
并将相应的语言设置为de
或pt-PR
,如果匹配。
持久性
访客最后使用的语言将被存储在用户会话和cookie中。如果用户在没有语言代码的情况下再次访问您的网站,他将重定向到存储的语言。
例如,如果用户首先访问
/de/some/page
然后一段时间后回到以下URL之一
/some/page -> Redirect to /de/some/page
/ -> Redirect to /de/
/dk/some/page
在最后一种情况下,dk
将被存储为最后使用的语言。
默认启用持久性,可以通过将localeUrls
组件中的enableLanguagePersistence
设置为false
来禁用。
您可以使用以下方式修改其他持久性设置
languageCookieDuration
:在cookie中存储语言信息的时间(以秒为单位)。设置为false
以禁用cookie。languageCookieName
:语言cookie的名称。默认为_language
。languageCookieOptions
:设置在语言cookie上的其他选项。languageSessionKey
:语言会话键的名称。默认为_language
。从1.6.0版本开始,这也可以设置为false
以完全不使用会话。
重置为默认语言
您会发现,如果enableDefaultLanguageUrlCode
设置为false
(这是默认值)并且用户已将de
存储为最后使用的语言,则存在一个问题。我们如何现在以默认语言访问站点?因为如果我们尝试/
,我们会被重定向到/de/
。
答案是简单的:要创建重置URL,您必须在URL中明确包含默认语言的代码。例如,如果默认语言是fr
<?= Url::to(['demo/action', 'language' => 'fr']) ?>
/fr/demo/action -> Redirect to /demo/action
在这种情况下,fr
将首先被存储为最后使用的语言,然后用户将被重定向。
如果您需要显式创建不带任何语言代码的默认语言URL,您也可以传递一个空字符串作为语言
<?= Url::to(['demo/action', 'language' => '']) ?>
这将给您
/demo/action
语言更改事件
当启用持久性时,组件将在会话或cookie中存储的语言更改时触发languageChanged
事件。以下是如何使用此功能跟踪数据库中的用户语言的一个示例
<?php 'urlManager' => [ 'class' => 'codemix\localeurls\UrlManager', 'languages' => ['en', 'fr', 'de'], 'on languageChanged' => `\app\components\User::onLanguageChanged', ]
User
中的静态类方法可能看起来像这样
<?php public static function onLanguageChanged($event) { // $event->language: new language // $event->oldLanguage: old language // Save the current language to user record $user = Yii::$app->user; if (!$user->isGuest) { $user->identity->language = $event->language; $user->identity->save(); } }
注意:用户在登录或注册之前可能已经选择了语言。因此,您还应在这些情况下保存或更新语言。
语言检测
如果用户第一次访问您的网站,并且会话或cookie中没有存储语言(或者持久性已关闭),则将从访问者的浏览器设置中检测语言。如果首选语言之一与您的语言匹配,则将用作应用程序语言(如果启用持久性,也将持久化)。
要禁用此功能,可以将enableLanguageDetection
设置为false
。默认情况下是启用的。
如果浏览器语言包含国家代码,如de-AT
,并且您的$languages
配置中只有de
,则将回退到该语言。只有当您使用了通配符如de-*
或显式配置了de-AT
或别名如'at' => 'de-AT'
时,浏览器语言包括国家代码才会被使用。
让我们通过一个示例配置来更好地理解$languages
配置如何影响语言检测和创建的URL。
'languages' => [ 'en', 'at' => 'de-AT', 'de', 'pt-*' ],
现在假设一个用户第一次访问您的网站。根据他的浏览器设置,他将被重定向到不同的URL。
通过GeoIP服务器模块进行检测
从1.7.0版本开始,语言也可以通过Web服务器的GeoIP模块进行检测。请注意,这仅在浏览器设置中没有找到有效语言时才会发生。
要使用此功能,相关的GeoIp模块必须已经安装,并且它必须提供国家代码作为$_SERVER
中的服务器变量。您可以在$geoIpServerVar
中配置键。默认为HTTP_X_GEO_COUNTRY
。
要启用此功能,您必须提供一个GeoIp国家代码列表,并按应设置的语言进行索引
'geoIpLanguageCountries' => [ 'de' => ['DEU', 'AUT'], 'pt' => ['PRT', 'BRA'], ],
排除路由/URL
您可能想通过$ignoreLanguageUrlPatterns
选项禁用某些路由和URL的语言处理
<?php 'ignoreLanguageUrlPatterns' => [ // route pattern => url pattern '#^site/(login|register)#' => '#^(signin|signup)#', '#^api/#' => '#^api/#', ],
键和值都是正则表达式。键是匹配要排除的语言处理的路由的模式(在创建URL时排除),而值是要排除的pathInfo的模式(在解析URL时排除)。
注意:键和值不一定相互关联。这只是为了方便,将配置组合为单个选项。
示例语言选择小部件
没有包含语言选择小部件,因为这种小部件的标记和行为选项太多。但它很容易构建。以下是基本思路
<?php use Yii; use yii\bootstrap\Dropdown; class LanguageDropdown extends Dropdown { private static $_labels; private $_isError; public function init() { $route = Yii::$app->controller->route; $appLanguage = Yii::$app->language; $params = $_GET; $this->_isError = $route === Yii::$app->errorHandler->errorAction; array_unshift($params, '/' . $route); foreach (Yii::$app->urlManager->languages as $language) { $isWildcard = substr($language, -2) === '-*'; if ( $language === $appLanguage || // Also check for wildcard language $isWildcard && substr($appLanguage, 0, 2) === substr($language, 0, 2) ) { continue; // Exclude the current language } if ($isWildcard) { $language = substr($language, 0, 2); } $params['language'] = $language; $this->items[] = [ 'label' => self::label($language), 'url' => $params, ]; } parent::init(); } public function run() { // Only show this widget if we're not on the error page if ($this->_isError) { return ''; } else { return parent::run(); } } public static function label($code) { if (self::$_labels === null) { self::$_labels = [ 'de' => Yii::t('language', 'German'), 'fr' => Yii::t('language', 'French'), 'en' => Yii::t('language', 'English'), ]; } return isset(self::$_labels[$code]) ? self::$_labels[$code] : null; } }
升级
从1.0.*到1.1.*的更改
如果您从1.0.*版本升级,您将不得不修改您的配置。现在不再有localeUrls
组件了。相反,所有内容都被合并到我们自定义的urlManager
组件中。因此,您应将任何针对localeUrls
组件的配置移动到urlManager
组件中。
两个选项也已重命名以提高清晰度
enableDefaultSuffix
现在为enableDefaultLanguageUrlCode
enablePersistence
现在为enableLanguagePersistence
因此,如果您的配置之前是这样的
<?php return [ 'bootstrap' => ['localeUrls'], 'components' => [ 'localeUrls' => [ 'languages' => ['en-US', 'en', 'fr', 'de', 'es-*'], 'enableDefaultSuffix' => true, 'enablePersistence' => false, ], 'urlManager' => [ 'class' => 'codemix\localeurls\UrlManager', ] ] ];
现在应更改为
<?php return [ 'components' => [ 'urlManager' => [ 'class' => 'codemix\localeurls\UrlManager', 'languages' => ['en-US', 'en', 'fr', 'de', 'es-*'], 'enableDefaultLanguageUrlCode' => true, 'enableLanguagePersistence' => false, ] ] ];