integready/yii2-localeurls

Automatic locale/language management for URLs.

1.1.3 2020-06-17 10:58 UTC

This package is auto-updated.

Last update: 2022-06-17 15:34:43 UTC


README

Forked from

Automatic locale/language management through URLs for Yii 2.

Features

With this extension you can use URLs that contain a language code like:

/en/some/page
/de/some/page
http://www.example.com/en/some/page
http://www.example.com/de/some/page

You can also configure friendly names if you want:

http://www.example.com/english/some/page
http://www.example.com/deutsch/some/page

The language code is automatically added whenever you create a URL, and read back when a URL is parsed. For best user experience the language is autodetected from the browser settings, if no language is used in the URL. The user can still access other languages, though, simply by calling a URL with another language code.

The last requested language is also persisted in the user session and in a cookie. So if the user tries to access your site without a language code in the URL, he'll get redirected to the language he had used on his last visit.

All the above (and more) is configurable of course.

Widget for choosing language

Installation

Install the package through composer:

composer require meshzp/yii2-localeurls

And then add this to your application configuration:

<?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-*'],
        ]

        // ...
    ]
];

Now you're ready to use the extension.

Note: You can still configure custom URL rules as usual. Just ignore any language parameter in your URL rules as it will get removed before parsing and added after creating a URL.

Note 2: The language code will be removed from the pathInfo.

Mode of operation and configuration

Creating URLs

All created URLs will contain the code of the current application language. So if the language was detected to be de and you use:

<?php $url = Url::to(['demo/action']) ?>
<?= Html::a('Click', ['demo/action']) ?>

you'll get URLs like

/de/demo/action

To create a link to switch the application to a different language, you can explicitely add the language URL parameter:

<?= $url = Url::to(['demo/action', 'language'=>'fr']) ?>
<?= Html::a('Click', ['demo/action', 'language'=>'fr']) ?>

This will give you a URL like

/fr/demo/action

Note: The URLs may look different if you use custom URL rules. In this case the language parameter is always prepended/inserted to the final relative/absolute URL.

If for some reason you want to use a different name than language for that URL parameter you can configure it through the languageParam option of the urlManager component.

Default Language

The default language is configured via the language parameter of your application configuration. You always have to include this language in the $languages configuration (see below).

By default the URLs for the default language won't contain any language code. For example:

/
/some/page

If the site is accessed with URLs containing the default language code, the visitor gets redirected to the URLs without language code. For example if default language is fr:

/fr/            -> Redirect to /
/fr/some/page   -> Redirect to /some/page

If enableDefaultLanguageUrlCode is changed to true it's vice versa. The default language is now treated like any other configured language. Requests with URL that don't contain a language code are no longer accessible:

/fr
/fr/some/page
/               -> Redirect to /fr
/some/page      -> Redirect to /fr/some/page

Language Configuration

All languages including the default language must be configured in the languages parameter of the localeUrls component. You should list more specific language codes before the similar looking generic ones (i.e. 'en-US' before 'en'):

'languages' => ['en-US','en-UK','en','fr','de-AT','de'],

Note: If you use country codes, they should always be configured in upper case letters as shown above. The URLs will still always use lowercase codes. If a URL with an uppercase code like en-US is used, the user will be redirected to the lowercase en-us variant. The application language will always use the correct en-US code.

If you want your URL to optionally contain any country variant you can also use a wildcard pattern:

'languages' => ['en-*','de-*'],

Now any URL that matches en-?? or de-?? could be used, like en-us or de-at. URLs without a country code like en and de will also still work:

/en/demo/action
/en-us/demo/action
/en-en/demo/action
/de/demo/action
/de-de/demo/action
/de-at/demo/action

The URLs with a country code will set the full ll-CC code as Yii language whereas the URLs with a language code only, will lead to ll as configured language.

Note: You don't need this if all you want is a fallback of de-AT to de for languages detected from the browser settings. See the section on Language Detection below.

You can also use friendlier names or aliases in URLs, which are configured like so:

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

This will give you URLs like

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

and set the respective language to de or pt-PR if matched.

Persistence

The last language a visitor has used will be stored in the user session and in a cookie. If the user visits your site again without a language code, he will get redirected to the stored language.

For example, if the user first visits:

/de/some/page

then after some time comes back to one of the following URLs:

/some/page      -> Redirect to /de/some/page
/               -> Redirect to /de/
/dk/some/page

In the last case, dk will be stored as last language.

Persistence is enabled by default and can be disabled by setting enableLanguagePersistence to false in the localeUrls component.

You can modify other persistence settings with:

  • languageCookieDuration: How long in seconds to store the language information in a cookie. Set to false to disable the cookie.
  • languageCookieName: The name of the language cookie. Default is _language.
  • languageSessionKey: The name of the language session key. Default is _language.

Reset To Default Language

You'll notice, that there's one problem, if enableDefaultLanguageUrlCode is false (which is the default) and the user has e.g. stored de as last language. How can we now access the site in the default language? Because if we try / we'd be redirected to /de/.

The answer is simple: To create a reset URL, you explicitely include the language code for the default language in the URL. For example if default language is fr:

<?= Url::to(['demo/action', 'language'=>'fr']) ?>
/fr/demo/action -> Redirect to /demo/action

In this case, fr will first be stored as last used language before the user is redirected.

Language Detection

If a user visits your site for the first time and there's no language stored in session or cookie (or persistence is turned off), then the language is detected from the visitor's browser settings. If one of the preferred languages matches your language, it will be used as application language (and also persisted if persistence is enabled).

To disable this, you can set enableLanguageDetection to false. It's enabled by default.

If the browser language contains a country code like de-AT and you only have de in your $languages configuration, it will fall back to that language. Only if you've used a wildcard like de-* or have explicitely configured de-AT or an alias like 'at' => 'de-AT', the browser language including the country code will be used.

Let's look at an example configuration to better understand, how the $languages configuration affects language detection and the created URLs.

'languages' => [
  'en',
  'at' => 'de-AT',
  'de',
  'pt-*'
],

Now say a user visits your site for the first time. Depending on his browser settings, he will be directed to different URLs.

Accept-Language Header Resulting URL code Resulting Yii language
en, en-us, en-US, ... /en en
de-at, de-AT /at de-AT
de, de-de, de-DE, de-ch, ... /de de
pt-BR, pt-br /pt-br pt-BR
pt-PT, pt-pt /pt-pt pt-PT
Any other pt-CC code /pt-cc pt-CC
pt /pt pt

Excluding Routes / URLs

You may want to disable the language processing for some routes and URLs with the $ignoreLanguageUrlPatterns option:

<?php
    'ignoreLanguageUrlPatterns' => [
        '#^site/(login|register)#' => '#^(login|register)#'
        '#^api/#' => '#^api/#',
    ],

Both, keys and values are regular expressions. The keys are patterns that describe routes to exclude from language processing during URL creation, whereas the values are patterns to exclude during URL parsing.

Note: Keys and values don't neccessarily have to relate to each other. It's just for convenience, that the configuration is combined into a single option.