2013-05-03 3 views
5

사용자의 기본 언어 (Accept-Language 헤더 고려)를 감지하고 모든 요청을 검사하지 않도록 세션에 저장하는 LocaleListener를 구현하려고합니다. 코드가 작동Symfony2 로케일 감지 : _locale을 세션에서 고려하지 않음

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); 
    } 
} 

, 선호하는 언어가 세션에 저장되고 있지만, 심포니는 문자열을 번역하기 위해 세션에 저장되어있는 로케일을 고려하지 않는 : 나는이 작업을 수행하기 위해 아래의 코드를 개발했습니다. 필자의 경우 선호하는 언어는 'pt_BR'이었고 도망친 때 :

{{ app.request.locale }} 

symfony는 'en'을 이스케이프 처리합니다. 심포니가 요청 로케일을 정의하기 위해 세션 ('_ locale')에 저장된 값을 고려해야하지 않습니까? 이것은 올바른 행동입니까? 어떻게해야합니까?

답변

15

는 작업 언어 청취자입니다. 두 번째 방법은 언어를 사용자가 선택한 사용자 기본 설정으로 변경하는 것입니다. 사용자가 언어를 정의 할 수있는 기능이없는 경우이 방법을 생략 할 수 있습니다.

<?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" 
+0

고마워, @Pazi. 귀하의 발췌 문장에 대해 두 가지 질문이 있습니다. 1) 요청할 때마다 로케일을 설정하는 것이 좋은 아이디어입니까? 나는이 로케일을 세션에 저장하는 것을 피하려고 노력했다. 2) 세션에서 로케일을 어디에서 설정 했습니까? 귀하의 $ user-> getLanguage() 메서드는 무엇을 반환합니까? –

+0

내 프로젝트에 아무런 문제가 없습니다. 이 소스 코드를 다른 소스에서 가져 왔지만 더 이상 URL을 모르겠습니다. 세션에서'_locale' 만 사용하도록 수정할 수 있습니다. 과거에 내가 이것을 소개했을 때, 그것은 효과가 없었습니다.'$ user-> getLanguage()'는 사용자 엔티티에서 단순한 언어 필드입니다. 왜냐하면 내 사용자가 브라우저 로켈과 독립적으로 웹 응용 프로그램을 사용할 언어를 결정할 수 있기 때문입니다. –

7

심포니 2.1에서 로케일은 세션에 저장되지 않고 요청에 저장됩니다. 해결 방법 :

  • 이전 방식으로 로케일을 복원하십시오. 당신은 요청에 로케일을 저장하기 위해 upgrade file
  • 편집에 LocaleListener을이 작업을 수행하는 방법을 읽을 수 있습니다

    if (!$request->attributes->has('locale')) { 
        $request->setLocale(...); 
    } 
    
  • 여기
+0

에서 [공식 문서 (http://symfony.com/doc/2.1/book/translation.html#handling-the-user-s-locale)의 수도가 세션에서 로케일 저장하는 것을 말한다 . 자동이 아닌가요? 아니면 버그가보고되어야합니까? "요청별로 요청하는 대신 세션에 로캘을 저장할 수도 있습니다. 이렇게하면 각 후속 요청에이 로캘이 적용됩니다." –

+0

@hugomn이 점에 유의하십시오. "이렇게하면, 이후의 요청마다이 로케일이 생깁니다. **"그리고 우리는 하위 요청에 대해 말하는 것이 아닌가요? 그래서 작동하지 않습니다. –

+0

나는 그것을 얻지 않았다. 그렇다면 심포니는 이후 요청을 위해 세션에서 키 _locale을 고려하지 않는다는 뜻입니까? –

관련 문제