skip to Main Content

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 IlluminateSupportFacadesRequest::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?

2

Answers


  1. assuming you have a controller that handels changes to your locale:

    class LocaleController
    {
      public function store(Request $request)
      {
        // validate locale is a valid one
        
        $prevRoute = Route::getRoutes()->match(Request::create(URL::previous()));
        $prevRouteName = $prevRoute->getName();
        $prevRouteParams = $prevRoute->parameters();
    
        app()->setLocale($request->locale);
        $currentParams['locale'] = $request->locale;
    
        // redirect to the same route with the same parameters, except for the locale
        return redirect()->route($prevRouteName, $prevRouteParams);
      }
    }
    
    Login or Signup to reply.
  2. 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);
      }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search