New in Symfony 4.1: Internationalized routing

Contributed by
Frank de Jonge
in #26143.

We recently improved the performance of the Routing component to make it the fastest PHP router available. Now, just in time for including it in Symfony 4.1, we added another amazing feature to it: support for internationalized routes.

This feature allows to define different paths for each route depending on the user locale. This feature is essential for internationalized apps and that's why third-party bundles like JMSI18nRoutingBundle have millions on downloads. In Symfony 4.1 we decided to integrate this into the routing component itself so you can use it out-of-the-box in Symfony apps.

In practice, when defining a route you can now provide an array in the path option to define a different path per locale:

1
2
3
4
5
contact:
    controller: App\Controller\ContactController::send
    path:
        en: /send-us-an-email
        nl: /stuur-ons-een-email

This format is also supported for routes defined in XML and PHP annotations:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
use Symfony\Component\Routing\Annotation\Route;

class ContactController
{
    /**
     * @Route({
     *     "en": "/send-us-an-email",
     *     "nl": "/stuur-ons-een-email"
     * }, name="contact")
     */
    public function send()
    {
        // ...
    }
}

Internally Symfony creates one route per locale (called contact.en and contact.nl in this example) but you can still use the original route name to generate URLs. When generating a URL, the request locale is used by default, but you can pass the locale explicitly to generate any of the alternative URLs:

1
2
3
4
5
6
7
8
/** @var UrlGeneratorInterface $urlGenerator */
// uses the current request locale
$url = $urlGenerator->generate('contact');

// ignores the current request locale and generates '/stuur-ons-een-email'
$url = $urlGenerator->generate('contact', ['_locale' => 'nl']);
// this would also work, but it's not recommended:
// $url = $urlGenerator->generate('contact.nl');

The route prefix can also be translated (both in YAML/XML files and @Route annotations defined at controller class level) and you can mix translated and not translated paths too:

1
2
3
4
5
6
7
# config/routes/annotations.yaml
site:
    resource: '../src/Controller/'
    type: annotation
    prefix:
        en: '/site'
        es: '/sitio'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class DefaultController extends Controller
{
    /**
     * @Route({"en": "/contact", "es": "/contacto"}, name="contact")
     */
    public function contact()
    {
        // ...
    }

    /**
     * @Route("/page/{slug}", name="page")
     */
    public function page($slug)
    {
        // ...
    }
}

The four resulting routes generated by Symfony will be:

Route name Route path
contact.en /site/contact
contact.es /sitio/contacto
page.en /site/page/{slug}
page.es /sitio/page/{slug}

Comments

That's great thank you !
Great improvement, Thank you!
Nice! Thanks you. This is really great. Waited for this for a long time!
On of the best new features. Thx guys!
Great feature !
Very nice! Thanks for this feature!
Wow! Very hot feature! Thank you! :-)
Amazing! I look forward to version 4.1
This is really amazing! :)
very cool! is it possible to use translation files for the route names?
is it possible to use translator component to manage the routes ? we did it 2 years ago on a project, but we had to write our own custom router.
In the last example the class itself misses the route annotation:

```
@Route({"en": "/site", "es": "/sitio"})
```
@12: oops, I've missed the mixed config part, sorry
Great feature..! Can we use in Hindi..??
😍
Thumbs up!
This is indeed great feature:)
Very useful ! no need for extra bundle to internationalize our apps. Thanks a lot !
Nice. Very good.
This will really help internationalized project !
very very cool!
Login with SensioLabsConnect to post a comment