Add locale and requirements to all routes - Symfony2

后端 未结 6 502
离开以前
离开以前 2021-01-04 14:12

I created an application which was not intended to have translations, but now I decided to add this feature. The problem is that all my routes look like this:



        
相关标签:
6条回答
  • 2021-01-04 14:36

    You can see this solution: https://stackoverflow.com/a/37168304/6321297

    The {_local} parameter in route has to be in the app/config routing file if you want to apply it to all your routes.

    This solution uses an event listener to redirect to the good url if there is no {_local} in the url: Change yoursite.com/your/route to yoursite.com/{_locale}/your/route

    It works with or without params.

    0 讨论(0)
  • 2021-01-04 14:40

    You can do it this way, in your global configuration file

    customsite:
      resource: "@CustomSiteBundle/Resources/config/routing.yml"
      prefix:   /{_locale}
      requirements:
        _locale: fr|en
      defaults: { _locale: fr}
    

    Quite slow reaction, but had some similar issue.

    Nice to know is that you can also drop the {_locale} prefix when importing the resource. You would then be required to add {_locale} to every specific route.

    This way you can catch the www.domain.com without a locale from inside your bundle, without having to rewrite the requirements and the defaults.

    You could however, always define the www.domain.com route in your global routing configuration.

    0 讨论(0)
  • 2021-01-04 14:40

    Configure symfony for localization:

    Add localization to the session(please note that the convention is /locale/action):

    goodbye:
    
        pattern: /{_locale}/goodbye
        defaults: { _controller: AcmeBudgetTrackerBundle:Goodbye:goodbye, _locale: en }
        requirements:
            _locale: en|bg
    

    Alternatively locale can be set manually:

    $this->get('session')->set('_locale', 'en_US');
    

    app/config/config.yml

    framework:
        translator: { fallback: en }
    

    In your response:

    use Symfony\Component\HttpFoundation\Response;
    
    public function indexAction()
    {
        $translated = $this->get('translator')->trans('Symfony2 is great');
    
        return new Response($translated);
    }
    

    Configure localization messages localized files:

    messages.bg

    <?xml version="1.0"?>
    <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
        <file source-language="en" datatype="plaintext" original="file.ext">
            <body>
                <trans-unit id="1">
                    <source>Symfony2 is great</source>
                    <target>Symfony2 е супер</target>
                </trans-unit>
                <trans-unit id="2">
                    <source>symfony2.great</source>
                    <target>Symfony2 е супер</target>
                </trans-unit>
            </body>
        </file>
    </xliff>
    

    messages.fr

    <?xml version="1.0"?>
    <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
        <file source-language="en" datatype="plaintext" original="file.ext">
            <body>
                <trans-unit id="1">
                    <source>Symfony2 is great</source>
                    <target>J'aime Symfony2</target>
                </trans-unit>
                <trans-unit id="2">
                    <source>symfony2.great</source>
                    <target>J'aime Symfony2</target>
                </trans-unit>
            </body>
        </file>
    </xliff>
    

    More on the topic: Official symfony documentation

    0 讨论(0)
  • 2021-01-04 14:40

    I think you need a custom loader extending the classic config loader (Symfony\Component\Config\Loader\Loader) and manipulate the pattern

    http://symfony.com/doc/current/cookbook/routing/custom_route_loader.html

    check the first example, i haven't tried it yet, but i'm quite sure it will fit your problem.

    0 讨论(0)
  • 2021-01-04 14:41

    Use JMS18nRoutingBundle (documentation) for this purpose. No custom loader, no coding ...

    The bundle is able to prefix all your routes with the locale without changing anything except some configuration for the bundle. It's the quickest ( and my recommended ) solution to get you started.

    You can even translate existing routes for different locales.

    A quick introduction can be found in this coderwall post.

    0 讨论(0)
  • 2021-01-04 14:52

    The better solution instead of putting requirements in all routes or global scope is to use EventListener and redirect user into same route, but with supported locale, in example:

    <?php
    
    namespace Selly\WebappLandingBundle\EventListener;
    
    use Symfony\Component\HttpFoundation\RedirectResponse;
    
    use Symfony\Component\Routing\RouterInterface;
    use Symfony\Component\HttpKernel\Event\GetResponseEvent;
    use Symfony\Component\HttpKernel\KernelEvents;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class LocaleInParamListener implements EventSubscriberInterface
    {
        /**
         * @var Symfony\Component\Routing\RouterInterface
         */
        private $router;
    
        /**
         * @var string
         */
        private $defaultLocale;
    
        /**
         * @var array
         */
        private $supportedLocales;
    
        /**
         * @var string
         */
        private $localeRouteParam;
    
        public function __construct(RouterInterface $router, $defaultLocale = 'en_US', array $supportedLocales = array('en_US'), $localeRouteParam = '_locale')
        {
            $this->router = $router;
            $this->defaultLocale = $defaultLocale;
            $this->supportedLocales = $supportedLocales;
            $this->localeRouteParam = $localeRouteParam;
        }
    
        public function isLocaleSupported($locale) {
            return in_array($locale, $this->supportedLocales);
        }
    
        public function onKernelRequest(GetResponseEvent $event)
        {
            $request = $event->getRequest();
            $locale = $request->get($this->localeRouteParam);
    
            if(null !== $locale) {
                $routeName = $request->get('_route');
    
                if(!$this->isLocaleSupported($locale)) {
                    $routeParams = $request->get('_route_params');
    
                    if (!$this->isLocaleSupported($this->defaultLocale))
                        throw \Exception("Default locale is not supported.");
    
                    $routeParams[$this->localeRouteParam] = $this->defaultLocale;
                    $url = $this->router->generate($routeName, $routeParams);
    
                    $event->setResponse(new RedirectResponse($url));
                }
            }
        }
    
        public static function getSubscribedEvents()
        {
            return array(
                // must be registered before the default Locale listener
                KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
            );
        }
    }
    

    And services.yml

    services:
        selly_webapp_landing.listeners.localeInParam_listener:
            class: Selly\WebappLandingBundle\EventListener\LocaleInParamListener
            arguments: [@router, "%kernel.default_locale%", "%locale_supported%"]
            tags:
                - { name: kernel.event_subscriber }
    

    In parameters.yml you can specify supported locales:

    locale_supported: ['en_US', 'pl_PL']
    
    0 讨论(0)
提交回复
热议问题