簡體   English   中英

在Symfony-CMF中,一個應該如何將無語言環境的URI重定向到全語言環境的URI?

[英]How should one redirect locale-less URIs to locale-full ones in Symfony-CMF?

背景

對於多語言Symfony CMF網站,我們有一個(非常典型的安排),其中資源路徑以所需的語言環境為前綴-例如:

  • http://www.example.com/en/path/to/english-resource.html ;
  • http://www.example.com/fr/voie/à/ressource-française.html

我們正在使用RoutingAutoBundle將這些路由存儲在內容存儲庫中,並使用DynamicRouter來利用它們:簡單易行。

如果GET請求到達時沒有語言環境前綴,我們希望:

  1. 確定最適合用戶的語言環境; 接着
  2. 將用戶重定向1到相同的路徑,但添加了語言環境前綴。

當前方法

第一部分顯然是LuneticsLocaleBundle的候選router的猜測順序比我們期望的后備方法要高:同樣,簡單易行。

但是,如何最好地實施第二部分卻不太明顯。 當前,我們已將Symfony的默認/靜態路由器配置為在路由鏈中的優先級低於DynamicRouter,並在其中配置了以下控制器:

/**
 * @Route("/{path}", requirements={"path" = "^(?!(en|fr)(/.*)?$)"})
 * @Method({"GET"})
 */
public function localeNotInUriAction()
{
    $request = this->getRequest();

    $this->redirect(
        '/'
      . $request->getLocale()     // set by Lunetics
      . $request->getRequestUri()
    );
}

但這感覺很hacky,我正在尋找“更清潔”的東西。

有更好的方法嗎?

最初,我考慮過修改LuneticsLocaleBundle,以便在猜測者確定語言環境時將觸發一個事件,以為如果不是RouterLocaleGuesser那么我們可以推斷出所請求的URI不包含語言環境。 但是,顯然不是這種情況,因為RouterLocaleGuesser僅會確定是否首先存在路由的區域設置,因此我不會取得任何進展。

我現在對其他任何想法都有些困惑。 也許我畢竟已經在做正確的事情? 如果是這樣,那么我需要做的就是找到某種方法(從配置中)將允許的語言環境注入到需求正則表達式中。


  1. 外部重定向,即通過HTTP 302狀態的響應。

我們使用自定義的404處理程序和lunetics:

exception_listener:
    class: AppBundle\EventListener\ExceptionListener
    arguments:
        container: "@service_container"
    tags:
        - { name:"kernel.event_listener", event:kernel.exception, handler:onKernelException }

和php類

class ExceptionListener
{
/**
 * @var ContainerInterface
 */
protected $container;

public function __construct(ContainerInterface $container)
{
    $this->container = $container;
}

public function onKernelException(GetResponseForExceptionEvent $event)
{
    if ($this->container->getParameter('kernel.debug')) {
        // do not interfere with error handling while debugging
        return;
    }
    $exception = $event->getException();
    if ($exception instanceof NotFoundHttpException) {
        $this->handle404($event);
        return;
    }

    // ...
}

public function handle404(GetResponseForExceptionEvent $event)
{
    $request = $event->getRequest();

    if (preg_match('#^\/(de|fr|en)\/#', $request->getPathInfo())) {
        // a real 404, these are nicely handled by Twig
        return;
    }

    // i *think* that the locale is not set on the request, as lunetics comes after routing, and the routing will raise the 404
    $bestLang = $this->container->get('lunetics_locale.guesser_manager')->runLocaleGuessing($request);
    if (! $bestLang) {
        $bestLang = 'de';
    }

    $qs = $request->getQueryString();
    if (null !== $qs) {
        $qs = '?'.$qs;
    }
    $url = $request->getSchemeAndHttpHost() . $request->getBaseUrl() . '/' . $bestLang . $request->getPathInfo() . $qs;

    $this->redirect($event, $url);
}

最好還是檢查目標路徑是否確實存在-按原樣,我們將/ foobar重定向到/ de / foobar並顯示該路徑的404,這並不是那么好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM