首页 > 解决方案 > 使用自定义侦听器设置的区域设置被覆盖

问题描述

我的意图是根据 Accept-Language HTTP 请求标头设置语言环境。

我已经创建了自定义 LocaleListener 类,并在 config/services.yaml 中将其配置为优先级高于 LocaleListener,如下所示:https ://symfony.com/doc/current/translation/locale.html

onKernelRequest()方法中包含的逻辑成功地检索了我传递给该setLocale()方法的语言环境。

在同一文件中回显当前语言环境会返回预期的语言环境(由用户浏览器定义的语言环境)。但是,最终,此语言环境被覆盖,更改为应用程序默认值。

这就是问题所在。我需要确定覆盖区域设置的内容以及可能的解决方案。Symfony 文档并没有那么深入。我打算用我发现的内容为文档做出贡献。

这是一个运行在 GNU/Linux 上的 Symfony 4 应用程序。

我收集了以下输出php bin/console debug:event kernel.request

Registered Listeners for "kernel.request" Event
===============================================

 ------- ------------------------------------------------------------------------------------------------- ---------- 
  Order   Callable                                                                                          Priority  
 ------- ------------------------------------------------------------------------------------------------- ---------- 
  #1      Symfony\Component\HttpKernel\EventListener\DebugHandlersListener::configure()                     2048      
  #2      Symfony\Component\HttpKernel\EventListener\ValidateRequestListener::onKernelRequest()             256       
  #3      Symfony\Component\HttpKernel\EventListener\SessionListener::onKernelRequest()                     128       
  #4      App\EventListener\LocaleListener::onKernelRequest()                                               110       
  #5      Symfony\Component\HttpKernel\EventListener\LocaleListener::setDefaultLocale()                     100       
  #6      Symfony\Component\HttpKernel\EventListener\RouterListener::onKernelRequest()                      32        
  #7      Symfony\Bundle\FrameworkBundle\EventListener\ResolveControllerNameSubscriber::onKernelRequest()   24        
  #8      Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelRequest()                      16        
  #9      Symfony\Component\HttpKernel\EventListener\LocaleAwareListener::onKernelRequest()                 15        
  #10     Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener::configureLogoutUrlGenerator()      8         
  #11     Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener::onKernelRequest()                  8         
 ------- ------------------------------------------------------------------------------------------------- ----------

如您所见,在所有其他与语言环境相关的侦听器之上,有我的自定义侦听器。

我试图设置它的优先级,所以它在 setDefaultLocale() 之后执行,但最终语言环境仍然是默认值,'en'。

这是来自 src/EventListener/ 的自定义监听器代码:

<?php

namespace App\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;

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

        // LOGIC TO RETRIEVE LOCALE

        $request->setLocale($locale);
    }
}

观察 01:$locale 变量在回显时返回预期的字符串。

观察 02:在上述方法中回显 $request->getLocale() 返回预期的字符串,这意味着此时区域设置已成功更改。

以下是 config/services.yaml 底部的监听器配置

    App\EventListener\LocaleListener:
        tags:
            - { name: kernel.event_listener, event: kernel.request, priority: 110 }

预计语言环境将根据浏览器上定义的语言进行更改 - 第一个是“pt”葡萄牙语;但是,语言环境继续设置为默认值“en”。

标签: symfonylocalization

解决方案


是路由器。

路由器配置为在所有路由上使用前缀,这决定了语言环境,例如 /pt 或 /en。我只需要禁用它们,然后应用程序将根据我的浏览器语言环境成功确定语言环境。

现在我只需要弄清楚如何保持区域设置前缀可用,同时仍然主要使用 Accept-Language 信息。然后前缀将充当此自动定义的语言环境的覆盖。这就是许多流行网站的工作方式,尽管通过单个 URL 提供不同内容并不是最佳实践。


推荐阅读