Php symfony 2根据数据库中存储的用户首选项设置语言环境
我试图根据数据库中存储的当前用户的首选项设置语言环境 因此,我们的用户类有一个getPreferredLanguage,它返回一个区域设置标识(“en”、“fr\u fr”等) 我考虑了以下方法:Php symfony 2根据数据库中存储的用户首选项设置语言环境,php,symfony,locale,Php,Symfony,Locale,我试图根据数据库中存储的当前用户的首选项设置语言环境 因此,我们的用户类有一个getPreferredLanguage,它返回一个区域设置标识(“en”、“fr\u fr”等) 我考虑了以下方法: 注册订阅KerneleEvents::REQUEST事件的“locale”侦听器服务 此服务可以访问安全上下文(通过其构造函数) 此服务的onKernelRequest方法尝试从安全上下文获取用户,获取用户的首选区域设置,并将其设置为请求的区域设置 不幸的是,这不起作用。调用“locale”侦听器
- 注册订阅KerneleEvents::REQUEST事件的“locale”侦听器服务李>
- 此服务可以访问安全上下文(通过其构造函数)
- 此服务的onKernelRequest方法尝试从安全上下文获取用户,获取用户的首选区域设置,并将其设置为请求的区域设置
是否有人知道如何修复此方法,或建议另一种方法?您可能对locale listener感兴趣,我在下面的回答中发布了此方法: 编辑:如果用户在配置文件中更改其语言,则没有问题。如果您使用的是FOSUserBundle(master),则可以连接到概要文件编辑成功事件。如果您使用自制系统,则在您的配置文件控制器中。以下是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);
}
}
对于多个浏览器中的多个会话没有问题,因为每个新会话都需要新的登录。嗯,好的,在更改语言之后就不会了,因为只有当前会话才会被更新。但您可以修改LanguageListener以支持此功能。如果管理员更改了语言,这种情况应该无关紧要。如果你通过谷歌找到这个答案,我目前正在使用这个解决方案
<?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());
}
}
}
我很感激你的回答,这在一定程度上是有帮助的。我早就考虑过这种方法,但有几个用例需要更进一步的逻辑才能得到支持,例如:用户在登录时更改首选语言(需要更新会话)、多个会话(例如,用户通过多个浏览器登录),以及用户首选语言在DB中直接更改(例如,通过管理页面)。这让我想知道是否没有一个更直接的答案来解决这个问题。是的,这会起作用,这当然是一个比我提出的更好的解决方案,但它确实涉及到很多活动部件。由于我的应用程序环境简单,我会选择我公认的次优解决方案(因为我只处理一个防火墙,所以我可以简单地将它的id注入我的侦听器,并使用它从会话中检索安全令牌)。非常感谢。对于我自己的问题,我找到了一个不完美的答案,这是值得的:在内核事件侦听器中,我可以从会话中获取安全令牌并取消序列化,从而获得用户。不幸的是,这依赖于知道防火墙的“contextKey”,这几乎是硬编码的。例如,如果防火墙是“main”,则可以通过:$token=$session->get(“\u security\u main”)从会话中获取令牌;此逻辑是从ContextListener中提取的。但是在配置过程中,context listener通过了防火墙id。您是否尝试过注入安全上下文?然后您可以从上下文中简单地获取令牌和用户。Pazi,注入安全上下文不起作用。这是此票据的全部要点。我没有正是他的问题,找到好的解决办法了吗?
<?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());
}
}
}