Redirect all routes without _locale to new routes including _locale in Symfony 2.8

巧了我就是萌 提交于 2021-02-11 08:42:40

问题


(Just in case you have visited my previous question: Do not be confused that the first part of the question / the introduction is the same. The question at the end is different :)

I am working on a WebApp project using Symfony 2.8. I would like to add different languages to the page. Depending on the users locale all routes/URLs should be changed from /some/url to /locale/some/url, e.g./en/some/url`.

Before adding the languages the main routing file looked like this:

<?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>

And the public_routes.xml has the following content:

<?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>

So far, so simple. Now I have added the following to the routing to add the localization:

<?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>

So the import of the public pages was extended with prefix="/{_locale}" which automatically adds the current locale to all routes from public_routes.xml.

This works fine. I can now navigate to /en, /en/price, /en/about, etc.

To be able to still navigate to an "empty" route (domain without any additional path) I added the home_redirect route with its controller:

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

So if _locale is set for the request, the homeAction checks if the language is supported or throws an error. If _locale is not set, homeAction tries to get the current _locale from the request (e.g. from the browser accepted languages).

If "/" called the user is automatically re-directed to /en, /fr or whatever the current local is.

This works fine for the homepage, but I would like to achieve the same for all "old" routes, like /about and /price

Of course I could add a about_redirect route just like I have added an home_redirect route. But to do this for all old routes would be quite cumbersome and ugly.

Is there any better, more elegant and automatic solution?

Thanks!


回答1:


You can add listener that will check if locale is set.

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


来源:https://stackoverflow.com/questions/35204512/redirect-all-routes-without-locale-to-new-routes-including-locale-in-symfony-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!