Giter Club home page Giter Club logo

yii2-localeurls's Introduction

Yii2 Locale URLs

build Latest Stable Version Total Downloads Latest Unstable Version License

Automatic locale/language management through URLs for Yii 2.

IMPORTANT: If you upgraded from version 1.0.* you have to modify your configuration. Please check the section on Upgrading below.

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.

Installation

Install the package through composer:

composer require codemix/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 explicitly 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:

'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 don't want to redirect URLs with lowercase country code, you can set the keepUppercaseLanguageCode option to true.

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.
  • languageCookieOptions: Other options to set on the language cookie.
  • languageSessionKey: The name of the language session key. Default is _language. Since 1.6.0 this can also be set to false to not use the session at all.

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 explicitly 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.

If you explicitely need to create a URL to the default language without any language code, you can also pass an empty string as language:

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

This will give you:

/demo/action

Language Change Event

When persistence is enabled, the component will fire a languageChanged event whenever the language stored in session or cookie changes. Here's an example how this can be used to track user languages in the database:

<?php

'urlManager' => [
    'class' => 'codemix\localeurls\UrlManager',
    'languages' => ['en', 'fr', 'de'],
    'on languageChanged' => `\app\components\User::onLanguageChanged',
]

The static class method in User could look like this:

<?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();
    }
}

Note: A language may already have been selected before a user logs in or signs up. So you should also save or update the language in these cases.

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 explicitly 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

Detection via GeoIP server module

Since 1.7.0 language can also be detected via the webserver's GeoIP module. Note though that this only happens if no valid language was found in the browser settings.

For this feature to work the related GeoIp module must already be installed and it must provide the country code in a server variable in $_SERVER. You can configure the key in $geoIpServerVar. The default is HTTP_X_GEO_COUNTRY.

To enable this feature, you have to provide a list of GeoIp country codes and index them by the corresponding language that should be set:

'geoIpLanguageCountries' => [
    'de' => ['DEU', 'AUT'],
    'pt' => ['PRT', 'BRA'],
],

Excluding Routes / URLs

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

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

Both, keys and values are regular expressions. The keys are patterns that match routes to exclude from language processing during URL creation, whereas the values are patterns for pathInfo that should be excluded during URL parsing.

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

Example Language Selection Widget

There's no widget for language selection included, because there are simply too many options for the markup and behavior of such a widget. But it's very easy to build. Here's the basic idea:

<?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;
    }
}

Upgrading

Changes from 1.0.* to 1.1.*

If you upgrade from a 1.0.* version you'll have to modify your configuration. There no longer is a localeUrls component now. Instead everything was merged into our custom urlManager component. So you should move any configuration for the localeUrls component into the urlManager component.

Two options also have been renamed for more clarity:

  • enableDefaultSuffix is now enableDefaultLanguageUrlCode
  • enablePersistence is now enableLanguagePersistence

So if your configuration looked like this before:

<?php
return [
    'bootstrap' => ['localeUrls'],
    'components' => [
        'localeUrls' => [
            'languages' => ['en-US', 'en', 'fr', 'de', 'es-*'],
            'enableDefaultSuffix' => true,
            'enablePersistence' => false,
        ],
        'urlManager' => [
            'class' => 'codemix\localeurls\UrlManager',
        ]
    ]
];

you should now change it to:

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

yii2-localeurls's People

Contributors

alexantr avatar alxlnk avatar bicf avatar cebe avatar ddinchev avatar jafaripur avatar metalguardian avatar mikehaertl avatar phpnode avatar samdark avatar schmunk42 avatar silverfire avatar terabytesoftw avatar vediovis avatar zrayev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yii2-localeurls's Issues

infinite loop bug + solution

Firstly thank you very much for sharing your solution.

I've got infinite redirect loop.
You can fix infinite loop by insert something like this on line 403

        //don't redirect when we are on same page
        if( $redirectUrl===$_SERVER['REQUEST_URI'] )
            return;

(before redirect)

Yii::$app->getResponse()->redirect($redirectUrl);

Merge LocaleUrl component into UrlManger

I'm not sure why I decided to create a separate localeUrls component. But I think, this is not really neccessary. We can combine everything into the UrlManager class.

While the configuration will become easier, this will als break backwards compatibility. It's thus scheduled for 1.1.0 release.

Get a 404 error page for url .../en/index.php

Not sure how this was done. However, I saw this in the statistics of my web hosting.

It would be great if such an URL would lead to the English index page instead of the 404 error page (in English).

wrong multilanguage url from module

Hi,
Your solution work good in my app and I am glad to have found it. But in my app I use dektrium/yii2-user module and I have wrong urls from this module. I have not found a solution and I will wait for your help.

So, I have
current url - localhost/en/user/settings
and Url::to() function with params
["user/settings/profile", "language" => "uk"]
return to me result
localhost/uk/user/user/settings/profile
but I need
localhost/uk/user/settings/profile

Do you have any idea?

Is it possible to combine this extension with geo IP ?

So if user from France come ti visit my site I would like to load fr language. If user from UK comes to my site I would like to load en-uk language. It seems that this extension is recognizing geo ip https://github.com/rmrevin/yii2-geoip, put is it possible to combine this ext with yours ? I am already using your extension in my website and it is amazing, but now I need to be able to detect location of the user and load language based on that. Is it possible ? Thanks for your great work !

EDIT: so when user comes to my site for the first time, I want to load language based on his location, but he should still be able to chose other languages that app is offering to him via this extension.

PHP Fatal Error – yii\base\ErrorException Class 'LanguageDropdown' not found

I'm using the yii 2.0.3 advanced template and

  1. I've installed the yii2-localurls extension using composer.
  2. I've added namespace app\components; at the top of the LanguageDropdown class
  3. I've put the LanguageDropdown class in my components folder
  4. I've made all the adjustments in the config files as indicated
    and on my form
  5. I've added a use yii\bootstrap\Dropdown; statement
  6. when I call the LanguageDropdown like this: <?php echo LanguageDropdown::widget([]); ?>,
    I get: PHP Fatal Error – yii\base\ErrorException Class LanguageDropdown not found.
    I was expecting a dropdown with languages to show up so that when I select one, the corresponding
    url is triggered.
    I think this is not an issue with this beautiful extension as such, but rather because of my weak programming skills. What I need is a simple dropdown language switcher widget.
    What am I missing? Can please someone help me here?

Thanks in advance and apology for my weak programming skills.

Example Language Selection Widget contains some issues

Your example is great for building custom code. Only some issues avoid it to run fine:

  • line 19:
    Yii::$app->localeUrls->languages
    should be: Yii::$app->urlManager->languages
  • line 25 & 29: $isWildCard
    should be: $isWildcard

Cookie value

I found a bug in protected function processLocaleUrl($request).

Function $this->matchCode($language) expects $language as string but $language = $request->getCookies()->get($this->languageCookieName); is an object

Changes:

Line 273:

    $language = $request->getCookies()->get($this->languageCookieName);

to

    $cookie = $request->getCookies()->get($this->languageCookieName);
    if($cookie){
        $language = $cookie->value;
    }

index page redirect

Everything works as expected but there is a case that google analytics claims is hurting my seo.

I have enableDefaultLanguageUrlCode enabled, as it should be, but google frowns upon a redirect from the index page of a website so http://site.com makes a 302 redirect to http://site.com/defaut-language
For this case, there would ideally be no redirect for the index page url.

I can't see a way to handle this case with any features in the package, I was wondering if you have a suggestion on how to handle this case. I realize that perhaps this is not meant to be in the scope of the functionality.

I would appreciate a suggestion if you have one. I appreciate your work on this package, it has been a great help to me.

Can't set default language via app language

Hi,
In app config I set
'language' => 'th',
and
'urlManager' => [
'class' => 'codemix\localeurls\UrlManager',
'languages' => ['en-US','en','th']
]
then open new private window on bowser or clear cache, the to to my site,
url still go to /en-US instead of /th.

it's mean, we can't set default language via app language right?

check for languages

I noticed that, if I comment out languages, the urlManager starts behaving in weird way and creating wrong URLs, eg.

http:/

instead of

http://192.168.59.103:32772/de/

I am also running into endless redirects on some routes which should be the same, eg. / and site/index - one works, the other is an endless redirect.

I think there should be a check for the languages property, which should contain at least one element. And if not, throw a configuration exception.

What do you think?

URL rules per language

Hi, great plugin, saves a lot of time!

Is there an easy way to change a URL rule for just a certain language? Since the language gets stripped from the rules array in the config, I wasn't sure the best way to handle this. I'm assuming a custom rule class, but how best to do this without interfering with the plugin?

Ex:
'rules' => [ 'contact' => 'site/contact', '<language:fr>/nousjoindre' => 'site/contact' ]

Fallback to default language on unknown language in URL

Implement an option, so that an unknown language code in the URL doesn't give you a 404 but instead redirects to the default language.

Things to consider:

  • This will break URLs that look like a language code
  • Should we optionally include a country code? (ll-cc)

(There's also some discussion about this in #11 )

Can not set default language to anything else than english

I have set 'language' => 'de', in config,
I have set 'languages' => ['de', 'en'] in localeUrls component configuration,
but every time I start my browser (with clean cashe) language is set to en and I want to to de.

What should I do ?

Sorry for closing, wrong button....

Infinite redirects when changing configuration

The language read from session or cookie is not validated against the current list of configured languages. So if a user has a language code stored there and this language is removed from the configuration this leads to an infinite redirect.

Accept different country variants

Requests from Firefox include the language code including any country codes completely in lower case. Localeurls just uses this code as is to set the Yii language.

This is ok for language only. However, if you have country specific language variants, Yii specifies them as upper case (ISO-3166). Also ICU requires the country codes as upper case. Furthermore, if you use the JUI Datepicker, its language specific javascript files have the country code in upper case in their name.
So I suppose converting any country code to upper case before it goes into the Yii language would help.

Another issue is that Localeurls does not fall back from an unsupported language variant to the language without variant. So if I support the 'de' translation, I get an page not found error if the request has 'de-at' as the language code. It could silently switch to 'de' instead.

Adding ending slash to url

Hello,
I'm using your extension and for Seo reasons I need to have some urls ending with slash. Navigating through forums and yii2 references I found that the way to do that is by adding the slash as a suffix

['pattern' => '<nombreGoogle>-tickets', 'route' => 'site/parser', 'suffix' => '/'],

But once I want to define a folder language in order to create a url like /es/barcelona-tickets/ the ending slash is trimmed.
I've found that removing

$url = rtrim($url, '/');

from the UrlManager.php file solves that. Is there any reason for having the rtrim ??

Armenian Language

Hello !!

How do I add a my own language ` Armenian ???
How can i make it ??

Thank you !
Best Regards !!!

Working with layouts?

Hello, I'm quite new to Yii 2 so, perhaps, I'm doing something wrong but:

When I use:

'en-US']) ?>

On a view. The language changes as expected, all working nicely.

When, however, I place this code on a Layout, it doesn't even bother to send it server side, and nothing seems to happen.

Any clue why is this?

Update from 1.3.0 to 1.4.2 breaks application, when YII_ENV=test

When I update from 1.3.0 to 1.4.2, I get an exception for most requested pages (see below), but just during testing (dev and prod works) - any idea what may cause this?

I have this setting enabled:

'enableDefaultLanguageUrlCode' => true,

And I also set:

'showScriptName' => false,
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "2016-02-28 22:41:20 [192.168.172.1][-][-][error][yii\base\Exception] exception 'yii\base\Exception' with message '/de' in /app/vendor/codemix/yii2-localeurls/UrlManager.php:425"
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "Stack trace:"
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "#0 /app/vendor/codemix/yii2-localeurls/UrlManager.php(348): codemix\localeurls\UrlManager->redirectToLanguage('de')"
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "#1 /app/vendor/codemix/yii2-localeurls/UrlManager.php(171): codemix\localeurls\UrlManager->processLocaleUrl(Object(yii\web\Request))"
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "#2 /app/vendor/yiisoft/yii2/web/Request.php(180): codemix\localeurls\UrlManager->parseRequest(Object(yii\web\Request))"
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "#3 /app/vendor/yiisoft/yii2/web/Application.php(75): yii\web\Request->resolve()"
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "#4 /app/vendor/yiisoft/yii2/base/Application.php(375): yii\web\Application->handleRequest(Object(yii\web\Request))"
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "#5 /app/web/index.php(15): yii\base\Application->run()"
[28-Feb-2016 22:41:20] WARNING: [pool www] child 18 said into stderr: "#6 {main}"
172.17.0.6 -  28/Feb/2016:22:41:21 +0000 "GET /index.php" 200
172.17.0.6 -  28/Feb/2016:22:41:24 +0000 "GET /index.php" 500
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "2016-02-28 22:41:24 [192.168.172.1][-][-][error][yii\base\Exception] exception 'yii\base\Exception' with message '/en' in /app/vendor/codemix/yii2-localeurls/UrlManager.php:425"
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "Stack trace:"
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "#0 /app/vendor/codemix/yii2-localeurls/UrlManager.php(348): codemix\localeurls\UrlManager->redirectToLanguage('en')"
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "#1 /app/vendor/codemix/yii2-localeurls/UrlManager.php(171): codemix\localeurls\UrlManager->processLocaleUrl(Object(yii\web\Request))"
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "#2 /app/vendor/yiisoft/yii2/web/Request.php(180): codemix\localeurls\UrlManager->parseRequest(Object(yii\web\Request))"
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "#3 /app/vendor/yiisoft/yii2/web/Application.php(75): yii\web\Request->resolve()"
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "#4 /app/vendor/yiisoft/yii2/base/Application.php(375): yii\web\Application->handleRequest(Object(yii\web\Request))"
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "#5 /app/web/index.php(15): yii\base\Application->run()"
[28-Feb-2016 22:41:24] WARNING: [pool www] child 17 said into stderr: "#6 {main}"
172.17.0.6 -  28/Feb/2016:22:41:25 +0000 "GET /index.php" 500

Small thing

Hello, first of all thank you for this I lost 10 years of mental life before I have found this

I am not a pro-programmer but according to my IDE found one mistake (or not )

substr_replace($string, $replacement, $start, $length)

there is changed the order of the last two arguments.

$url = $length ? substr_replace($url, "/$language", $length,0) : "$language$url";

But this is not what I was going to commit. The thing is I have set in app configuration 'showScriptName' => true, and after language has been stored in session/cookie and requested home page (example.com) the php index.php was replaced with language

My huge changes to code 😄

$url = $length ? substr_replace($url, "/$language", 0, $length) : "index.php/$language";

Thanks,
Marcel

redirect loop with advanced application template

Just pulled master, looks like a very helpful extension.

Once I'm setup on frontend (local vhost), I just get a redirect loop back to frontend. here's my config/main.php:

'bootstrap' => ['log', 'codemix\localeurls\LocaleUrls'],
'localeUrls' => [
  'class' => 'codemix\localeurls\LocaleUrls',
  'enableDefaultSuffix' => true,
  'enableLanguageDetection' => false,
  'enablePersistence' => false,
  'languages' => ['en', 'fr'],
],
'urlManager' => [
  'class' => 'codemix\localeurls\UrlManager',           
  'enablePrettyUrl' => true,
  'showScriptName' => false         
],

I cleared any persistence that may have stuck around, but any request to http://frontend, which should redirect to http://frontend/en is just looping back to http://frontend.

url manager slug pattern problem

this is my *_urlmanager *_settings

        'urlManager' => [
            'class' => 'codemix\localeurls\UrlManager',
            'languages' => ['en', 'ar'],
            'enableDefaultLanguageUrlCode' => false,
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
                '<alias:index|login>' => 'site/<alias>', 
                '<controller:\w+>/<id:\d+>' => '<controller>/view',
                '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
                '<controller:\w+>/<action:\w+>' => '<controller>/<action>', 
                '<controller:\w+>/<action:\w+>/<slug:[A-Za-z0-9 -_.]+>' => '<controller>/<action:\w+>/slug',
                '<controller:\w+>/<slug:[A-Za-z0-9 -_.]+>' => '<controller>/slug',
                'defaultRoute' => '/site/index',
            ],
        ],

i have 2 languages English and Arabic

so i made simple language switcher like this

        $route = Yii::$app->controller->route;
        $params = !empty($_GET) ? '?'.http_build_query($_GET) : '';
        $link = '/'.$route.$params;

and in the navbar i add the language switcher

<?php
    NavBar::begin([
        'brandLabel' => 'My Company',
        'brandUrl' => Yii::$app->homeUrl,
        'options' => [
            'class' => 'navbar-inverse navbar-fixed-top',
        ],
    ]);
    $menuItems = [
        ['label' => 'Home', 'url' => ['/site/index']],
    ];
    if(Yii::$app->language == 'ar'){
        $menuItems[] = ['label' => 'English', 'url' => Url::to([$link, 'language'=>'en'])];
    } else {
        $menuItems[] = ['label' => 'العربية', 'url' => Url::to([$link, 'language'=>'ar'])];
    }
    if (Yii::$app->user->isGuest) {
        $menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
    } else {
        $menuItems[] = '<li>'
            . Html::beginForm(['/site/logout'], 'post')
            . Html::submitButton(
                'Logout (' . Yii::$app->user->identity->username . ')',
                ['class' => 'btn btn-link']
            )
            . Html::endForm()
            . '</li>';
    }
    echo Nav::widget([
        'options' => ['class' => 'navbar-nav navbar-right'],
        'items' => $menuItems,
    ]);
    NavBar::end();
    ?>

but my url generating like this

http://localhost/multi/backend/web/ar/post/slug?slug=my-long-slug-post ----- Arabic
http://localhost/multi/backend/web/post/slug?slug=my-long-slug-post ----- English

http://stackoverflow.com/questions/35574561/yii2-createurl-is-duplicating-the-route/35580052
this is my first attempt to create the simple switcher and i have a duplicating problem so after lots of trying i got above solution it's working well except the slug

Not found page has wrong urls

I have a page with url
something.com/en/controller/method?id=12
and this page does not exist.

Generated links are:
something.com/ru/site/error?id=12
something.com/de/site/error?id=12
something.com/fr/site/error?id=12

But I need
something.com/ru/controller/method?id=12
something.com/de/controller/method?id=12
something.com/fr/controller/method?id=12

Any ideas? Thanks a lot in advance

Logout from Yii2 advanced template cause redirect loop

First of all TNX for your great extention!

I'm using advanced template for my project and I run into a problem with your extention.

Everything works fine except when user logout. logout will redirect to home url with the default language at the end (like this: http://example.com/fa), but it has a redirect loop and home page will never shown till user delete the default language from address bar(like this: http://example.com).

Also "enableDefaultLanguageUrlCode" has its default value(I mean it is false).

What am I doing Wrong? Or maybe its an issue?

url problem for codeception acceptance testing

Forgive me if this is not the proper place for this issue, please direct me to the proper place if you know where that might be. I am new to acceptance testing with codeception and localeurls. An example of my problem is that I am trying to run an acceptance test on the route "en/about"; the error in codeception says: "Can't be on page "/frontend/web/index-test.php/en/about" "; but when I try this url in a browser it gets rewritten to "en/frontend/web/index-test.php/en/about" which must be the problem since it generates a 404 error. Should I have a separate urlmanager configuration for acceptance tests or something? Have you run into this problem before? Thank you for your consideration.

Switch to a user configured language during login

I wonder if there is a way to switch to a language that logged-in users have configured for themselves.
So the language would come from a user record (not part of this extension of course).
During the logged in state the language persistence of this extension would not be used.

I thought to set Yii::$app->language explicitely during the controller init() method, if the user is no guest. However a few days ago it did not work like that.

Rename configuration options

With #13 all configuration options will be part of the urlManager component. We therefore should rename some of them so that it's clear that they are related to language options.

Suggested changes:

  • enableDefaultSuffix -> useSuffixForDefaultLanguage
  • enablePersistence -> enableLanguagePersistence

Slug URL rules not working

There's a problem with slug URL routes, as reported by @ComradePashka.


For example i have slug rule:

'<slug:.+>' => 'site/index'

and default language ru. When I open slug url:

site.com/en/some/slug/url

and then I am trying to change language in my language switcher. I open:

site.com/ru/some/slug/url

so createUrl() will make url which used in redirectToLanguage() so I go to:

site.com/site/index/?slug=some%2Fslug%2Furl

but for my case it should be:

site.com/some/slug/url

We identified the changes in b4c9629 to cause the issue.

We should

  • Add a test case for the above problem
  • Undo changes in b4c962e4 in a way to not break existing tests

Can't get extension to work

screenshot from 2015-07-21 14 39 05
screenshot from 2015-07-21 14 40 13

as you can see when i added the following code in main.php(advanced app)
'urlManager' => [
'class' => 'codemix\localeurls\UrlManager',
'languages' => ['en-US', 'en', 'fr', 'de', 'es-*'],
'enableDefaultLanguageUrlCode' => true,
'enableLanguagePersistence' => false,
],
my whole website got errors, images are not displaying, layout all displaced. what am i missing apart from the code that i inserted in main.php

How to force https

My website should run entirely in https, it's running on a facebook canvas page that required that every with ssl.

But i'm keeping have a problem if I change from secondary language to primary language I get an request without https and this break my website inside facebook canvas page.

Get a look in my network log:
http redirect https language

As you see it call the default language https://domain.com/pt-pt/site (pt-pt is the default language), then is redirected (302) to http://domain.com/site/index (in the image the "popup" with the http url is from the second entry) then this url without the https hit my htaccess than redirect it back to https, but on facebook the website is blocked before this happen because every request must be with ssl.

There is an way to force the use of https every time?

Problem with login in different languages

I'm Using ActiveForm to generate login form on index view of a controller. Like this:

$form = ActiveForm::begin(
    [
        'id' => 'login-form',
        'method' => 'post',
        'action' => 'site/login'
    ]
);

everything is okay when you submit form on default language using 'enableDefaultLanguageUrlCode' => false,

but changing to 'enableDefaultLanguageUrlCode' => true or using other languages for loging in cause 404 error.

One way for login correctly in all languages is to use 'enableDefaultLanguageUrlCode' => false and get the language code, then if it isn't the default one, pass it in form's action, but I think this is not nice!
then what is you suggestion?

absolute url problem

Hi! I have problems with url creating with controller and subdomain
I have this config:

'urlManager' => [
            'class' => 'codemix\localeurls\UrlManager',
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'enableDefaultLanguageUrlCode' => true,

            // List all supported languages here
            // Make sure, you include your app's default language.
            'languages' => [ 'en',  'ar'],
            'rules' => [
                'http://account.test.ru/<ev:(.*)>/' => 'account/<ev>',
            ]
        ],

and when I try to create absolute link:


    <?= $resetLink = Yii::$app->urlManager->createAbsoluteUrl(['/account/reset-password', 'token' => 'ssss']);?>

I get: /arhttp://account.test.ru/reset-password?token=ssss
The problem exists because parent::createUrl($params); at 148 UrlManager.php returns 'http://account...' which gets through $value => $key in $rules array. And then "/$language$url" at 162 string
So I "fix" it with:

            'rules' => [
                'account/<ev>' => 'account/<ev>',
                'http://account.test.ru/<ev:(.*)>/' => 'account/<ev>',
            ]

different controller/action names for different languages

Hi!

Is it possible to create different controller/action names (or lets call them aliases) for different languages that point to the same action?

For example:
/en/contact -> site/contact
/de/kontakt -> site/contact
etc.

So that If the language is 'de' then Url::to(['site/contact']) will return '/de/kontakt'.

Thanks,
Norbert.

Refactor test cases

It would be more logical to first call mockComponent() then mockRequest(). And the second argument to mockRequest() is not used. We could pass a list of URL parameters instead.

enableDefaultLanguageUrlCode disables Yii Debug Toolbar

Haven't done too much digging but setting 'enableDefaultLanguageUrlCode' => true hides the Yii Debug Toolbar from view. Removing this setting restores it.

Yii Version 2.0.4
Environment dev
Debug Mode Yes
PHP Version 5.6.8
Xdebug Enabled
APC Enabled
Memcache Disabled

Case sensitivity

Hi there,

Could you please write why you've decided to lowercase language codes? Is not it more consistent to keep ISO 639-1 codes where last part is in uppercase? Is it possible to make an option which will behave as it was before?

I've just noticed many broken links after update (because some parts of code cannot follow redirects).

Appreciate your work!

Language change automatically.

Hello I have 2 languages on my website pt-PT and en. Portuguese is the default language. In general everything works perfect.

But in the few days during my tests I change the language a lot and sometimes I change from pt-PT to en then change back to pt-PT and it change but if I wait a few seconds and try to open a page it goes back do en.

When this bug appears I have to logout, restart the browser and then it return to normal behaviour.
Do you have any idea what can cause this strange behaviour?

Getting 404 with showScriptName=false

Maybe I misconfigured the app, or don't meet all the minimum requirements.

When I go to "localhost", I am redirected to "localhost/es" and I get a 404 response from the apache server, but when I use showScriptName=true, I'm redirected to "localhost/index.php/es" and the app works.

Here's my UrlManager configuration:

        'class' => codemix\localeurls\UrlManager::className(),
        'enablePrettyUrl'               => true,
        'showScriptName'                => false,
        'enableDefaultLanguageUrlCode'  => true,
        'enableLanguagePersistence'     => true,
        'enableLanguageDetection'       => true,
        'languages'                     => $languages,

trailing slash "incoherence"

Hi,
the problem is the generation of the root URL, sometimes it has the trailing slash sometimes not.

I mean "root URL" a URL without pathinfo

In main.php I've set:

            'languages'               => ['it-*', 'en-*',],
            'showScriptName'  => false,
            'enableLanguageDetection'  => false,
            'enableDefaultLanguageUrlCode' => true,
            'enablePrettyUrl' => true,

The incoherence redised in two functions

  • the function createUrl do append the final slash
  • the function redirectToLanguage don't append the final slash

I think tha the correct beavior is set the final slash

Some examples using createUrl

call URL generated
$this->createUrl(['/']) /it/
$this->createUrl(['']) /it/

Some examples using redirectToLanguage

Initial URL Redirect to URL behavior
www.example.com/site/index www.example.com/it/site/index correct
www.example.com/it/ www.example.com/it/ correct
www.example.com/it www.example.com/it not correct
www.example.com www.example.com/it not correct

A possible solution could be the follows (UlrManager.php:385):

        $pathInfo = $this->_request->getPathInfo();
        if ($pathInfo || $language) {
            $redirectUrl .= '/'.$pathInfo;
        }

Automatic language top menu option

Have you considered adding support for a top menu automatic language option

The idea is to create a optional menu dropdown option (most like Phundament (check the top right menu option based on this extension configuration

Some changes should be made to the extension configuration. Something like changing the available languages from this:

 'languages' => ['en_us', 'en', 'fr', 'de']

to something like this:

 'languages' => [
   ['en_us' => 'English US'],
   ['en' => 'English'],
   ['fr' => 'French'],
   ['de' => 'Deutsch']
]

If you want i can try coding something to accomplish what i'm suggesting.

Let me know what you think

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.