Installation
composer require alvadi-it/i18n-routing-bundle
Add to config/bundles.php:
return [
// ...
Alvadi\I18nRoutingBundle\AlvadiI18nRoutingBundle::class => ['all' => true],
];
Configure Supported Locales
In config/packages/alvadi_i18n_routing.yaml:
alvadi_i18n_routing:
locales: ['en', 'fr', 'de']
default_locale: 'en'
prefix_locale: true # e.g., `/en/about`
First Route Definition
In config/routes.yaml:
app_home:
path: /{_locale}/about
controller: App\Controller\HomeController::about
requirements:
_locale: en|fr|de
Generate URLs with Locale
$url = $this->generateUrl('app_home', ['_locale' => 'fr']);
// Outputs: /fr/about
Detect Current Locale
$locale = $this->get('router')->getContext()->getParameter('_locale');
prefix_locale: true to enforce /{locale}/ structure._locale in route requirements for flexibility:
app_blog_post:
path: /blog/{slug}
controller: App\Controller\BlogController::show
requirements:
_locale: en|fr
slug: '.*'
fr.example.com → fr)/fr/about)// src/Kernel.php
protected function build(RequestContext $context): void
{
$locale = $this->detectLocale(); // Custom logic
$context->setParameter('_locale', $locale);
}
app_home_fr:
path: /accueil
controller: App\Controller\HomeController::about
defaults: { _locale: 'fr' }
requirements:
_locale: fr
// src/Components/LocaleSwitcher.php
use Alvadi\I18nRoutingBundle\Routing\RouterInterface;
public function __construct(private RouterInterface $router) {}
public function render(): string {
$locales = ['en', 'fr', 'de'];
$current = $this->router->getContext()->getParameter('_locale');
return $this->renderView('locale_switcher.html.twig', [
'locales' => $locales,
'current' => $current,
]);
}
RequestContext to read Accept-Language:
# config/packages/alvadi_i18n_routing.yaml
alvadi_i18n_routing:
locale_from_header: true
RequestContext post-login:
// src/EventListener/LoginListener.php
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event) {
$user = $event->getAuthenticationToken()->getUser();
$context = $this->router->getContext();
$context->setParameter('_locale', $user->getPreferredLocale());
}
alvadi_i18n_routing:
locale_from_header: true
prefix_locale: false
Route:
api_posts:
path: /posts/{id}
methods: [GET]
requirements:
_locale: en|fr
locale field in entities and filter queries:
// src/Repository/PostRepository.php
public function findByLocale(string $locale): array {
return $this->createQueryBuilder('p')
->where('p.locale = :locale')
->setParameter('locale', $locale)
->getQuery()
->getResult();
}
_locale clashes with route parameters (e.g., /en/{id} where id is en).prefix_locale: true or rename the parameter (e.g., _lang).locales config:
php bin/console cache:clear
default_locale, but the URL may break.RouteListener to rewrite URLs:
// src/EventListener/LocaleFallbackListener.php
public function onKernelRequest(GetResponseEvent $event) {
$request = $event->getRequest();
if (!$request->hasPreviousSession() && $request->get('_locale') !== $this->defaultLocale) {
$request->attributes->set('_locale', $this->defaultLocale);
$request->query->set('_locale', $this->defaultLocale);
}
}
/FR/ ≠ /fr/).$locale = strtolower($request->get('_locale'));
_locale in nested routes or use _locale in all route requirements.dump($this->get('router')->getContext()->getParameters());
Outputs:
array:_locale => 'fr', _route => 'app_home', ...
Validate locale requirements in routes:
app_test:
path: /{_locale}/test
requirements:
_locale: 'en|fr|de' # Explicitly list allowed locales
Add a listener to log locale sources:
// src/EventListener/LocaleDebugListener.php
public function onKernelRequest(GetResponseEvent $event) {
$request = $event->getRequest();
$this->logger->info('Locale detected from:', [
'path' => $request->get('_locale'),
'header' => $request->headers->get('Accept-Language'),
'session' => $request->getSession()->get('_locale'),
]);
}
Implement Alvadi\I18nRoutingBundle\Locale\LocaleProviderInterface:
class CustomLocaleProvider implements LocaleProviderInterface {
public function getLocale(Request $request): string {
// Custom logic (e.g., geoIP, user agent)
return 'en';
}
}
Register in config:
alvadi_i18n_routing:
locale_provider: App\Service\CustomLocaleProvider
Use a compiler pass to generate locale-specific routes at runtime:
// src/DependencyInjection/Compiler/LocaleRoutePass.php
public function process(ContainerBuilder $container) {
$definition = $container->findDefinition('router');
$definition->addMethodCall('addLocaleRoutes', [
$container->getParameter('alvadi_i18n_routing.locales'),
]);
}
Extend the bundle’s UrlGenerator to handle redirects:
// src/Service/LocaleAwareUrlGenerator.php
public function generate(string $route, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string {
if (!isset($parameters['_locale'])) {
$parameters['
How can I help you explore Laravel packages today?