Як зробити локаль "липкою" під час сесії користувача
Дата оновлення перекладу 2023-06-22
Як зробити локаль "липкою" під час сесії користувача
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/EventSubscriber/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(string $defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(RequestEvent $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 [
// повинен бути зареєстрований після слухача локалі за замовчуванням
KernelEvents::REQUEST => array(array('onKernelRequest', 15)),
];
}
}
Якщо ви використвуєте конфігурацію services.yml за замовчуванням ,
то ви закнічили! Symfony автоматично дізнається про підписаника подій та викличе
метод onKernelRequest
для кожного запиту.
Щоб побачити, як це працює, або встановіть ключ _locale
у сесії вручну (наприклад,
через маршрут і контролер "Змінити локаль"), або створіть маршрут з
локаллю за замовчуванням .
Ось і все! Тепер відсвяткуйте, змінивши локаль користувача та побачивши, що вона "прилипає" у всьому запиті.
Памʼятайте, щоб отримати локаль користувача, завжди використовуйте метод Request::getLocale:
1 2 3 4 5 6 7
// з контролера...
use Symfony\Component\HttpFoundation\Request;
public function index(Request $request)
{
$locale = $request->getLocale();
}
Установка локалі, засновуючись на побажаннях користувача
Ви можете захотіти покращити цю техніку та визначити локаль, засновуючись на сутності
користувача, який виконав вхід. Однак, так як LocaleSubscriber
викликається перед
FirewallListener
, який відповідає за управління аутентифікацією та установку мітки
користувача у TokenStorage
, у вас немає доступу до користувача, який виконав вхід.
Уявіть, що у вас є властивість locale
у вашій сутності User
і ви хочете
використати це в якості локалі даного користувача. Щоб зробити це, ви можете
підключитися до процесу виконання входу та оновити сесію користувача з цим значенням
локалі до того, як він буде перенаправлений на свою першу стоінку.
Щоб зробити це, вам знадобиться підписник подій у події security.interactive_login
:
// src/EventSubscriber/UserLocaleSubscriber.php namespace AppEventSubscriber;
use SymfonyComponentEventDispatcherEventSubscriberInterface; use SymfonyComponentHttpFoundationRequestStack; use SymfonyComponentSecurityHttpEventInteractiveLoginEvent; use SymfonyComponentSecurityHttpSecurityEvents;
- /**
- Зберігає локаль користувача у сесії після виконання входу.
- Це може бути використано LocaleSubscriber пізніше.
*/
class UserLocaleSubscriber implements EventSubscriberInterface { private $requestStack;
public function __construct(RequestStack $requestStack) { $this->requestStack = $requestStack; }
public function onInteractiveLogin(InteractiveLoginEvent $event) { $user = $event->getAuthenticationToken()->getUser();
- if (null !== $user->getLocale()) {
- $this->requestStack->getSession()->set('_locale', $user->getLocale());
}
}
public static function getSubscribedEvents() { return [ SecurityEvents::INTERACTIVE_LOGIN => 'onInteractiveLogin', ]; }
}
Caution
Для того, щоб оновити мову одразу ж після того, як користувач змінив мовні
побажання, вам також знадобиться оновити сесію, коли ви будете змінювати
сутність User
.