1

I have a simple routing setup to address different languages. The goal is to have the language as a first parameter in the url like /en/docs or /de/docs. The language definitions are set as scopes as show below:

$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;
});

Each of the scopes is working as expected. Even with some more complex connects and prefixes (I removed them from the code above to make the code more readable).

The problem is now: how to create a link to switch between the languages (scopes)?

I tried different urls, but depending on the current url (e.g. /de/docs), the language parameter does not have any effect on the created urls:

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

How to fix the routes to get the expected urls?

mixable
  • 1,068
  • 2
  • 12
  • 42

1 Answers1

1

I found the reason for this behaviour. The function addUrlFilter replaced the language parameter when generating the urls and the result was always the current language. An updated version of this function does the job:

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

Puuh, one hour of searching and trying...

mixable
  • 1,068
  • 2
  • 12
  • 42