Documentação do Symfony - versão 3.1
Renderizada do repositório symfony-docs-pt-BR no Github
O Symfony armazena a configuração de localidade na requisição (Request), o que significa que essa configuração não está disponível nas requisições subsequentes. Neste artigo, você vai aprender a armazenar a localidade na sessão, para que ela seja a mesma para cada requisição subsequente.
Para simular que a localidade está armazenada numa sessão, você precisa criar e
registrar um novo event listener.
O listener será parecido com o seguinte. Tipicamente, _locale
é usado
como um parâmetro de roteamento para indicar a localidade, embora, realmente não faz
diferença como você determina a localidade desejada a partir da requisição:
// src/AppBundle/EventListener/LocaleListener.php
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class LocaleListener implements EventSubscriberInterface
{
private $defaultLocale;
public function __construct($defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(GetResponseEvent $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 array(
// must be registered after the default Locale listener
KernelEvents::REQUEST => array(array('onKernelRequest', 15)),
);
}
}
Em seguida, registre o listener:
1 2 3 4 5 6 | services:
app.locale_listener:
class: AppBundle\EventListener\LocaleListener
arguments: ['%kernel.default_locale%']
tags:
- { name: kernel.event_subscriber }
|
1 2 3 4 5 6 | <service id="app.locale_listener"
class="AppBundle\EventListener\LocaleListener">
<argument>%kernel.default_locale%</argument>
<tag name="kernel.event_subscriber" />
</service>
|
1 2 3 4 5 6 7 8 9 | use Symfony\Component\DependencyInjection\Definition;
$container
->setDefinition('app.locale_listener', new Definition(
'AppBundle\EventListener\LocaleListener',
array('%kernel.default_locale%')
))
->addTag('kernel.event_subscriber')
;
|
É isso! Agora celebre alterando a localidade do usuário e vendo que ela está
persistindo em toda a requisição. Lembre-se, para obter a localidade do usuário,
use sempre o método
Request::getLocale
:
// from a controller...
use Symfony\Component\HttpFoundation\Request;
public function indexAction(Request $request)
{
$locale = $request->getLocale();
}
Você pode querer melhorar essa técnica ainda mais e definir a localidade com base na
entidade de usuário do usuário logado. No entanto, uma vez que o LocaleListener
é chamado
antes do FirewallListener
, que é responsável pelo tratamento de autenticação e
definição do token do usuário no TokenStorage
, você não tem acesso ao usuário
que está logado.
Suponha que você tenha definido uma propriedade locale
em sua entidade User
e quer usá-la como localidade para o usuário. Para conseguir isso,
você pode alterar durante o processo de login e atualizar a sessão do usuário
com esse valor de localidade antes de serem redirecionadas para sua primeira página.
Para fazer isso, você precisa de um event listener para o evento
security.interactive_login
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // src/AppBundle/EventListener/UserLocaleListener.php
namespace AppBundle\EventListener;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
/**
* Stores the locale of the user in the session after the
* login. This can be used by the LocaleListener afterwards.
*/
class UserLocaleListener
{
/**
* @var Session
*/
private $session;
public function __construct(Session $session)
{
$this->session = $session;
}
/**
* @param InteractiveLoginEvent $event
*/
public function onInteractiveLogin(InteractiveLoginEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
if (null !== $user->getLocale()) {
$this->session->set('_locale', $user->getLocale());
}
}
}
|
Em seguida, registre o listener:
1 2 3 4 5 6 7 | # app/config/services.yml
services:
app.user_locale_listener:
class: AppBundle\EventListener\UserLocaleListener
arguments: ['@session']
tags:
- { name: kernel.event_listener, event: security.interactive_login, method: onInteractiveLogin }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <!-- app/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="app.user_locale_listener"
class="AppBundle\EventListener\UserLocaleListener">
<argument type="service" id="session"/>
<tag name="kernel.event_listener"
event="security.interactive_login"
method="onInteractiveLogin" />
</service>
</services>
</container>
|
1 2 3 4 5 6 7 8 | // app/config/services.php
$container
->register('app.user_locale_listener', 'AppBundle\EventListener\UserLocaleListener')
->addArgument('session')
->addTag(
'kernel.event_listener',
array('event' => 'security.interactive_login', 'method' => 'onInteractiveLogin'
);
|
Caution
Para atualizar o idioma imediatamente após um usuário alterar as
suas preferências de idioma, você precisa atualizar a sessão após uma
atualização na entidade User
.