Как сделать локаль "липкой" во время сессии пользователя
Дата обновления перевода 2023-06-30
Как сделать локаль "липкой" во время сессии пользователя
Symfony сохраняет настройку локали в запросе, что означает, что эта же настройка не сохраняется автоматически ("липко") для всех запросов. Но вы можете сохранять локаль в сессии так, чтобы она была использована в последующих запросах.
Создание LocaleSubscriber
Создайте нового подписчика событий . Обычно, _locale
используется в качестве параметра маршрутизации, чтобы обозначить локаль, хотя вы
можете определять правильную локаль так, как вам хочется:
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 35 36 37 38 39 40
// src/AppBundle/EventSubscriber/LocaleSubscriber.php
namespace AppBundle\EventSubscriber;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class LocaleSubscriber implements EventSubscriberInterface
{
private $defaultLocale;
public function __construct($defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}
// попробуйте увидеть, была ли локаль установлена как параметр маршрутизации _locale
if ($locale = $request->attributes->get('_locale')) {
$request->getSession()->set('_locale', $locale);
} else {
// если для этого запроса не было ясно установлено никакой локали, используйте её из сесии
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}
}
public static function getSubscribedEvents()
{
return array(
// должен быть зарегистрирован после слушателя локали по умолчанию
KernelEvents::REQUEST => array(array('onKernelRequest', 15)),
);
}
}
Если вы используете конфигурацию default services.yml ,
то вы закончили! Symfony автоматически узнает о подписчике событий и вызовет
метод onKernelRequest
для каждого запроса.
Чтобы увидеть, как это работает, либо установите ключ _locale
в сессии вручную
(например, через маршрут и контроллер "Изменить локаль"), или создайте маршрут с
_locale по умолчанию .
Вот и всё! Теперь отпразднуйте, изменив локаль пользователя и увидев, что она "прилипает" во всём запросе.
Помните, чтобы получить локаль пользователя, всегда используйте метод Request::getLocale:
1 2 3 4 5 6 7
// from a controller...
use Symfony\Component\HttpFoundation\Request;
public function indexAction(Request $request)
{
$locale = $request->getLocale();
}
Установка локали, основываясь на предпочтениях пользователя
Вы можете захотеть улучшить эту технику и обозначить локаль, основываясь на сущности
пользователя, выполнившего вход. Однако, так как LocaleSubscriber
вызывается перед
FirewallListener
, который отвечает за управление аутентификацией и установку метки
пользователя в TokenStorage
, у вас нет доступа к пользователю, выполнившему вход.
Представьте, что у вас есть свойство locale
в вашей сущности User
и
вы хотите использовать это в качестве локали данного пользователя. Чтобы сделать
это, вы можете подключиться к процессу выполнения входа и обновить сессию
пользователя с этим значением локали до того, как он будет перенаправлен на свою
первую страницу.
Чтобы сделать это, вам понадобится подписчик событий в событии
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
// src/AppBundle/EventSubscriber/UserLocaleSubscriber.php
namespace AppBundle\EventSubscriber;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Сохраняет локаль пользователя в сессии после выполнения входа.
* Это может быть использовано LocaleSubscriber позднее.
*/
class UserLocaleSubscriber implements EventSubscriberInterface
{
private $session;
public function __construct(SessionInterface $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());
}
}
}
Если вы используете конфигурацию services.yml по умолчанию ,
то вы закончили! Symfony автоматически узнает о подписчике событий и передаст его в
ваше сервис session
. Теперь, когда вы будете выполняь вход, локаль пользователя
будет установлена в сессии.
Caution
Для того, чтобы обновить язык сразу же после того, как пользователь изменил
языковые предпочтения, вам также понадобится обновить сессию, когда вы будете
изменять сущность User
.