remmel/i18n-routing-bundle
A Symfony bundle for internationalized routing, adding locale-aware route generation and matching so multilingual sites can serve localized URLs, including locale prefixes and translated route paths.
Read the composer.json first, not the README. The single most important fact about this package for a Laravel developer is that it is a Symfony bundle, not a Laravel package. There is no Remmel\I18nRoutingBundle\ServiceProvider, no package discovery entry in extra.laravel, no vendor:publish tags, and no facade. It targets Symfony's routing component and expects a kernel that compiles bundles. Before writing a line of integration code, confirm whether you are adding this to a genuine Symfony app (in which case you are in the wrong framework for the rest of this document) or trying to reuse the translated-route concept inside Laravel (in which case you are wiring a third-party component against symfony/routing yourself, not "installing a package").
Minimum viable setup (Symfony host):
composer require remmel/i18n-routing-bundle:^4.0.1 and pin exactly — the 4.0.1 changelog is a single line ("Remove deprecated usage"), so you have no evidence about what else moved.config/bundles.php (Symfony) — there is no Laravel equivalent.First use case to validate: a single contact route with an English and a French path segment (/contact vs /contactez-nous), rendered by name — the route name stays constant while the path changes with locale. If that round-trips cleanly, the rest of the bundle is variations on the same mechanic.
Where to look next: the route loader (how localized paths are declared), the config tree (locale list, default locale, whether it prefixes paths or replaces segments), and the tests directory — with 1 star and no dependents, the test suite is your only reliable specification.
Stable names, variable paths. The core contract is: one route name, N path variants. Keep route names in a constant or enum on the Laravel side and never derive them from the localized string. All URL generation goes through the name; only the path fragments live in translations. This is the pattern that actually pays off, and it pays off identically whether the host framework is Symfony or Laravel.
Locale as request state. The bundle resolves URLs for "the current or requested locale." In practice that means you need a single, canonical answer to "what locale is this request?" — set by middleware in a Laravel app (or a kernel.request listener in Symfony) from the first path segment, and injected everywhere else. Do not let a controller, a Blade view, and a queue job each infer locale independently.
Route generation at the edges. Generate localized URLs in exactly two places: HTTP controllers returning redirects, and the view layer emitting links, hreflang alternates, and canonicals. Centralize it behind one helper (route_localized($name, $params, $locale)) so that when the bundle's API changes you have one call site to fix rather than two hundred.
SEO pairing. For every localized route, emit the full alternate set (en, fr, …) plus x-default. Localized routing exists to make this cheap; if you are not emitting alternates, you are paying the complexity cost for nothing.
Laravel-side reuse (if you insist). Pull in symfony/routing directly, register the bundle's loader or replicate its path-translation logic in a small RouteCollection wrapper, and bind the result in a service provider. Treat this as writing a thin adapter, not as installing a package. Budget a day, and expect to own it.
Testing. Snapshot the generated URL for every route × every locale. Missing-translation behaviour is the failure mode you will actually hit at runtime, and a table-driven test is the cheapest way to make it loud.
The framework mismatch is the headline gotcha. Everything else here is secondary. A Symfony bundle dropped into a Laravel app does nothing by default: no autoloaded provider, no config merge, no route registration. The release is also 2019-era against a 4.x branch — check the composer.json php and symfony/* constraints before assuming it installs alongside a current Laravel/Symfony stack. composer why-not remmel/i18n-routing-bundle 4.0.1 is the fastest disqualifier.
The changelog is not a changelog. "Remove deprecated usage" is one line and does not say whether public API was removed. Read the 4.0.0→4.0.1 diff before you upgrade, and read the 3.x→4.0 upgrade notes before you adopt. If any helper, interface, or extended class you touch was deprecated, assume it is gone.
Missing translations fail late. Depending on config, a route missing a locale variant may throw only when someone requests that locale, or silently fall back to the default path — producing a French page served at an English URL, which is worse than an error. Force the failure in a test; do not discover it via a search console alert.
Parameter translation is per-parameter, not per-route. A route with both a localized segment and a dynamic {slug} will happily generate a URL with a translated path and an untranslated slug. Slugs usually need their own translation layer; the bundle will not do it for you.
Trailing slashes, encoding, and case. Localized segments that contain non-ASCII characters must be encoded consistently on generation and decoding on match, or route matching silently 404s on one locale only. Test with an accent and a space.
Cache invalidation. Symfony route caches and Laravel's route:cache both bake in the compiled collection. Any locale added at runtime, or any config change, requires a rebuild. In a Laravel adapter, remember php artisan route:cache will not know about routes registered outside the standard loader unless you register them in boot() before the cache is built.
Extension points, such as they are. If the loader does not fit your declaration format, the supported seam is a custom route loader / route collection extension, not monkey-patching the bundle. On the Laravel side your seam is the service provider — keep the adapter in one file with a documented public method or two, so replacing it with mcamara/laravel-localization later is a contained change.
Honest recommendation. For a Laravel application, evaluate mcamara/laravel-localization first. It solves the same problem natively, with maintained Laravel support and package discovery. Reach for this bundle only if you are already on Symfony or have a specific reason to reuse its route-definition format.
How can I help you explore Laravel packages today?