Php 如何使用Symfony 4更改用户区域设置?
我试图用Symfony从数据库中的字段“locale”更改用户区域设置。我阅读了Symfony手册(例如如何粘贴会话),但在我的应用程序中没有任何功能。Translator仍将获取默认区域设置 我创建了监听器、订阅者。。。动态更改区域设置,但由于它们是在防火墙侦听器之前加载的,因此无法更改当前值 我试图更改优先订户,但丢失了用户实体。我试图在控制器中设置区域设置请求,但我认为为时已晚 我不想在URL中添加区域设置 这里是我的订户-侦听器-代码:Php 如何使用Symfony 4更改用户区域设置?,php,symfony,symfony4,symfony-translator,Php,Symfony,Symfony4,Symfony Translator,我试图用Symfony从数据库中的字段“locale”更改用户区域设置。我阅读了Symfony手册(例如如何粘贴会话),但在我的应用程序中没有任何功能。Translator仍将获取默认区域设置 我创建了监听器、订阅者。。。动态更改区域设置,但由于它们是在防火墙侦听器之前加载的,因此无法更改当前值 我试图更改优先订户,但丢失了用户实体。我试图在控制器中设置区域设置请求,但我认为为时已晚 我不想在URL中添加区域设置 这里是我的订户-侦听器-代码: public function onKernelR
public function onKernelRequest(RequestEvent $event)
{
$user = $this->tokenStorage->getToken()->getUser();
$request = $event->getRequest();
$request->setLocale($user->getLocale());
}
在订阅服务器中,我添加了:
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => [['onKernelRequest', 0]],
];
}
这里是我的完整代码:
framework.yml:
default_locale: fr
services.yml:
parameters:
locale: 'fr'
app_locales: fr|en|
translation.yml:
framework:
default_locale: '%locale%'
translator:
paths:
- '%kernel.project_dir%/translations'
fallbacks:
- '%locale%'
LocaleSubscriber.php:
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class LocaleSubscriber implements EventSubscriberInterface
{
private $defaultLocale;
public function __construct($defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}
// try to see if the locale has been set as a _locale routing parameter
if ($locale = $request->attributes->get('_locale')) {
$request->getSession()->set('_locale', $locale);
} else {
// if no explicit locale has been set on this request, use one from the session
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}
}
public static function getSubscribedEvents()
{
return [
// must be registered before (i.e. with a higher priority than) the default Locale listener
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}
}
UserLocaleSubscriber.php
// src/EventSubscriber/UserLocaleSubscriber.php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
/**
* Stores the locale of the user in the session after the
* login. This can be used by the LocaleSubscriber afterwards.
*/
class UserLocaleSubscriber implements EventSubscriberInterface
{
private $session;
public function __construct(SessionInterface $session)
{
$this->session = $session;
}
public function onInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
if (null !== $user->getLocale()) {
$this->session->set('_locale', $user->getLocale());
}
}
public static function getSubscribedEvents()
{
return [
SecurityEvents::INTERACTIVE_LOGIN => 'onInteractiveLogin',
];
}
}
Ex控制器注释:
/**
* @Route("/user/locale", name="user_locale", requirements={"_locale" = "%app.locales%"})
* @Route("/{_locale}/user/locale", name="user_locale_locale", requirements={"_locale" = "%app.locales%"})
*/
如果看不到您使用的完整代码,很难提供帮助 Symfony也有自己的LocaleListener。确保首先执行您的
/**
*@return数组
*/
公共静态函数getSubscribedEvents()
{
返回[
//必须在默认区域设置侦听器之前注册(即优先级高于)
KernelEvents::REQUEST=>[['onKernelRequest',20]],
];
}
debug:event-kernel.request
查找防火墙侦听器的优先级UserLocaleSubscriber
感谢您的回答,我试图将优先级设置为20、15或17,但令牌存储是空的。Symfony文档中写道:“您可能希望进一步改进此技术,并根据登录用户的用户实体定义区域设置。但是,由于LocaleSubscriber是在FirewallListener之前调用的,FirewallListener负责处理身份验证并在TokenStorage上设置用户令牌,因此您无法访问登录的用户。“即使区域设置存储在会话中,defaultLocale仍然应用。@Alexander将使用类似于此工作的方法:我在会话中丢失区域设置$请求->getSession()->getLocale()为空。结果,翻译器获得了备用语言环境。我如何解决这个问题?
// src/EventSubscriber/UserLocaleSubscriber.php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* Stores the locale of the user in the session after the
* login. This can be used by the LocaleSubscriber afterwards.
*/
class UserLocaleSubscriber implements EventSubscriberInterface
{
private $session;
private $translator;
public function __construct(SessionInterface $session, TranslatorInterface $translator)
{
$this->session = $session;
$this->translator = $translator;
}
public function onInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
if (null !== $user->getLocale()) {
$this->translator->setLocale($user->getLocale());
}
}
public static function getSubscribedEvents()
{
return [
SecurityEvents::INTERACTIVE_LOGIN => ['onInteractiveLogin', 7]
];
}
}