CakePHP 3:在路由器作用域之间切换

CakePHP 3: switching between Router scopes

我有一个简单的路由设置来处理不同的语言。目标是将语言作为 url 中的第一个参数,如 /en/docs/de/docs。语言定义设置为 scopes 如下所示:

$builder = function ($routes)
{
  $routes->connect('/:controller', ['action' => 'index']);
  $routes->connect('/:controller/:action/*', ['action' => 'index']);
};

$languages = ['en', 'de'];
foreach ($languages as $lang) {
  Router::scope('/'.$lang, ['language' => $lang], $builder);
}

Router::addUrlFilter(function ($params, $request) {
  if ($request->param('language')) {
    $params['language'] = $request->param('language');
  }
  else {
    $params['language'] = 'en';
  }
  return $params;
});

每个范围都按预期工作。即使有一些更复杂的连接和前缀(我从上面的代码中删除它们以使代码更具可读性)。

现在的问题是:如何创建一个link来在语言(范围)之间切换?

我尝试了不同的url,但是根据当前的url(例如/de/docs),语言参数对创建的url没有任何影响小号:

Router::url(['language' => 'en', 'controller' => 'docs']);
// -> /de/docs (expected: /en/docs)
Router::url(['language' => 'de', 'controller' => 'docs']);
// -> /de/docs

如何修复路由以获得预期的 urls?

我找到了这种行为的原因。函数 addUrlFilter 在生成 url 时替换了语言参数,结果始终是当前语言。此函数的更新版本可以完成这项工作:

Router::addUrlFilter(function ($params, $request) {
  if (!isset($params['language'])) {
    $params['language'] = $request->param('language');
  }
  return $params;
});

噗,一小时的搜索和尝试...