用户区域设置在第一次请求时不起作用

时间:2013-09-06 01:09:34

标签: symfony locale event-listener sonata-user-bundle

我的网站正在运行Symfony,主版本。到目前为止,我能够使用网站上的LocalListener logic,但由于代码与我的版本不兼容而略有不同。 (我认为)我只是这样简化了 onKernelRequest 方法:

public function onKernelRequest(GetResponseEvent $event)
{
    $request = $event->getRequest();
    if (!$request->hasPreviousSession()) {
        return;
    }

    if ($locale = $request->get('_locale')) {
        $request->getSession()->set('_locale', $locale);
    }
    $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}

这样,我可以使用these paths在我的页面上放置一个简单的语言选择器,并在第一次请求时应用新语言。 (如果我离开“其他”条件,就不会发生这种情况)

然后我想考虑用户帐户中存储的区域设置,以防用户登录并在其个人资料中指定了区域设置。所以我在函数中添加了这段代码:

public function onKernelRequest(GetResponseEvent $event)
{
    $request = $event->getRequest();
    if (!$request->hasPreviousSession()) {
        return;
    }

    $token = $this->container->get('security.context')->getToken();
    if (is_object($token)) {
    $user = $token->getUser();
    if (is_object($user)) {
        $userlocale = $user->getLocale();
        if ($userlocale) {
        $request->getSession()->set('_locale', $userlocale);
        $request->setLocale($userlocale);
        return;
        }
    }
}

    if ($locale = $request->get('_locale')) {
        $request->getSession()->set('_locale', $locale);
    }
    $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}

(编辑:抱歉压痕不好,不知何故stackoverflow不想正确缩进...)

基本上,它检查用户是否已登录,如果有用户,如果他或她已设置了区域设置,并且是否已设置,则将区域设置设置为用户区域设置。现在这个有效,但......不是即刻的。每当我在我的个人资料中登录或更改我的语言环境时,我到达的下一页仍然是以前设置的语言环境。只有当我加载新页面时,它才会正确地更改其翻译,并为下一次请求保留这种方式。

所以这是我的问题:是否有一些我应该添加的内容,以便在这些后登录和后配置文件编辑请求中进行此更改?

4 个答案:

答案 0 :(得分:2)

您不仅需要设置新的区域设置,还需要在执行此操作后重定向用户,以使更改生效。

此外,it's not a good practice to store the locale in the session — you should keep the locale in the URL。这样,重定向到具有适当区域设置的URL会更有意义。

答案 1 :(得分:1)

非常感谢Elnur我决定回到我的jms_i18n解决方案(参见Elnur的回答中的评论),我发现this question帮我构建了自己的解决方案。所以我从EventSubscriber扩展类切换到我自己的简单“未扩展”类。这是工作代码:

<?php
//src/myApp/MainBundle/EventListener/LocaleListener.php
namespace myApp\MainBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Cookie;

class LocaleListener
{
  private $container;

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

  public function onKernelRequest(GetResponseEvent $event)
  {
    if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
      return;
    }
    $request = $event->getRequest();
    if ($request->getRequestFormat() !== 'html') {
      return;
    }

    $token = $this->container->get('security.context')->getToken();
    if (is_object($token)) {
      $user = $token->getUser();
      if (is_object($user)) {
        $userlocale = $user->getLocale();
        if ($userlocale && $userlocale != $request->get('_locale')) {
          $parmArray = $request->get('_route_params');
          $parmArray['_locale'] = $userlocale;

          $redirectResponse = new RedirectResponse( $this->container->get('router')->generate($request->get('_route'), $parmArray) );
          $redirectResponse->headers->setCookie( new Cookie('b_locale', $userlocale, time() + 2592000) );

          $event->setResponse( $redirectResponse );
        }
      }
    }
  }
}

以下是如何在服务中注册它:

# app/config/config.yml
services:
    myapp_main.locale_listener:
        class: myApp\MainBundle\EventListener\LocaleListener
        arguments: ["@service_container"]
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

非常感谢大家改变主意。

答案 2 :(得分:0)

我不确定这是否有效。但是当用户登录时,将在他/她的会话中设置区域设置。

你可以在你的听众中做这样的事情:

    $request = $event->getRequest();
    $session = $request->getSession();
    $locale = $session->get('_locale');
    if (!empty($locale)) {
     $request->setLocale($locale);
    }

在用户将选择区域设置的链接上,您可以创建一些操作

    public function localeAction($locale)
    {
      $this->get('session')->set('_locale', $locale);

      return $this->redirect($this->generateUrl('route'));
    }

答案 3 :(得分:0)

我发现你的听众有问题,特别是:

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

您正在请求hasPreviousSession并且它有但它没有我不知道是什么原因导致的语言环境但这是第一个请求的主要问题。如果你改变它:

 if ($request->hasPreviousSession() && $this->defaultLocale == $request->get('_locale') ) {
        return;
    }

它会像魅力一样工作:)