symfony 2根据存储在DB中的用户首选项设置区域设置

时间:2013-05-18 10:48:55

标签: php symfony locale

我正在尝试根据存储在数据库中的当前用户的首选项来设置区域设置。

因此,我们的User类有一个getPreferredLanguage,它返回一个语言环境标识('en','fr_FR'等)。

我考虑过以下方法:

  • 注册订阅KernelEvents :: REQUEST事件的“locale”侦听器服务。
  • 此服务可以访问安全上下文(通过其构造函数)
  • 此服务的onKernelRequest方法尝试从安全上下文中获取用户,获取用户首选的语言环境,并将其设置为请求的语言环境。

不幸的是,这不起作用。当调用“locale”侦听器服务的onRequestEvent方法时,安全上下文没有令牌。看起来上下文监听器是在很晚的阶段调用的(优先级为0),并且不可能告诉我的“locale”监听器在安全上下文之前运行。

有谁知道如何修复这种方法,或建议另一种方法?

2 个答案:

答案 0 :(得分:2)

您可能对我在此答案中发布的语言环境监听器感兴趣:Symfony2 locale detection: not considering _locale in session

编辑:如果用户在配置文件中更改了他的语言,则没有问题。如果您正在使用FOSUserBundle(主),您可以挂钩到配置文件编辑成功事件。否则,在配置文件控制器中,如果您使用的是自制系统。以下是FOSUserBundle的示例:

<?php
namespace Acme\UserBundle\EventListener;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ChangeLanguageListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
                FOSUserEvents::PROFILE_EDIT_SUCCESS => 'onProfileEditSuccess',
        );
    }

    public function onProfileEditSuccess(FormEvent $event)
    {
        $request = $event->getRequest();
        $session = $request->getSession();
        $form = $event->getForm();
        $user = $form->getData();
        $lang = $user->getLanguage();

        $session->set('_locale', $lang);
        $request->setLocale($lang);
    }
}

和services.yml

services:
    acme.change_language:
        class: Acme\UserBundle\EventListener\ChangeLanguageListener
        tags:
            - { name: kernel.event_subscriber }

对于多个浏览器中的多个会话没有问题,因为每个新会话都需要新的登录。嗯,好吧,不是在更改语言之后,因为只有当前会话才会更新。但您可以修改LanguageListener以支持此功能 管理员改变语言的情况应该是微不足道的。

答案 1 :(得分:0)

如果您通过Google获得此答案,那么我目前正在使用此解决方案。

    <?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;

class SetLocaleEventSubscriber implements EventSubscriberInterface
{

    private Security $security;
    private TranslatorInterface $translator;

    public function __construct(Security $security, TranslatorInterface $translator)
    {
        $this->security = $security;
        $this->translator = $translator;
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::CONTROLLER => [
                ['setLocale', 1]
            ]
        ];
    }

    public function setLocale(ControllerEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }
        $request = $event->getRequest();
        /**
         * @var \App\Entit\User
         */
        $user = $this->security->getUser();

        if ($user) {;
            $request->setLocale($user->getLocale());
            $this->translator->setLocale($user->getLocale());
        }
    }
}