# Meertalig Laravel: vertaalde routes goed gedaan

> Geef elke locale een écht vertaalde URL (/pricing, /nl/tarieven, /es/precios) in plaats van Engelse slugs te prefixen. Los slugs op uit vertaalbestanden bij het registreren van routes, stuur een complete reciproke hreflang-set inclusief x-default, houd canonicals binnen de locale, en redirect crawlers nooit op Accept-Language. Die vier regels dekken het meeste dat misgaat.

De meeste meertalige Laravel-applicaties worden hetzelfde gebouwd: een Engelse routetabel met een localeprefix ervoor geschroefd. Het werkt, en het laat de niet-Engelse versies nergens op ranken waar iemand écht naar zoekt.

## Waarom de slug vertaald moet worden

Een Nederlandse prospect die naar prijzen zoekt, typt *tarieven*. De URL is een echt, zij het bescheiden, relevanciesignaal, en belangrijker: het is wat in resultaten staat, in berichten wordt gedeeld en door assistenten wordt voorgelezen. `/nl/pricing` kondigt een vertaling van een Engelse site aan. `/nl/tarieven` kondigt een Nederlandse pagina aan.

Hetzelfde geldt voor het hele pad. Deze site draait `/pricing`, `/nl/tarieven` en `/es/precios`; `/ai-development`, `/nl/ai-development` en `/es/desarrollo-ia`. De Nederlandse markt gebruikt voor die ene het Engelse woord, dus vertalen zou slechter zijn.

Dat laatste detail is het echte punt: slugkeuze is een keywordbeslissing per taal, geen vertaaltaak. Het kan niet geautomatiseerd worden, en het is de reden dat de slugs in vertaalbestanden horen, waar een mens ze stuk voor stuk kan zetten.

## Hoe je het bouwt

Zet de slugs in een vertaalbestand per locale, één entry per pagina:

```php
// lang/nl/routes.php
return [
    'pricing' => 'tarieven',
    'about' => 'over',
    'ai-development' => 'ai-development',
];
```

Registreer de routes daarna één keer, en los elke URI via de translator op, binnen welk gelokaliseerd-routemechanisme je ook gebruikt. Elke locale krijgt zijn eigen route met zijn eigen pad en een locale-geprefixte naam, zodat `route('pricing')` de URL van de huidige locale geeft en links overal kloppen zonder één voorwaarde in een template.

Twee regels houden dit over tijd overeind. Hernoem nooit een slug die al rankt. Daar zit geen upside in, en je erft een redirect die je voor altijd moet onderhouden. En houd de redirecttabel voor oude URL's als data in één array, niet als een stapel losse closures, zodat een test hem volledig kan asserten.

## De hreflang-fouten die ertoe doen

Hier gaan meertalige sites het vaakst stuk, en de falen zijn stil.

**De set moet reciprook en zelfverwijzend zijn.** Elke locale-pagina somt elke locale op, inclusief zichzelf. Als de Nederlandse pagina naar Engels en Spaans wijst maar de Engelse pagina niet terug naar Nederlands, gooit de zoekmachine de relatie weg.

**`x-default` is niet optioneel.** Het vertelt de engine wat te serveren aan iemand die in geen van je locales past. Wijs het naar de taal met het breedste bereik, meestal Engels.

**Canonicals blijven binnen de locale.** De canonical van de Nederlandse pagina is de Nederlandse URL. Een canonical van de Nederlandse pagina naar de Engelse is een instructie om de Nederlandse pagina uit de index te gooien, en het is een opvallend veelvoorkomend ongeluk.

**Som alleen locales op die bestaan.** Als een blogpost een Engelse versie heeft en geen Nederlandse, stuur dan geen Nederlands alternate. Daarom hebben vertalingen een gedeelde identifier nodig (de bestandsnaam, of een key) die losstaat van de vertaalde slug, zodat het systeem kan zien of een vertaling bestaat in plaats van dat aan te nemen.

## Redirect een crawler nooit op Accept-Language

Eerste bezoekers automatisch naar de taal van hun browser sturen is goed voor mensen en rampzalig als het ook voor bots geldt. Een crawler die aankomt met een Europees IP en geen taalvoorkeur wordt in één locale gestuiterd, en de andere blijven ongekropen en ongeïndexeerd.

Drie regels houden het veilig: vrijwaar bekende crawler-useragents volledig; redirect alleen een eerste bezoek, achter een cookie, zodat een bezoeker die een taal koos die houdt; en gebruik altijd een tijdelijke redirect, nooit een permanente, omdat de bestemming van de bezoeker afhangt.

## Testen wat je niet kunt zien

Twee tests vangen het meeste.

Assert dat elke route in elke locale resolvet, 200 teruggeeft, en precies één `h1` rendert. Stuur het vanuit de localeconfig, zodat het toevoegen van een taal de dekking automatisch uitbreidt. Als het toevoegen van een locale ergens anders een codewijziging vraagt dan een configentry en een taaldirectory, is de architectuur fout en is deze test wat je dat vertelt.

Assert daarna de hreflang-sets: voor elke pagina in elke locale bevat de set elke locale, bevat hij zichzelf, bevat hij `x-default`, en resolvet elke URL erin. Reciprociteit is precies het soort eigenschap dat met de hand saai is om te checken en in een lus triviaal.

## De korte versie

Vertaalde slugs uit vertaalbestanden. Eén routeregistratie voor alle locales. Reciproke, zelfverwijzende hreflang met `x-default`. Canonicals binnen de locale. Bots vrijgesteld van taalredirects. Tests die de localelijst itereren in plaats van hem hard te coderen.

Doe dat, en een vierde taal toevoegen is een directory en een configentry, wat hier de enige redelijke definitie van klaar is.

---

Gepubliceerd door Vuewer. AI-functies en webapplicaties, tot in productie.
Canonieke versie: https://vuewer.com/nl/blog/meertalig-laravel-vertaalde-routes