2017-09-03 81 views
2

我使用Symfony 3. 我的網站有2種語言,法語和英語,人們可以通過選擇表格進行切換。 默認語言是法語。 主要URL是: example.com/fr法國版本和example.com/en英語版本Symfony 3,檢測瀏覽器語言

好了,現在,我會當用戶到達該網站檢測自己的瀏覽器語言,並重定向到喜歡正確的語言自動。 爲例,如果瀏覽器是法語,他將被重定向到法語版本:example.com/fr 否則他將被重定向到英文版:example.com/en

有沒有辦法做到這一點正確?

謝謝您的幫助

+0

試試'JMSI18nRoutingBundle'。你也可以手動分析'Accept-Language'請求頭。 –

回答

3

如果你不希望依賴其他包一樣JMSI18nRoutingBundle 你已經讓自己熟悉的Symfony的事件系統,例如通過閱讀HttpKernel

爲了您的情況,您希望掛入kernel.request事件。

典型用途:詳細信息添加到請求中,初始化該系統的部分,或返回一個響應,如果可能的(例如,拒絕訪問的安全層)。

在您的自定義EventListener中,您可以偵聽該事件添加信息到您的路由器中使用的請求對象。它可能是這個樣子:

class LanguageListener implements EventSubscriberInterface 
{ 
    private $supportedLanguages; 

    public function __construct(array $supportedLanguages) 
    { 
     if (empty($supportedLanguages)) { 
      throw new \InvalidArgumentException('At least one supported language must be given.'); 
     } 

     $this->supportedLanguages = $supportedLanguages; 
    } 

    public static function getSubscribedEvents() 
    { 
     return [ 
      KernelEvents::REQUEST => ['redirectToLocalizedHomepage', 100], 
     ]; 
    } 

    public function redirectToLocalizedHomepage(GetResponseEvent $event) 
    { 
     // Do not modify sub-requests 
     if (KernelInterface::MASTER_REQUEST !== $event->getRequestType()) { 
      return; 
     } 
     // Assume all routes except the frontpage use the _locale parameter 
     if ($event->getRequest()->getPathInfo() !== '/') { 
      return; 
     } 

     $language = $this->supportedLanguages[0]; 
     if (null !== $acceptLanguage = $event->getRequest()->headers->get('Accept-Language')) { 
      $negotiator = new LanguageNegotiator(); 
      $best  = $negotiator->getBest(
       $event->getRequest()->headers->get('Accept-Language'), 
       $this->supportedLanguages 
      ); 

      if (null !== $best) { 
       $language = $best->getType(); 
      } 
     } 

     $response = new RedirectResponse('/' . $language); 
     $event->setResponse($response); 
    } 
} 

此偵聽器會檢查請求的Accept-Language頭,並使用協商\ LanguageNegotiator以確定最佳的語言環境。要小心,因爲我沒有添加使用語句,但它們應該相當明顯。

對於更高級的版本,您可以從JMSI18nRoutingBundle中讀取LocaleChoosingListener的源代碼。

這樣做通常只對首頁需要,這就是爲什麼我發佈的示例和JMSBundle的示例都排除了所有其他路徑。對於那些你可以使用專用參數_locale如文檔中描述:

https://symfony.com/doc/current/translation/locale.html#the-locale-and-the-url

symfony的文檔還包含一個例子,如何閱讀的語言環境,並使用監聽器使其在一個會話粘性:https://symfony.com/doc/current/session/locale_sticky_session.html 這個例子還展示瞭如何在你的services.yml中註冊Listener。