Symfony2 неправильное определение локали? - PullRequest
11 голосов
/ 05 октября 2011

Следуя руководству Symfony2 о переводе я обнаружил, что выведенный язык из заголовков http (хранится в $this->get('session')->getLocale()) неверен (отправлено it , выведено en ) :

Хост localhost User-Agent Mozilla / 5.0 (Windows NT 6.1; WOW64; версия: 7.0.1) Gecko / 20100101 Firefox / 7.0.1 Принять текст / html, application / xhtml + xml, application / xml; q = 0,9, / ; q = 0,8 Accept-Language it-it, it; q = 0,8, en-us; q = 0,5, en; q = 0,3

Это нормальное поведение? Или я должен установить что-то, чтобы локализация работала из коробки?

Ответы [ 4 ]

7 голосов
/ 08 ноября 2011

Сегодня я более тщательно изучил код, потому что у меня возникла та же проблема, что и у вас, и похоже, что язык происходит от Session::getLocale(). Но Symfony2 никогда не вызывает Session::setLocale() и устанавливает член locale объекта Session. Поиск в Google "symfony2 session setlocale" приводит к этому § документации

Итак, я поставил эту строку поверх контроллера, над которым работал, и это сработало:

$this->getRequest()->getSession()->setLocale(
    $this->getRequest()->getPreferredLanguage());

Теперь я думаю, что это неприемлемо, потому что вы не собираетесь добавлять это поверх каждого контроллера. Кроме того, это следует делать не для каждого запроса, а только для первого, когда у пользователя еще нет сеанса. Если кто-нибудь знает, как это сделать, не стесняйтесь редактировать этот ответ.

4 голосов
/ 01 июня 2012

на HTTP-стандарт. Вы должны использовать разные URL для каждой переведенной версии страницы. Остается простое действие, которое выведет из запроса лучший языковой стандарт и перенаправит на соответствующую страницу:

/**
 * @Route("/")
 */
public function localeRedirectAction() {
    /* @var $request \Symfony\Component\HttpFoundation\Request */
    /* @var $session \Symfony\Component\HttpFoundation\Session */
    $req = $this->getRequest();
    $session = $this->get('session');

    $session->setLocale($req->getPreferredLanguage(array('de', 'en')));

    return $this->redirect($this->generateUrl('home'));
}

Если вам нужно сделать это для любой страницы, вам, в основном, нужно сделать то же самое, но в Слушателе для kernel.request -События. Чтобы быть надежно вызванным после того, как route-matcher сделал его работу, вы должны установить priority слушателя на значение <0: </p>

# services.yml
services:
  my_locale_listener:
    class: Namespace\LocaleListener
    tags: [{ name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: -255 }]
    arguments: [ @service_container, [ 'en', 'fr', 'de', 'es', 'it' ] ]

тогда слушатель будет выглядеть так:

class LocaleListener {
    public function __construct($container, $availableLocales) {
        $this->container = $container;
        $this->availableLocales = $availableLocales;
    }

    public function onKernelRequest(GetResponseEvent $e) {
        $req = $e->getRequest();
        $locale = $req->getPreferredLanguage($this->availableLocales);

        // generate a new URL from the current route-name and -params, overwriting
        // the current locale
        $routeName = $req->attributes->get('_route');
        $routeParams = array_merge($req->attributes->all(), array('_locale' => $locale));
        $localizedUrl = $this->container->get('router')->generateUrl($routeName, $routeParams);

        $e->setResponse(new RedirectResponse($localizedUrl));
    }
}

P.S. я не совсем уверен, что этот код действительно работает, но он должен дать общее представление о том, как это можно сделать.

1 голос
/ 12 декабря 2011

Вы можете зарегистрировать слушателя следующим образом:

use Symfony\Component\DependencyInjection\ContainerInterface;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

class LocaleListener
{
    private $container;
    private $defaultLocale;

    public function __construct(ContainerInterface $container, $defaultLocale = 'nl')
    {
        $this->container = $container;
        $this->defaultLocale = $defaultLocale;
    }

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

        if (!$this->container->has('session')) {
            return;
        }

        $session = $this->container->get('session');
        $session->setLocale($this->defaultLocale);
    }
}

( суть )

Сразу после этапа настройки сеанса фреймворка:

<service id="my.event_listener.locale_listener" class="MyBundle\MyEventListener\LocaleListener">
    <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="100" />
    <argument type="service" id="service_container" />
</service>

( 1012 * суть *)

0 голосов
/ 27 августа 2012

Я написал LocaleListener, который не перенаправляет вас на специфичный для локали URL, однако он устанавливает для вас настройки локали;)

Код в services.yml

services:
    acme.demobundle.listener.request:
        class: Namespace\LocaleListener
        tags: [{ name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: -255 }]
        arguments: [ @service_container, [ 'en', 'fr', 'de', 'it', 'es' ] ]

и фактический слушатель:

class LocaleListener
{
    protected $container;
    protected $availableLocales;

    public function __construct(\Symfony\Component\DependencyInjection\Container $container, $availableLocales) {
        $this->container = $container;
        $this->availableLocales = $availableLocales;
    }

    public function onKernelRequest(GetResponseEvent $e) {
        $req = $e->getRequest();
        $locale = $req->getPreferredLanguage($this->availableLocales);
        $session = $this->container->get('session');
        $session->setLocale($locale);
    }
}
...