Skip to content

Twig path function fails for internationalized routes #30010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JeroenDeDauw opened this issue Jan 29, 2019 · 11 comments
Closed

Twig path function fails for internationalized routes #30010

JeroenDeDauw opened this issue Jan 29, 2019 · 11 comments

Comments

@JeroenDeDauw
Copy link
Contributor

JeroenDeDauw commented Jan 29, 2019

Symfony version(s) affected: 4.2.2

Description
The Twig path function fails for internationalized routes when rendering a template on NotFoundHttpException.

How to reproduce

1/3: Have an internationalized route (routes.yaml):

mypage:
    path:
        en: /en/english
        de: /de/german
    controller: App\Controller\SimplePageController::page

2/3: Have an EventListener that renders a 404 template:

class ExceptionListener {

	private $twig;

	public function __construct( \Twig_Environment $twig ) {
		$this->twig = $twig;
	}

	public function onKernelException( GetResponseForExceptionEvent $event ) {
		if ( $event->getException() instanceof NotFoundHttpException ) {
			$response = new Response(
				$this->twig->render( 'errors/404.html.twig' ),
				404
			);

			$event->setResponse( $response );
		}
	}
}

3/3: Call the path function with the name of the internationalized route in the template:

{{ path('mypage') }}

The path function works fine for routes that do not use the i18n feature like this one:

index:
    path: /
    controller: App\Controller\IndexController::index

I did some digging though the Symfony code though did not find the issue. Might be related to #27872

@stof
Copy link
Member

stof commented Jan 29, 2019

What do you mean exactly by it fails ? What is happening ?

@JeroenDeDauw
Copy link
Contributor Author

JeroenDeDauw commented Jan 30, 2019

image

Stack trace: https://pastebin.com/hbvFgUiu

@JeroenDeDauw
Copy link
Contributor Author

JeroenDeDauw commented Jan 30, 2019

To be 100% clear: this template renders fine when it is rendered from a controller. The error just occurs when I do the rendering from the EventListener that reacts to 404.

Presumably some initialization has not happened yet at that point, or maybe I am accessing the wrong twig instance or something like that. As mentioned, I looked though the Symfony source a bunch though it's hard to follow things due to magical dependency injection which I am not used to.

@xabbuh
Copy link
Member

xabbuh commented Jan 30, 2019

I guess the problem is that the exception occurs before the LocaleListener is executed. This means that the URL generator is not able to find a route as there is no locale set yet.

@fancyweb
Copy link
Contributor

Status: Reviewed

Exactly xabbuh. Just reproduced it successfully.

RouterListener is executed before LocaleListener so there is no locale in the RequestContext in the generator.

However, there is a little fix we can do. We currently don't pass a default locale to the generator. We should pass the kernel.default_locale param I guess as an ultimate fallback. But still, every generated link will be for the "en" locale for example.

@xabbuh
Copy link
Member

xabbuh commented Jan 30, 2019

If you rely on the locale being extracted from the route configuration, I think we cannot do better as there is no matching route that could be used to extract the locale. When using something more sophisticated with custom code (e.g. storing the locale in the session), you could of course make sure that your own listener is executed before.

@fancyweb
Copy link
Contributor

fancyweb commented Jan 30, 2019

I thought about my proposition a bit more and actually it would lead to BC breaks if there is another non internationalized route with the same name. Exemple : "myroute" and "myroute.en"

@JeroenDeDauw
Copy link
Contributor Author

JeroenDeDauw commented Jan 31, 2019

I got around the linking via path() issue by injecting the UrlGenerator into my EventListener and setting the locale parameter in its RequestContext.

$this->urlGenerator->getContext()->setParameter(
    '_locale',
    $locale
);

While that solves the linking issue, the template is rendered with the default locale, rather than the one I am computing from the url in my EventListener.

I've switched to using some catch-all routes for 404 rather than using an EventListener. This approach is much simpler and works nicely with the new Symfony internationalized routing (unlike the JMS bundle where I did not get it to work for the life of me). So this bug is no longer getting in my way. Still, it seems like the route function / UrlGenerator should at least fall back to the default locale and not error out.

@xabbuh
Copy link
Member

xabbuh commented Apr 23, 2019

Does #31023 help?

@JeroenDeDauw
Copy link
Contributor Author

I ran composer update and am now rendering a 500 page from the EventListener without any problems, so I guess this is fixed.

@xabbuh xabbuh closed this as completed Apr 26, 2019
@kyeno
Copy link

kyeno commented Aug 7, 2020

Your problem might be having yet another locale set. I've encourted similar issue here:
https://stackoverflow.com/questions/63286922/symfony-4-multilang-routes-with-default-fallback

Trying to workaround this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants