Symfony2 default locale in routing

前端 未结 12 2288
猫巷女王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:18

    I have a full solution to this that I discovered after some research. My solution assumes that you want every route to have a locale in front of it, even login. This is modified to support Symfony 3, but I believe it will still work in 2.

    This version also assumes you want to use the browsers locale as the default locale if they go to a route like /admin, but if they go to /en/admin it will know to use en locale. This is the case for example #2 below.

    So for example:

    1. User Navigates To ->  "/"         -> (redirects)    -> "/en/"
    2. User Navigates To ->  "/admin"    -> (redirects)    -> "/en/admin"
    3. User Navigates To ->  "/en/admin" -> (no redirects) -> "/en/admin"
    

    In all scenarios the locale will be set correctly how you want it for use throughout your program.

    You can view the full solution below which includes how to make it work with login and security, otherwise the Short Version will probably work for you:

    Full Version

    Symfony 3 Redirect All Routes To Current Locale Version

    Short Version

    To make it so that case #2 in my examples is possible you need to do so using a httpKernal listner

    LocaleRewriteListener.php

    router = $router;
            $this->routeCollection = $router->getRouteCollection();
            $this->defaultLocale = $defaultLocale;
            $this->supportedLocales = $supportedLocales;
            $this->localeRouteParam = $localeRouteParam;
        }
    
        public function isLocaleSupported($locale) 
        {
            return in_array($locale, $this->supportedLocales);
        }
    
        public function onKernelRequest(GetResponseEvent $event)
        {
            //GOAL:
            // Redirect all incoming requests to their /locale/route equivlent as long as the route will exists when we do so.
            // Do nothing if it already has /locale/ in the route to prevent redirect loops
    
            $request = $event->getRequest();
            $path = $request->getPathInfo();
    
            $route_exists = false; //by default assume route does not exist.
    
            foreach($this->routeCollection as $routeObject){
                $routePath = $routeObject->getPath();
                if($routePath == "/{_locale}".$path){
                    $route_exists = true;
                    break;
                }
            }
    
            //If the route does indeed exist then lets redirect there.
            if($route_exists == true){
                //Get the locale from the users browser.
                $locale = $request->getPreferredLanguage();
    
                //If no locale from browser or locale not in list of known locales supported then set to defaultLocale set in config.yml
                if($locale==""  || $this->isLocaleSupported($locale)==false){
                    $locale = $request->getDefaultLocale();
                }
    
                $event->setResponse(new RedirectResponse("/".$locale.$path));
            }
    
            //Otherwise do nothing and continue on~
        }
    
        public static function getSubscribedEvents()
        {
            return array(
                // must be registered before the default Locale listener
                KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
            );
        }
    }
    

    To understand how that is working look up the event subscriber interface on symfony documentation.

    To activate the listner you need to set it up in your services.yml

    services.yml

    # Learn more about services, parameters and containers at
    # http://symfony.com/doc/current/book/service_container.html
    parameters:
    #    parameter_name: value
    
    services:
    #    service_name:
    #        class: AppBundle\Directory\ClassName
    #        arguments: ["@another_service_name", "plain_value", "%parameter_name%"]
         appBundle.eventListeners.localeRewriteListener:
              class: AppBundle\EventListener\LocaleRewriteListener
              arguments: ["@router", "%kernel.default_locale%", "%locale_supported%"]
              tags:
                - { name: kernel.event_subscriber }
    

    Finally this refers to variables that need to be defined in your config.yml

    config.yml

    # Put parameters here that don't need to change on each machine where the app is deployed
    # http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
    parameters:
        locale: en
        app.locales: en|es|zh
        locale_supported: ['en','es','zh']
    

    Finally, you need to make sure all your routes start with /{locale} for now on. A sample of this is below in my default controller.php

    get('translator')->trans('Symfony is great');
    
            // replace this example code with whatever you need
            return $this->render('default/index.html.twig', [
                'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
                'translated' => $translated
            ]);
        }
    
        /**
         * @Route("/admin", name="admin")
         */
        public function adminAction(Request $request)
        {
            $translated = $this->get('translator')->trans('Symfony is great');
    
            // replace this example code with whatever you need
            return $this->render('default/index.html.twig', [
                'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
                'translated' => $translated
            ]);
        }
    }
    ?>
    

    Note the requirements requirements={"_locale" = "%app.locales%"}, this is referencing the config.yml file so you only have to define those requirements in one place for all routes.

    Hope this helps someone :)

提交回复
热议问题