大夏实验室/yii2-localeurls

自动对URL进行区域/语言管理。

安装次数: 217

依赖项: 0

建议者: 0

安全性: 0

星标: 0

关注者: 3

分支: 0

开放性问题: 0

类型:yii2-extension

1.0.0 2018-03-08 05:42 UTC

This package is auto-updated.

Last update: 2024-09-23 07:44:08 UTC


README

Build Status Latest Stable Version Total Downloads Latest Unstable Version License

从codemix/yii2-localeurls分叉,为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 daxslab/yii2-localeurls

然后将其添加到您的应用程序配置中

<?php
return [

    // ...

    'components' => [
        // ...

        // Override the urlManager component
        'urlManager' => [
            'class' => 'daxslab\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,则相反。现在将默认语言视为任何其他配置的语言。不包含语言代码的URL请求不再可访问

/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-usde-at。没有国家代码的 URL,如 ende,也将继续工作。

/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 将导致使用配置的语言的 ll

注意:如果您只想将浏览器设置中检测到的语言从 de-AT 重置为 de,则不需要此功能。请参阅下文关于 语言检测 的部分。

您还可以在 URL 中使用更友好的名称或别名,配置如下。

'languages' => ['en', 'german' => 'de', 'br' => 'pt-BR'],
<?= Url::to(['demo/action', 'language' => 'de']) ?>

这将为您提供如下 URL

/german/demo/action
/br/demo/action

并将相应的语言设置为 dept-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' => 'daxslab\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 模式。

注意:键和值不一定必须相关。这只是为了方便,将配置合并为一个选项。

示例语言选择小部件

没有包含语言选择小部件,因为对于这样的小部件的标记和行为有太多的选项。但是,构建它非常简单。以下是基本思路

<?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' => 'daxslab\localeurls\UrlManager',
        ]
    ]
];

现在您应该将其更改为

<?php
return [
    'components' => [
        'urlManager' => [
            'class' => 'daxslab\localeurls\UrlManager',
            'languages' => ['en-US', 'en', 'fr', 'de', 'es-*'],
            'enableDefaultLanguageUrlCode' => true,
            'enableLanguagePersistence' => false,
        ]
    ]
];