config:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'/<lang>/news/<page>' => 'front/default/news',
'/<lang>/новости/<page>' => 'front/default/news',
],
],
beforeAction:
Yii::$app->language = Yii::$app->request->get('lang')
/en/news/1
echo Url::current(['page' => 2, 'lang' => Yii::$app->language]);
/ru/новости/1
echo Url::current(['page' => 2, 'lang' => Yii::$app->language]);
/en/news/2
/ru/новости/2
/en/новости/2
/ru/новости/2
| Q | A
| ---------------- | ---
| Yii version | 2.0.13 - dev
| PHP version | 7.1.*
| Operating system | Ubuntu 16.04.3
same result without <lang>
Is this bug, or I'm doing something wrong?
I think you've got your rules wrong. Should be:
'/<lang:en>/news/<page>' => 'front/default/news',
'/<lang:ru>/новости/<page>' => 'front/default/news',
@samdark \ same result with this ruleset in So for 2 cases above it takes '/news/<page>' => 'front/default/news',
'/новости/<page>' => 'front/default/news',
yiisoft/yii2/helpers/BaseUrl.php
public static function current(array $params = [], $scheme = false)
{
$currentParams = Yii::$app->getRequest()->getQueryParams();
$currentParams[0] = '/' . Yii::$app->controller->getRoute();
$route = ArrayHelper::merge($currentParams, $params);
return static::toRoute($route, $scheme);
}
Yii::$app->controller->getRoute()
always returns 'front/default/news'
and Url::toRoute()
takes the latest rule from ruleset.'/новости/<page>'
or '/news/<page>'
for all rules with same route.
UrlManager
not able to determine which pattern to use. And takes the last one from list ordered by cacheKey i guess.
@samdark What if we use UrlRule::$name
with route?
Yii::$app->controller->getRouteName() or Yii::$app->controller->getRoutePattern().
Values can be set in UrlRule::parseRequest
for matched pattern.
something like this:
'rules' => [
[
'pattern' => '/новости/<page>',
'route' => 'front/default/news',
'name' => 'news_ru',
'defaults' => [
'page' => 1
],
],
[
'pattern' => '/news/<page>',
'route' => 'front/default/news',
'name' => 'news_en,
'defaults' => [
'page' => 1
],
],
]
Url::to(['news_en', 'page' => 2]); // /news/2
Url::to(['news_ru', 'page' => 2]); // /новости/2
public function createUrl($manager, $route, $params)
{
//...
// match the route part first
if ($route !== $this->route) {
if (($route == $this->name && $this->name != $this->pattern) || $this->_routeRule !== null && preg_match($this->_routeRule, $route, $matches)) {
//...
} else {
//...
}
}
}
Your example is incorrect. Since first rule will match front/default/news
route it will always be used for creating URL. The only weird thing is that you get /ru/новости/2
instead of /ru/news/2
@rob006 Yeah, I know, that it will use front/default/news
for both cases. That's why I'm suggesting add ability differentiation rules with same route using name
property (if it's specified in route definition) like in example above.
@gevorgmansuryan This does not make much sense. Rules should have unique set of route and default params. You should use syntax propsed by @samdark (https://github.com/yiisoft/yii2/issues/14977#issuecomment-336808693) to differentiate URLs for different languages or this:
'rules' => [
[
'pattern' => '/новости/<page>',
'route' => 'front/default/news',
'defaults' => [
'page' => 1,
'lang' => 'ru',
],
],
[
'pattern' => '/news/<page>',
'route' => 'front/default/news',
'defaults' => [
'page' => 1,
'lang' => 'en',
],
],
]
Url::to(['front/default/news', 'page' => 2, 'lang' => 'en']); // /news/2
Url::to(['front/default/news', 'page' => 2, 'lang' => 'ru']); // /новости/2
if you want to hide language prefix from URLs.
@rob006 https://github.com/yiisoft/yii2/issues/14977#issuecomment-336812584 is a real case. I think we should introduce an ability to alias a rule so it's used for creating URLs directly w/o searching for it in a rules array.
I agree with @rob006 because we should keep rules configuration as clean as possibile. Introducing aliases in rules some developers could use aliases improperly, just to avoid to write complete requirements for that route.
@yiisoft/core-developers thoughts?
@rob006 in https://github.com/yiisoft/yii2/issues/14977#issuecomment-337350272
it may work for Url::to
with specified lang, what about Url::current
?
For example I'm using yii\data\Pagination
and it uses Url::current
for creating page urls.
Agreed with @rob006
@gevorgmansuryan It will work fine with Url::current()
. You don't need to pass current language to Url::current()
if it is already in current URL.
http://www.yiiframework.com/doc-2.0/guide-helper-url.html#creating-urls
Most helpful comment
@gevorgmansuryan This does not make much sense. Rules should have unique set of route and default params. You should use syntax propsed by @samdark (https://github.com/yiisoft/yii2/issues/14977#issuecomment-336808693) to differentiate URLs for different languages or this:
if you want to hide language prefix from URLs.