Remy Mellet
Remy Mellet

Reputation: 1795

Change the way the locale is displayed in url with Symfony3

Symfony3 displays by default local in url in that way : website.com/en_GB/ (or "en_gb").

How to change that to display it in that way: website.com/en-gb/ ?

With the below controller and calling to website.com/en-GB/ returns the homepage in French (default language is French). Calling to website.com/en_GB/ returns the page in English.

en_GB : english of UK

Controller:

/**
 * @Route("/{_locale}/", name="homepageLocale")
 * @Template("AppBundle:Default:homepage/homepage.html.twig")
 */
 public function homepageLocaleAction(Request $request) {
    return [];
 }

It's seems that the code decoding the locale is that one:

   Symfony\Component\Intl\Locale.php

   public static function getFallback($locale)
    {
        if (false === $pos = strrpos($locale, '_')) {
            if (self::$defaultFallback === $locale) {
                return 'root';
            }

            // Don't return default fallback for "root", "meta" or others
            // Normal locales have two or three letters
            if (strlen($locale) < 4) {
                return self::$defaultFallback;
            }

            return;
        }

        return substr($locale, 0, $pos);
    }

Upvotes: 2

Views: 856

Answers (1)

yceruto
yceruto

Reputation: 9585

To achieve that you might need decorate "completely" the HttpKernel LocaleListener to something like this:

// AppBundle\EventListener\LocaleListener

private function setLocale(Request $request)
{
    if ($locale = $request->attributes->get('_locale')) {
        if (false !== strpos($locale, '-')) {
            // translate en-gb to en_GB
            $localeParts = explode('-', $locale);
            $locale = $localeParts[0].'_'.strtoupper($localeParts[1]);
        }

        $request->setLocale($locale);
    }
}

private function setRouterContext(Request $request)
{
    if (null !== $this->router) {
        $locale = $request->getLocale();

        // translate en_GB to en-gb
        $locale = strtolower(strtr($locale, '_', '-'));

        $this->router->getContext()->setParameter('_locale', $locale);
    }
}

Note: These two methods are private, it's why we need copy+paste the complete code of the original listener to change its behavior.

More about "How to Decorate Services" here, or creates you own compiler pass to exchange the service class of the locale_listener definition.

Upvotes: 1

Related Questions