Geoffrey D's avatar

What is the best approach for translating multilingual URLs?

Hello everyone,

I am currently working on implementing translations in a Laravel website. For now, I am using Laravel's static translation files and the website is available in two languages (French/English). Eventually, it will be available in five languages.

currently :

  • /fr/a-propos
  • /en/a-propos

My goal is also to translate the URLs, for example:

  • /fr/a-propos
  • /en/about
  • /it/a-proposito

This raises several questions for me:

  1. Should I only keep the locale in the URL and leave the rest of the structure unchanged?
  2. Should all URLs be translated, which would involve redesigning the routing system?
  3. Should translation management via the database be considered?

If you had to choose between these solutions, which would you prefer and why? Do you have any resources or links to share for further reading on this topic?

I’d like to implement a clean solution, and later on I also want to improve SEO. I have also translated the road names and navigation menu for testing purposes.

Thank you in advance for your feedback!

0 likes
4 replies
LaryAI's avatar
Level 58

Great question! Translating multilingual URLs in Laravel is a common challenge and the approach can depend on your site's needs, SEO strategy, and maintainability considerations.

1. URL Structures: Localized Only Locale vs. Full URL Translation

  • Locale Only (e.g. /en/about, /fr/about):
    This is easier to maintain, as you use a "slug" once and just prepend the locale. It's the standard Laravel Route::group(['prefix' => '{locale}'], ...) approach.

  • Full URL Translation (e.g. /en/about, /fr/a-propos):
    This is more "user friendly" and SEO-optimized for each language, but is also significantly more complex to implement and maintain.

2. Translate ALL URLs?

If your target is better user experience and SEO in each language, translating URLs is recommended. European users in particular expect to see their language in the entire URL, not just the content.

3. Translation Management: Static Files vs. Database

  • For a limited set of routes/pages, keeping translated slugs in lang files (e.g. lang/en/routes.php and lang/fr/routes.php) is manageable.
  • For lots of dynamic content (e.g. blog posts), storing slugs in the database per language is best.

Recommended Approach

For mostly static routes, keep translations in lang files. For dynamic content, store slugs in the database. Redesigning your Laravel routes for localization is necessary if you want truly translated URLs.

Here's how you can handle static translated URLs in Laravel:

1. In your lang files:

resources/lang/en/routes.php

return [
    'about' => 'about',
    'contact' => 'contact',
];

resources/lang/fr/routes.php

return [
    'about' => 'a-propos',
    'contact' => 'contact',
];

2. Generating routes in web.php:

foreach (['en', 'fr'] as $locale) {
    App::setLocale($locale);
    $aboutSlug = trans('routes.about');

    Route::get("$locale/$aboutSlug", function () use ($locale) {
        App::setLocale($locale);
        return view('about');
    })->name("$locale.about");
}

3. Generating URLs in Blade:

<a href="{{ route(app()->getLocale().'.about') }}">
    {{ __('About Us') }}
</a>

For dynamic slugs (e.g., blog posts):

  • Store a slug for each language in the posts table.
  • Fetch and use the appropriate slug per locale in route models and URL generations.

Resources


Conclusion

  • Translating all URLs (not just content) is best for international audiences and SEO.
  • For static routes, translation via lang files works well.
  • For dynamic content, use database translations.
  • For easier implementation, check out mcamara/laravel-localization, which handles much of this for you.

Let me know if you want to see a full code example for dynamic routes or any specific implementation details!

Glukinho's avatar

What if you once have non-latin language to translate to? Your translated URLs may look ugly in that case.

JussiMannisto's avatar

The standard practice is to transliterate non-ascii characters into ascii.

JussiMannisto's avatar
  1. I'd translate the whole URL. It's a better user experience.
  2. Do whatever you think is best for the user. The routing system can be extended easily, for example by creating a helper function localized_route and/or by adding a macro to the Route facade.
  3. I'd define all routes statically.

Please or to participate in this conversation.