1

Here is what I'm trying to achieve :

I have a multilingual site with 2 languages (en, fr) but I I also have 4 iso_codes (us, gb, fr, be).

I want Drupal to understand that /us and /gb for example is an alias of /en (they share the exact same content).

Do you know if there is a way to achieve that programmatically or with a module ?

I'm currently looking into two event subscriber to setPath on the go : RouteCollection and KernelEvents::Request, but no result for now.

Any help would be greatly appreciated.

1

I was able to achieve what I wanted to do by using PathProcessor service.

Here is my services.yml
  mymodule.path_processor:
    class: Drupal\mymodule\PathProcessor\PathProcessor
    arguments: ['@language_manager', '@config.factory', '@path.alias_manager']
    tags:
      - { name: path_processor_inbound, priority: 200 }

And my code in my PathProcessor.php class :

/**
 * Processes the inbound path using path alias lookups.
 */
class PathProcessorCustom implements InboundPathProcessorInterface, OutboundPathProcessorInterface {

    protected $language_manager;
    protected $configFactory;
    protected $aliasManager;

    public function __construct(LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory, AliasManagerInterface $alias_manager) {
        $this->languageManager = $language_manager;
        $this->configFactory = $config_factory;
        $this->aliasManager = $alias_manager;
    }

    public function processInbound($path, Request $request) {
        if (!strpos($path, '/admin/')) {
            $path = $this->removeISOCode($path);
        }

        return $path;
    }

    public function processOutbound($path, &$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
        if (!strpos($path, '/admin/')) {
            $path = $this->insertISOCode($path);
        }

        return $path;
    }

    protected function removeISOCode($path) {
        $langcode = $this->languageManager->getDefaultLanguage()->getId();
        $isocodes = $this->getISOCodeMapping();
        $path_items = explode('/', $path);
        if (isset($path_items[1]) && strlen($path_items[1]) == 2 && in_array($path_items[1], $isocodes[$langcode])) {
            $config_negotiation_url = $this->configFactory->get('language.negotiation')->get('url');
            if (!in_array($path_items[1], $config_negotiation_url['prefixes'])) {
                array_splice($path_items, 1, 1);
                if (count($path_items) == 1) {
                    $config_system_site = $this->configFactory->get('system.site')->get('page');
                    $path = $config_system_site['front'];
                }
                else {
                    $path = implode('/', $path_items);
                    $path = $this->aliasManager->getPathByAlias($path, 'en');
                }
            }
        }

        return $path;
    }

    protected function insertISOCode($path) {
        $path_items = explode('/', $path);
        if (isset($path_items[1]) && strlen($path_items[1]) == 2 && $path_items[1] == 'gb') {
            $config_negotiation_url = $this->configFactory->get('language.negotiation')->get('url');
            if(!in_array($path_items[1], $config_negotiation_url['prefixes'])) {
                $path_items[1] = $language;
            }
        }

        $path = implode('/', $path_items);

        return $path;
    }

    protected function getISOCodeMapping() {
        return [
            'en' => ['gb', 'us'],
            'fr' => ['fr', 'be']
        ];
    }

}

What I do is I decompose URL and remove what I know I don't need and map the URL to an actual content URL. Otherwise, redirect to the default 404.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.