I have a multilanguage site: en, hu, ro atm. The base URL is example.com/{locale}
e.g. example.com/en
. The language detection is just checking the locale
parameter of the route. I want it to stay this way.
I have a language selector where all locales can be selected and for every page I have link rel alternate for the crawlers to avoid duplicate content problems. So when I visit example.com/en/products/1
the language selector in the layout should have example.com/hu/products/1
and example.com/ro/products/1
as well. I think I should make these URIs in the language middleware and send it to the layout with View::share
.
I could build these URIs using the current URI and a simple preg replace or str replace on the first segment, but I guess there is a better way in Laravel. I found that \Illuminate\Support\Facades\Request::segment(1)
is good for getting the first segment and the route pattern is usually /{locale}/sthg/{sthg}
appended with query string, but I cannot find a Laravel solution for replacing the first segment. Is there such a thing?
if you want to build all language options, and pass them to your views, you can use a view composer:
class LocalesComposer
{
// inject current request into the ViewComposer
public function __construct(protected Request $request)
{}
public function compose(View $view)
{
// filter valid locales, assuming config('app.locales') is an array of all supported locales in this application
$locales = collect(config('app.locales'))
->reject(fn ($locale) => $locale == app()->getLocale());
$routeName = $this->request->route()->getName();
$routeParams = $this->request->route()->parameters();
$languageSelectOptions = $locales->map(function (string $locale) use ($routeName, $routeParams) {
$routeParams['locale'] = $locale;
return route($routeName, $routeParams); // return a url for this route
);
// pass URLs array to the view
$view->with('languageSelectOptions', $languageSelectOptions);
}