没有_locale的所有路由重定向到新路由,包括Symfony 2.8中的_locale

时间:2016-02-04 15:05:29

标签: php symfony localization routing

(以防万一你已经访问了我之前的问题:不要混淆问题的第一部分/介绍是一样的。最后的问题是不同的:)

我正在使用Symfony 2.8开发WebApp项目。我想在页面中添加不同的语言。根据用户区域设置,所有路由/网址都应从/some/url更改为/ locale / some / url , e.g. / en / some / url`。

在添加语言之前,主路由文件如下所示:

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <!-- Routes for the public pages -->
    <import
        resource="@AppBundle/Resources/config/routing/public_routes.xml" />

    ...
</routes>

public_routes.xml具有以下内容:

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="home" path="" methods="GET">
        <default key="_controller">AppBundle:Default:home</default>
    </route>

    <route id="public_price" path="/price" methods="GET">
        <default key="_controller">AppBundle:Default:price</default>
    </route>

    <route id="public_about" path="/about" methods="GET">
        <default key="_controller">AppBundle:Default:about</default>
    </route>

    ...
</routes>
到目前为止,这么简单。现在我已将以下内容添加到路由中以添加本地化:

<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <!-- Home route to redirect to the right route -->
    <route id="home_redirect" path="" methods="GET">
        <default key="_controller">AppBundle:Default:home</default>
    </route>

    <!-- Routes for the localized public pages -->
    <import
        resource="@AppBundle/Resources/config/routing/public_routes.xml"
        prefix="/{_locale}" >

        <requirement key="_locale">en|fr|es</requirement>
        <default key="_locale">en</default>        
     </import>

    ...
</routes>

因此,prefix="/{_locale}"扩展了公共页面的导入,自动将当前区域设置添加到public_routes.xml的所有路由中。

这很好用。我现在可以导航到/en/en/price/en/about

为了能够仍然导航到“空”路由(没有任何其他路径的域)我添加了home_redirect路由及其控制器:

public function homeAction(Request $request) {
    $locale = $request->attributes->get('_locale');
    if (!$locale) {
        // Try to get the preferred language from the request
        $locale = MySettings::getLanguage($request);               
        return $this->redirectToRoute('home', array('_locale' => $locale));
    } elseif (!MySettings::checkLanguage($locale)) {
        // Invalid Locale...
        throw $this->createNotFoundException();
    }

    return $this->render('AppBundle:Default:homepage.html.twig');
}

因此,如果为请求设置了_locale,则homeAction会检查语言是否受支持或引发错误。如果未设置_locale,则homeAction会尝试从请求中获取当前_locale(例如,从浏览器接受的语言)。

如果调用“/”,则会自动将用户重定向到/en/fr或当前本地的任何内容。

这适用于首页,但我希望所有“旧”路线都能实现相同功能,例如/about/price

当然,我可以像添加about_redirect路线一样添加home_redirect路线。但要为所有旧路线做这件事会非常麻烦和丑陋。

有更好,更优雅和自动的解决方案吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

您可以添加将检查是否设置了区域设置的侦听器。

$kernel->getContainer()->get('event_dispatcher')->addListener(\Symfony\Component\HttpKernel\KernelEvents::REQUEST, function($event) {
    if ($event->getRequestType() != \Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST) return;

    $request = $event->getRequest();
    $locale = $request->attributes->get('_locale');
    if (!$locale) {
        // Try to get the preferred language from the request
        $locale = MySettings::getLanguage($request);
        return new \Symfony\Component\HttpFoundation\RedirectResponse('/' . $locale . '/' . ltrim($request->getRequestUri(), '/'));
    } elseif (!MySettings::checkLanguage($locale)) {
        // Invalid Locale...
        throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException();
    }
});

....

$response = $kernel->handle($request);