feyen01
feyen01

Reputation: 417

How to generate current url with different locales in Laravel 8?

I want to generate current url with different locales as hreflang tags on every page and for each language. For example, for example.com/es/category/general I would like to generate this hreflangs in my <head> section:

<link rel="alternate" hreflang="en" href="example.com/category/general" />
<link rel="alternate" hreflang="es" href="example.com/es/category/general" />
<link rel="alternate" hreflang="de" href="example.com/de/category/general" />

Currently, I set locale via prefix. Notice that for default en locale I don't use the prefix:

Route::prefix(parseLocale())->group(function () {
... // all routes go here
}

function parseLocale()
{
    $locale = request()->segment(1);
    $locales = config('app.available_locales');
    $default = config('app.fallback_locale');
    if ($locale !== $default && in_array($locale, $locales)) {
        app()->setLocale($locale);
        return $locale;
    }
    return;
}

How can I generate correct hreflang tags for each locale?

Upvotes: 1

Views: 1573

Answers (2)

Stefano Amorelli
Stefano Amorelli

Reputation: 4854

We could use a blade directive to generate the hreflang tags for each locale, in each page:

@foreach (config('app.available_locales') as $locale)
   @if ($locale == app()->getLocale())
      <link rel="alternate" hreflang="{{ $locale }}" href="{{ url()->current() }}" />
   @else
      @if ($locale == config('app.fallback_locale'))
         <link rel="alternate" hreflang="{{ $locale }}" href="{{ url('/') . request()->segments() }}" />
      @else
         <link rel="alternate" hreflang="{{ $locale }}" href="{{ url('/') . $locale . request()->segments() }}" />
      @endif
   @endif
@endforeach

Upvotes: 1

feyen01
feyen01

Reputation: 417

The solution was a bit more complex that I thought, because I don't use a prefix for default language. I decided to create a custom Service Provider and return an array with locales associated with URLs for these locales (I will also use this array for the language switcher component):

public function boot()
{
    view()->composer('*', function ($view) {
        $languageUrls = [];

        $currentLocale = request()->segment(1);
        $locales = config('app.available_locales'); // ['en', 'de', 'es']
        $defaultLocale = config('app.fallback_locale'); // 'en'

        // Remove language prefix if not default from segments
        if ($currentLocale !== $defaultLocale && in_array($currentLocale, $locales)) {
            $noPrefixSegments = request()->segments();
            array_shift($noPrefixSegments);
            $noPrefixSegments = implode('/', $noPrefixSegments);
        }
        // Keep all segments
        else {
            $noPrefixSegments = request()->segments();
            $noPrefixSegments = implode('/', $noPrefixSegments);
        }

        // Generate an array of locales associated with URLs
        foreach ($locales as $locale) {
            if ($locale === $defaultLocale) {
                $languageUrls[$locale] = $noPrefixSegments;
            } else {
                $languageUrls[$locale] =  $locale . '/' . $noPrefixSegments;
            }
        }

        return $view->with('languageUrls', $languageUrls);
    });
}

Then in the blade template I simply generate all hreflangs:

@foreach ($languageUrls as $language => $url)
<link rel="alternate" hreflang="{{ $language }}" href="{{ url('/') }}/{{ $url }}" />
@endforeach

which for https://example.com/es/category/page gives me what I've expected:

<link rel="alternate" hreflang="en" href="https://example.com/category/page" />
<link rel="alternate" hreflang="es" href="https://example.com/es/category/page" />
<link rel="alternate" hreflang="de" href="https://example.com/de/category/page" />

Upvotes: 0

Related Questions