Symfony2的现场检测:不考虑在会议_locale(Symfony2 locale detect

2019-09-01 19:47发布

我试图实现检测用户的首选语言LocaleListener(考虑Accept-Language头),并将其存储在会议上,以避免检查它的每一个请求。 我已经开发了下面的代码来实现:

public function onKernelRequest(GetResponseEvent $event) {
    $request = $event->getRequest();

    if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
        return;
    }

    $preferredLocale = $request->getPreferredLanguage($this->availableLocales);

    if ($this->container->has('session')) {
        $session = $this->container->get('session');
        if (!$session->has('_locale')) {
            $session->set('_locale', $preferredLocale);
        }
    } else {
        $request->setLocale($preferredLocale);
    }
}

该代码工作,首选语言被存储在会话,但symfony中没有考虑存储在会话翻译字符串的区域。 就我而言,我的首选语言是“pt_BR表示”当我逃离:

{{ app.request.locale }}

symfony中被转义成 'en'。 不应该被symfony的考虑存储在会话(“_区域”)来定义请求区域的价值? 这是一个正确的行为吗? 我怎样才能做到呢?

Answer 1:

这是一个工作语言监听器。 第二种方法是将语言切换到用户偏好,其中所述用户选择。 您可以忽略此方法,如果您的用户还没有设施,以确定他们的语言。

<?php

namespace Acme\UserBundle\EventListener;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class LanguageListener
{
    private $session;

    public function setSession(Session $session)
    {
        $this->session = $session;
    }

    /**
     * kernel.request event. If a guest user doesn't have an opened session, locale is equal to
     * "undefined" as configured by default in parameters.ini. If so, set as a locale the user's
     * preferred language.
     *
     * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
     */
    public function setLocaleForUnauthenticatedUser(GetResponseEvent $event)
    {
        if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
            return;
        }
        $request = $event->getRequest();
        if ('undefined' == $request->getLocale()) {
            if ($locale = $request->getSession()->get('_locale')) {
                $request->setLocale($locale);
            } else {
                $request->setLocale($request->getPreferredLanguage());
            }
        }
    }

    /**
     * security.interactive_login event. If a user chose a language in preferences, it would be set,
     * if not, a locale that was set by setLocaleForUnauthenticatedUser remains.
     *
     * @param \Symfony\Component\Security\Http\Event\InteractiveLoginEvent $event
     */
    public function setLocaleForAuthenticatedUser(InteractiveLoginEvent $event)
    {
        $user = $event->getAuthenticationToken()->getUser();

        if ($lang = $user->getLanguage()) {
            $this->session->set('_locale', $lang);
        }
    }
}

在您的services.yml:

services:
    acme.language.interactive_login_listener:
        class: Acme\UserBundle\EventListener\LanguageListener
        calls:
            - [ setSession, [@session] ]
        tags:
            - { name: kernel.event_listener, event: security.interactive_login, method: setLocaleForAuthenticatedUser }

    acme.language.kernel_request_listener:
        class: Acme\UserBundle\EventListener\LanguageListener
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: setLocaleForUnauthenticatedUser }

哦,你有config.yml定义一个未定义的fallback_language得到它的工作。

framework:
    translator:      { fallback: "undefined" }
    default_locale:  "en"


Answer 2:

因为symfony 2.1,该语言环境未存储在会话,但请求。 你能做些什么来解决这个问题:

  • 恢复保存区域的老办法。 你可以阅读如何在做这个升级文件
  • 编辑LocaleListener于区域设置存储在请求:

     if (!$request->attributes->has('locale')) { $request->setLocale(...); } 


文章来源: Symfony2 locale detection: not considering _locale in session