Symfony2 default locale in routing

前端 未结 12 2284
猫巷女王i
猫巷女王i 2020-12-01 04:41

I have a problem with routing and the internationalization of my site built with Symfony2.
If I define routes in the routing.yml file, like this:

exampl         


        
12条回答
  •  青春惊慌失措
    2020-12-01 05:13

    The Joseph Astrahan's solution of LocalRewriteListener works except for route with params because of $routePath == "/{_locale}".$path)

    Ex : $routePath = "/{_locale}/my/route/{foo}" is different of $path = "/{_locale}/my/route/bar"

    I had to use UrlMatcher (link to Symfony 2.7 api doc) for matching the actual route with the url.

    I change the isLocaleSupported for using browser local code (ex : fr -> fr_FR). I use the browser locale as key and the route locale as value. I have an array like this array(['fr_FR'] => ['fr'], ['en_GB'] => 'en'...) (see the parameters file below for more information)

    The changes :

    • Check if the local given in request is suported. If not, use the default locale.
    • Try to match the path with the app route collection. If not do nothing (the app throw a 404 if route doesn't exist). If yes, redirect with the right locale in route param.

    Here is my code. Works for any route with or without param. This add the locale only when {_local} is set in the route.

    Routing file (in my case, the one in app/config)

    app:
        resource: "@AppBundle/Resources/config/routing.yml"
        prefix:   /{_locale}/
        requirements:
            _locale: '%app.locales%'
        defaults: { _locale: %locale%}
    

    The parameter in app/config/parameters.yml file

    locale: fr
    app.locales: fr|gb|it|es
    locale_supported:
        fr_FR: fr
        en_GB: gb
        it_IT: it
        es_ES: es
    

    services.yml

    app.eventListeners.localeRewriteListener:
        class: AppBundle\EventListener\LocaleRewriteListener
        arguments: ["@router", "%kernel.default_locale%", "%locale_supported%"]
        tags:
            - { name: kernel.event_subscriber }
    

    LocaleRewriteListener.php

    router = $router;
            $this->routeCollection = $router->getRouteCollection();
            $this->defaultLocale = $defaultLocale;
            $this->supportedLocales = $supportedLocales;
            $this->localeRouteParam = $localeRouteParam;
            $context = new RequestContext("/");
            $this->matcher = new UrlMatcher($this->routeCollection, $context);
        }
    
        public function isLocaleSupported($locale)
        {
            return array_key_exists($locale, $this->supportedLocales);
        }
    
        public function onKernelRequest(GetResponseEvent $event)
        {
            //GOAL:
            // Redirect all incoming requests to their /locale/route equivalent when exists.
            // Do nothing if it already has /locale/ in the route to prevent redirect loops
            // Do nothing if the route requested has no locale param
    
            $request = $event->getRequest();
            $baseUrl = $request->getBaseUrl();
            $path = $request->getPathInfo();
    
            //Get the locale from the users browser.
            $locale = $request->getPreferredLanguage();
    
            if ($this->isLocaleSupported($locale)) {
                $locale = $this->supportedLocales[$locale];
            } else if ($locale == ""){
                $locale = $request->getDefaultLocale();
            }
    
            $pathLocale = "/".$locale.$path;
    
            //We have to catch the ResourceNotFoundException
            try {
                //Try to match the path with the local prefix
                $this->matcher->match($pathLocale);
                $event->setResponse(new RedirectResponse($baseUrl.$pathLocale));
            } catch (\Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
    
            } catch (\Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
    
            }
        }
    
        public static function getSubscribedEvents()
        {
            return array(
                // must be registered before the default Locale listener
                KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
            );
        }
    }
    

提交回复
热议问题