通过GET param在Symfony中设置Locale

时间:2013-06-24 11:23:21

标签: symfony internationalization

我创建了一个控制器,根据加密的GET参数手动设置安全令牌。我使用它来创建一个远程登录URL,当用户跟随​​此链接时将执行登录。

现在我想添加区域设置。提供Lang参数时,应设置语言环境。我把它添加到我的控制器:

$lang = strtolower($lang);
$this->getRequest()->getSession()->set('_locale', $lang);
$this->getRequest()->setLocale($lang);
$this->container->get('translator')->setLocale($lang);

根据开发栏将_locale变量设置到设置中。但是没有加载语言文件,它会回退到默认语言。

我读到了创建一个Listener来实现这一点,但在我看来,当你想在URL中提供语言时这很有用。我不想将其添加到我的路由中,我只想在创建会话时设置语言环境。

更新

我选择Symfony提供的'simulate old beheaviour'解决方案。设置请求区域设置似乎不起作用。当我在我的Twig模板中回显这个时,值不相等:req lang: {{ app.request.locale }} session: {{ app.session.get('_locale') }}。下面发布的LocaleListener正在工作,我通过插入die()检查了这一点,并且设置转换器服务的区域设置似乎正在工作。

因此,通过设置翻译器的语言环境,我得到了这个功能。我不明白为什么。翻译服务不应该使用请求区域设置吗?为什么我需要手动设置?

Request对象中的语言环境是否为翻译以外的其他内容?

<?php
namespace Mb\MyBundle\Listener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class LocaleListener implements EventSubscriberInterface
{
    private $translator;

    public function __construct($translator) {
        $this->translator = $translator;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        if (!$request->hasPreviousSession()) {
            return;
        }

        if (strlen( $request->getSession()->get('_locale') )) {
            $request->setLocale($request->getSession()->get('_locale'));
            $this->translator->setLocale($request->getSession()->get('_locale'));
        }
    }

    static public function getSubscribedEvents()
    {
        return array(
            // must be registered before the default Locale listener
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
        );
    }
}

在我的services.yml中,我有:

mb.locale.listener:
    class: Mb\MyBundle\Listener\LocaleListener
    arguments: [@translator]
    tags:An
      - { name: kernel.event_subscriber }

如果有人能解释我这里发生了什么,我会非常高兴: - )

1 个答案:

答案 0 :(得分:0)

这对我有用。

必须降低优先级,以便这是发生的最后一个事件,并且必须始终从会话中设置 cookie。

然后,在控制器中我得到正确的语言。此外,我正在通过 SessionInterface 上的 api 调用设置语言。

<?php

namespace App\EventSubscriber\Session;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class LocaleSubscriber implements EventSubscriberInterface
{
    /**
     * @var string $defaultLocale
     */
    private $defaultLocale;

    /**
     * LocaleSubscriber constructor.
     * @param string $defaultLocale
     */
    public function __construct($defaultLocale = 'en')
    {
        $this->defaultLocale = $defaultLocale;
    }

    /**
     * @param RequestEvent $event
     */
    public function onKernelRequest(RequestEvent $event)
    {
        $request = $event->getRequest();
        if (!$request->hasPreviousSession()) {
            return;
        }

        // if no explicit locale has been set on this request, use one from the session
        $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents(): array
    {
        return array(
            // must be registered before (i.e. with a higher priority than) the default Locale listener
            KernelEvents::REQUEST => array(array('onKernelRequest', 0)),
        );
    }
}