One controller with a single route, different paths in different languages:
my_module.routing.yml
custom.route:
path: '/path-english'
defaults:
_controller: '\Drupal\my_module\Controller\MyController::method'
requirements:
_permission: 'access content'
This works for english (default language), but say we want /path-deutsch
in German. We need to manipulate the path using a PathProcessor.
Set up the service in my_module.services.yml
:
services:
my_module.path_processor:
class: Drupal\my_module\Path\PathProcessor
arguments: ['@language_manager']
tags:
- { name: path_processor_inbound, priority: 50 }
- { name: path_processor_outbound, priority: 50 }
The class is inmy_module/src/Path/PathProcessor.php
:
<?php
namespace Drupal\my_module\Path;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Symfony\Component\HttpFoundation\Request;
/**
* Rewrites inbound and outbound paths.
*/
class PathProcessor implements InboundPathProcessorInterface, OutboundPathProcessorInterface {
/**
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
*/
public function __construct(LanguageManagerInterface $language_manager) {
$this->languageManager = $language_manager;
}
/**
* {@inheritdoc}
*/
public function processInbound($path, Request $request) {
if ($this->languageManager->getCurrentLanguage()->getId() === 'de' && $path === '/path-deutsch') {
return '/path-english';
}
return $path;
}
/**
* {@inheritdoc}
*/
public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
if ($path === '/path-english') {
if ($options['language']->getId() === 'de') {
return '/path-deutsch';
}
}
return $path;
}
}
processInbound
rewrites the German path in the request to the route used by the controller.
processOutbound
ensures that any generated links in a German context use the correct German path. (This doesn't work if you use two separate controller routes.)
// Will return '/path-deutsch'.
$url = Url::fromRoute('custom.route', ['language' => 'de'])->toString();
This means that the language switcher block etc. will automatically use the correct path.