Asked 1 month ago by MercurialOrbiter996
How can I dynamically generate translated routes in Laravel with a single routes file?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by MercurialOrbiter996
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I want my Laravel application to support multiple languages while maintaining only one web-routes file. In each language folder, I have a routes.php
that maps keys to translated paths, for example:
PHP['createAccount' => 'create-account'] // en
and
PHP['createAccount' => 'account-anlegen'] // de
I’m detecting the locale in a middleware using code like this:
PHP$middleware->web( prepend: SetLocale::class, // simply calls App::setLocale('whatever'); append: HandleInertiaRequests::class );
In my HandleInertiaRequests
, I adjust URLs, labels, and texts before passing them to the views so that links and display texts match the client’s language. This part works correctly.
Currently, my route definition in web.php
looks like this (spoiler: it doesn't work):
PHPRoute::get('{path}', [RegistrationController::class, 'route']) ->where('path', __('routes.createAccount')) ->name('createAccount');
I’m trying to dynamically replace the route path based on the client’s language. However, since the SetLocale
middleware runs after the routes are compiled, the translation function __()
doesn’t reflect the client’s locale. I could create separate web-routes files per language, but I’m seeking a more dynamic solution.
Is there a way to achieve this dynamically?
Comments 0
•Answers 2
•Views 43
Answer by TychoAI Agent • 1 month ago
When your routes file is compiled, the calls to translation functions (like __()) are evaluated immediately, before any middleware (like your SetLocale) has a chance to run. This means that the language context you want isn’t available yet, and the routes won’t “dynamically” change based on the client's locale.
Here are a couple of approaches to work around this:
You can iterate over your supported locales and register the translated routes explicitly. For example:
PHP$supportedLocales = ['en', 'de']; foreach ($supportedLocales as $locale) { // Optionally use a route group with a locale prefix Route::group(['prefix' => $locale], function () use ($locale) { // Here you force the locale for translation calls by passing it to __() Route::get( __( 'routes.createAccount', [], $locale ), [RegistrationController::class, 'route'] )->name('createAccount.' . $locale); }); }
This way, you have a separate route (or route group) for each locale, and translation strings are evaluated in the correct context.
Another common solution is to include the locale in the URL itself (e.g., /en/create-account
or /de/account-anlegen
). This lets you capture the language from the URL and then set the locale in your middleware accordingly. An example:
PHPRoute::group(['prefix' => '{locale}', 'middleware' => 'setLocale'], function () { Route::get( __( 'routes.createAccount' ), [RegistrationController::class, 'route'] )->name('createAccount'); });
Inside your middleware (e.g., setLocale), you can then grab the {locale}
parameter to set the application locale:
PHPpublic function handle($request, Closure $next) { if ($locale = $request->route('locale')) { App::setLocale($locale); } return $next($request); }
You cannot have a single route definition dynamically change its path based on middleware because the routes are resolved at compile time. Instead, either register the routes for each locale or use a URL prefix to capture the locale before the routes are matched. Both solutions are commonly used in multi-language Laravel applications.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by SolarSeeker140 • 1 month ago
There are different approaches. I cant tell from your example if you save the language in the session or if you use url detection. For the latter I can recommend the following way that I use in many projects.
In a dedicated config file, like config/localisation.php, you can define the languages or locales you want to be available in your application. For the sake of an example, something like this:
PHP<?php return [ 'languages' => [ 'en' => [ 'name' => 'English', 'native_name' => 'English', 'transliterate_urls' => false, 'translate_urls' => null, ], 'de' => [ 'name' => 'German', 'native_name' => 'Deutsch', 'transliterate_urls' => false, 'translate_urls' => true, ], ], ];
Use a middleware to detect and set the language.
Now, when defining routes, you could do something like this:
PHP<?php foreach (config('localisation.languages') as $langcode => $languageSettings) { Route::get( Str::of( __( 'Create account', [], $langcode // translate to this language to register the translated url ) )->slug('-'), function () { return view('register'); } )->name($langcode . '.Register'); }
An advantage is, that it automatically creates translated urls (if wanted) and you can specifically generate a link to a translated url because the route name is always the current language code plus '.Register'
.
So, you could make the current language code available in all views via view composer and generate links like so:
PHP<a href="{{ route($currentLangcode . '.Register') }}">{{ __('Create Account') }}</a>
And you can automatically check if translated routes exist by replacing the $currentLangcode
with any other defined in your config file, list all translations for a given route name, etc.
This approach generates the routes for all languages though. If you just want to generate the translated urls for the users language, you would have to change it by simply not iterating over all languages but get the current language either from a custom service provider or some other way.
No comments yet.
No comments yet.