From f080c39eec2e989173f3c10f3fba36f3043bdd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20H=C3=A4rtl?= Date: Mon, 9 Jan 2017 13:26:05 +0100 Subject: [PATCH] Issue #60 Cleanup creation logic and allow empty default language --- README.md | 12 ++++++++++++ UrlManager.php | 38 +++++++++++++++++++------------------- tests/UrlCreationTest.php | 8 ++++++++ 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 73058e1..dff1627 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,18 @@ for the default language in the URL. For example if default language is `fr`: 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: + +```php + '']) ?> +``` + +This will give you: + + /demo/action + + ### Language Detection If a user visits your site for the first time and there's no language stored in session diff --git a/UrlManager.php b/UrlManager.php index 890bf02..cd5a55a 100644 --- a/UrlManager.php +++ b/UrlManager.php @@ -194,31 +194,29 @@ public function createUrl($params) if ($this->enableLocaleUrls && $this->languages) { $params = (array) $params; - if (isset($params[$this->languageParam])) { - $language = $params[$this->languageParam]; + $addLanguage = false; + $isLanguageGiven = isset($params[$this->languageParam]); + $language = $isLanguageGiven ? $params[$this->languageParam] : Yii::$app->language; + $isDefaultLanguage = $language===$this->getDefaultLanguage(); + + if ($isLanguageGiven) { unset($params[$this->languageParam]); - $languageRequired = true; - } else { - $language = Yii::$app->language; - $languageRequired = false; } - // Do not use prefix for default language to prevent unnecessary redirect if there's no persistence and no detection + $url = parent::createUrl($params); + if ( - $languageRequired && $language===$this->getDefaultLanguage() && - !$this->enableDefaultLanguageUrlCode && !$this->enableLanguagePersistence && !$this->enableLanguageDetection - ) { - $languageRequired = false; - } + // Only add language if it's not empty and ... + $language!=='' && ( - $url = parent::createUrl($params); + // ... it's not the default language or default language uses URL code ... + !$isDefaultLanguage || $this->enableDefaultLanguageUrlCode || - // Unless a language was explicitely specified in the parameters we can return a URL without any prefix - // for the default language, if suffixes are disabled for the default language. In any other case we - // always add the suffix, e.g. to create "reset" URLs that explicitely contain the default language. - if (!$languageRequired && !$this->enableDefaultLanguageUrlCode && $language===$this->getDefaultLanguage()) { - return $url; - } else { + // ... or if a language is explicitely given, but only if either persistence or detection is enabled. + // This way a "reset URL" can be created for the default language. + $isLanguageGiven && ($this->enableLanguagePersistence || $this->enableLanguageDetection) + ) + ) { $key = array_search($language, $this->languages); if (is_string($key)) { $language = $key; @@ -250,6 +248,8 @@ public function createUrl($params) } $needleLength = strlen($needle); return $needleLength ? substr_replace($url, "$needle/$language", 0, $needleLength) : "/$language$url"; + } else { + return $url; } } else { return parent::createUrl($params); diff --git a/tests/UrlCreationTest.php b/tests/UrlCreationTest.php index eb2d57e..421367c 100644 --- a/tests/UrlCreationTest.php +++ b/tests/UrlCreationTest.php @@ -115,6 +115,7 @@ public function testCreateHomeUrlWithLanguageFromUrl() ], ]); $this->mockRequest('/de/site/page'); + $this->assertEquals($this->prepareUrl('/'), Url::to(['/site/index', 'language' => ''])); $this->assertEquals($this->prepareUrl('/de'), Url::to(['/site/index'])); $this->assertEquals($this->prepareUrl('/de?x=y'), Url::to(['/site/index', 'x' => 'y'])); } @@ -129,6 +130,7 @@ public function testCreateAbsoluteHomeUrlWithLanguageFromUrl() ], ]); $this->mockRequest('/de/site/page'); + $this->assertEquals('http://localhost'.$this->prepareUrl('/'), Url::to(['/site/index', 'language' => ''], 'http')); $this->assertEquals('http://localhost'.$this->prepareUrl('/de'), Url::to(['/site/index'], 'http')); $this->assertEquals('http://localhost'.$this->prepareUrl('/de?x=y'), Url::to(['/site/index', 'x' => 'y'], 'http')); } @@ -154,6 +156,10 @@ public function testCreateUrlWithSpecificLanguage() ], ]); $this->mockRequest('/de/site/page'); + $this->assertEquals($this->prepareUrl('/'), Url::to(['/', 'language' => ''])); + $this->assertEquals($this->prepareUrl('/demo/action'), Url::to(['/demo/action', 'language' => ''])); + $this->assertEquals($this->prepareUrl('/en'), Url::to(['/', 'language' => 'en'])); + $this->assertEquals($this->prepareUrl('/en/demo/action'), Url::to(['/demo/action', 'language' => 'en'])); $this->assertEquals($this->prepareUrl('/en-us'), Url::to(['/', 'language' => 'en-US'])); $this->assertEquals($this->prepareUrl('/en-us/demo/action'), Url::to(['/demo/action', 'language' => 'en-US'])); $this->assertEquals($this->prepareUrl('/en-us/demo/action?x=y'), Url::to(['/demo/action', 'language' => 'en-US', 'x'=>'y'])); @@ -388,10 +394,12 @@ public function testCreateUrlWithoutDefaultLanguageIfPersistenceAndDetectionDisa 'enableLanguagePersistence' => false, 'enableLanguageDetection' => false, 'rules' => [ + '' => 'site/index', '/foo//bar' => 'slug/action', ], ]); $this->mockRequest('/de/site/page'); + $this->assertEquals($this->prepareUrl('/'), Url::to(['/site/index', 'language' => 'en'])); $this->assertEquals($this->prepareUrl('/demo/action'), Url::to(['/demo/action', 'language' => 'en'])); $this->assertEquals($this->prepareUrl('/demo/action?x=y'), Url::to(['/demo/action', 'x' => 'y', 'language' => 'en'])); $this->assertEquals($this->prepareUrl('/foo/baz/bar'), Url::to(['/slug/action', 'term' => 'baz', 'language' => 'en']));