【问题标题】:Symfony2 locale languages whole page event listenerSymfony2 语言环境整页事件监听器
【发布时间】:2013-01-31 23:23:39
【问题描述】:

当用户点击语言时,我需要创建一个类似于 facebook lang 系统的系统,例如 france('fr') 页面将重新加载,messages.fr.yml 中的所有内容都将显示...

我尝试创建像/language/{localExtension} 这样的路由,但是当我在那里设置Locale 然后重定向它不起作用...我不知道我假设它只是针对某个页面而不是全局的?因为当我在控制器顶部设置setLocale('fr') 时,它可以工作......

我在使用www.example.com/contact/en/contact/fr等时发现了一些文章

但我想要/contact 和以前选择的语言显示的内容。或者当用户没有更改它时,就像现在一样默认'en'......

我整天都在谷歌搜索,我认为应该通过...服务 => 侦听器和...在 kernel.request 上完成?或类似的东西。

这里是有趣的链接Symfony2 wrong locale detection? 我想这就是我需要的吗?要么?我尝试设置服务并创建侦听器,但出现了一些错误,我什至不知道这是否是创建它的方式:/

【问题讨论】:

    标签: symfony service kernel listener translation


    【解决方案1】:

    是的,出于某种原因,您需要使用监听器:

    <?php
    
    namespace Your\Bundle\Listener;
    
    use Symfony\Component\HttpKernel\Event\GetResponseEvent;
    use Symfony\Component\HttpKernel\KernelEvents;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class LocaleListener implements EventSubscriberInterface
    {
      private $defaultLocale;
    
      public function __construct($defaultLocale = 'en')
      {
      $this->defaultLocale = $defaultLocale;
      }
    
      public function onKernelRequest(GetResponseEvent $event)
      {
      $request = $event->getRequest();
      if (!$request->hasPreviousSession()) {
          return;
      }
    
      if ($locale = $request->attributes->get('_locale')) {
          $request->getSession()->set('_locale', $locale);
      } else {
          $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
      }
      }
    
      static public function getSubscribedEvents()
      {
      return array(
          // must be registered before the default Locale listener
          KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
      );
      }
    }
    ?>
    

    在你的 service.xml 中注册你的监听器:

    <service id="my.listener" class="Your\Bundle\Listener\LocaleListener">
        <argument>%locale%</argument>
        <tag name="kernel.event_subscriber"/>
    </service>
    

    一个如何在你的 twig 模板中实现语言切换器的例子:

    {% for locale in ['en', 'fr','zh'] %}
        <li>
          <a href="{{ path(app.request.get('_route'), app.request.get('_route_params')|merge({'_locale' : locale})) }}">
            {% if locale == 'en' %}
            <img title="English" src="{{ asset('bundles/fkmywebsite/images/UnitedStates.png') }}" alt="English" height="30" width="30"/>
            {% elseif locale == 'fr' %}
            <img title="Français" src="{{ asset('bundles/fkmywebsite/images/France.png') }}" alt="Français" height="30" width="30"/>
            {% endif %}
          </div>
        </li>
    {% endfor %}
    

    【讨论】:

    • 好人,真的很好。我现在无法尝试,因为我使用了语言环境包,因为我找不到答案,而且这里没有人提供帮助,但非常感谢!似乎可以正常工作。
    • locale_listener: class: Acme\DemoBundle\Listener\LocaleListener arguments: ["%locale%"] tags: - { name: 'kernel.event_subscriber' } Yml 配置参考 :)
    【解决方案2】:

    听众工作并帮助了我很多。我重用脚本在​​会话中设置区域设置(带有子标签区域)和语言(区域设置语言代码)

         <?php
        namespace Fer\CaveBundle\EventListener;
        use Symfony\Component\HttpKernel\Event\GetResponseEvent;
        use Symfony\Component\HttpKernel\KernelEvents;
        use Symfony\Component\EventDispatcher\EventSubscriberInterface;
        use Symfony\Component\HttpFoundation\Session\Session;
        use Symfony\Component\DependencyInjection\ContainerInterface;
    
        class LocaleListener implements EventSubscriberInterface
        {
            private $defaultLocale;
            private $locales;
    
        public function __construct($defaultLocale='es', ContainerInterface $container)
        {
            //values from configuration of my bundle
            $backend =  $container->getParameter('cave.backend');
            $this->locales = $backend['_locale'];  
    
        //    $this->locales = array( 'es'=>'es_ES'
        //                            'en'=>'en_GB,en_US',
        //                            'fr'=>'fr_FR,fr_BG'
        //                        );
            //default must exists in _locales array. locale_lookup Default: es_ES
            $this->defaultLocale = locale_lookup(array_keys($this->locales),
                                                $defaultLocale,
                                                false,
                                                current(explode(',',implode(',',array_values($this->locales)))));
    
    
        }
    
        public function onKernelRequest(GetResponseEvent $event)
        {
            $request = $event->getRequest();
            $session = $request->getSession();
    
            //  Locale Get parameters
            if($locale = $request->query->get('_locale'))
            {
                $this->setLocale($request, $session, $locale);
                return;
            }
    
            //  Locale Post parameters with custom form name
            if($locale = $request->request->get('_localeForm'))
            {
             $this->setLocale($request, $session, $locale['_locale']);
             return;
            }
    
            //  Locale session parameters
            if($locale = $session->get('_locale'))
            {
                $this->setLocale($request, $session, $locale);
                return;
            }    
    
            //Locale in browser
            if($locale = $request->getPreferredLanguage()){
                $this->setLocale($request, $session, $locale);
                return;
            }    
    
            $this->setLocale($request, $session, $this->defaultLocale);
            return;
        }
    
        public function setLocale($request,$session,$locale)
        {
                //search language and lookup, default first locale in language
                if(in_array(current(locale_parse($locale)),array_keys($this->locales))){
                    $locale = locale_lookup(explode(',',$this->locales[current(locale_parse($locale))]),
                                        $locale,
                                        false,
                                        current(explode(',',$this->locales[current(locale_parse($locale))])));
                }else{
                    $locale = $this->defaultLocale;
                }
    
                //set session parameter
                if($locale!==$session->get('_locale')){
                    $session->set('_locale',$locale);
                    $session->set('language', current(locale_parse($locale)));//language code
                }
                //Set the default PHP locale.(for translations)
                $request->setLocale($locale);
                //set post parameter
                $request->request->set('_locale',$locale);  
                //set get parameter
                $request->query->set('_locale',$locale);  
    
    
                return;
        }
    
        static public function getSubscribedEvents()
        {
        return array(
            // must be registered before the default Locale listener
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
        );
        }
    
        }
        ?>
    

    如果您发送 post 参数,则控制器中的表单:

        public function indexAction()
        {
            $form = $this->get('form.factory')->createNamedBuilder('_localeForm')
                 ->add('_locale', 'choice', array(
                    'choices'   => array('en' => 'english', 'es' => 'Español'),//etc
                    'required'  => true,
                ))->getForm();
    
                return $this->render(
                'myProject:myBundle:index.html.twig',
                array('_localeForm' => $form->createView())
            );
        }
    

    示例树枝形式:

        <form  action="" method="post"  {{ form_enctype(_localeForm) }}>
        {{ form_widget(_localeForm)}} <br><br>
        <input type="submit" value="Enviar" />
        {{ form_rest(_localeForm) }}
        </form>
    

    在 url 中发送语言环境,最好使用 twig 函数从配置中获取语言环境数组:

        {% for locale in ('fer_cave.backend._locale'|caveParam)|keys %}
        <li {% if locale == app.session.get('language') %}class="active" style="color: red"{% endif %}>
        {#<a href="{{path(app.request.get('_route'), {'_locale': locale}) }}">{{ locale }}</a>#}
        {% set route = app.request.get('_route') %}
        {% set route_params = app.request.get('_route_params') %}
        <a href="{{ path(route, route_params | merge({ '_locale': locale })) }}">{{ locale }}</a>
        {% endfor %}
        {#
        Locale in session: {{app.session.get('_locale')}}<br>
        Language in session: {{app.session.get('language')}}<br>
        Locale as get param: {{app.request.get('_locale')}}<br>
        Locale as post {{app.request.request.get('_locale')}}
        #}
    

    如果您想从捆绑配置中检索语言环境,请将 serviceContainer 添加到侦听器:

        <service id="cave.listener" class="Fer\CaveBundle\EventListener\LocaleListener">
            <argument>%locale%</argument>
            <argument type="service" id="service_container" />
            <tag name="kernel.event_subscriber"/>
        </service>
    

    为什么不呢,myProject/myBUndle/DependencyInjection 中的示例配置数组

                //-------------------ejemplo de backend-------------------//  
         ->arrayNode('backend')
            ->addDefaultsIfNotSet()
            ->children()
                ->arrayNode('_locale')
                    ->addDefaultsIfNotSet()
                    ->children()
                        ->scalarNode('es')->defaultValue('es_ES')->end()//language=>region
                        ->scalarNode('en')->defaultValue('en_GB,en_US')->end()//
                        ->scalarNode('fr')->defaultValue('fr_FR,fr_BG')->end()//                
                    ->end()
                ->end()//end arrayNode('_locale')
                ->scalarNode('encoding')->defaultValue('UTF-8')->end()
            ->end()
        ->end()//end arrayNode('backend')            
    

    bundle 配置参数中的清理器:

    fer_cave.backend: 
      _locale: {es: [es_ES],en: [en_GB,en_US],fr: [fr_FR,fr_BG]}
      encoding: UTF-8
    cave.frontend: 
      _locale: {es: es_ES}    
      encoding: UTF-8 
    

    现在我可以使用 get、post 或浏览器配置来设置 Session _locale 和语言。

    希望我的英语清楚,抱歉,因为不断编辑文本。

    【讨论】:

    • uph....谢谢您的回复...太晚了,我现在没有时间尝试...我以后可能会遇到这个问题,如果有什么我会告诉你:) 但是谢谢你的时间 ;) 不要担心英语 :D 一切都足够干净。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-01
    相关资源
    最近更新 更多