In a multilingual Laravel application, it is easy to assume that every language should automatically have its own slug.
In ICanUp, I eventually chose a different model: Posts and Categories use one shared slug, while the locale controls the URL prefix and localized content without becoming part of the entity identity.
That decision affected much more than routing. It simplified hreflang, sitemaps, IndexNow, internal links, and the contract between the backend and frontend.


The Current Contract in ICanUp
In the current ICanUp model, the slug belongs directly to the Post or Category.
Validation checks its uniqueness without a locale dimension, and model lookup uses one shared value.
A translation changes the content, but it does not create another route identity for the same entity.
posts id slug UNIQUE ... categories id slug UNIQUE ... translations locale localized content localized SEO fieldsThis contract is enforced not only by application validation but also by unique constraints on the shared slug in the database.
Rule::unique('posts', 'slug'); Rule::unique('categories', 'slug');Shared Slugs and Translated Slugs Create Different URL Models
Model | UK URL | EN URL |
|---|---|---|
Shared slug | /posts/laravel-localization | /en/posts/laravel-localization |
Translated slugs | /posts/laravel-lokalizatsiia | /en/posts/laravel-localization |
With a shared slug, the locale changes the route namespace while the content identifier stays the same.
With translated slugs, the locale becomes part of the lookup contract because a slug alone is no longer enough to resolve the entity.
Why I Chose a Shared Slug
- One entity has one stable route identity.
- Slug lookup does not depend on translation storage.
- Changing one translation does not change another locale URL.
- Frontend and backend use the same logical route contract.
- Sitemaps, hreflang, and IndexNow work from one entity and generate its locale-aware URLs.
- Internal links are easier to build without resolving a separate slug for every target language.
This naturally continues the approach I described in my article about logical route names and localized URLs in Laravel.
I want application code to think in terms of a logical destination while the localization layer decides which locale prefix belongs in the public URL.
A Default Locale and Shared Slug Do Not Mean Identical URLs
UK default locale:https://icanup.com.ua/posts/example-slug EN locale:https://icanup.com.ua/en/posts/example-slugIn ICanUp, UK is the default locale, so its URL has no additional prefix.
The English URL receives /en, while the slug remains the same.
URL localization comes from the routing layer, not from translating the slug itself.
Route Lookup Becomes Simpler
With a shared slug, the entity can be resolved independently of the currently active locale.
$post = Post::query() ->where('slug', $slug) ->firstOrFail();With translated slugs, lookup usually has to include the locale or a translation relation.
That is not inherently wrong, but the locale becomes part of identity resolution, which means it follows routing, validation, redirects, caching, and tests.
Localized Content Still Remains Fully Localized
A shared slug does not mean that every language gets the same page.
Titles, short text, content blocks, SEO metadata, and other localized values can still differ completely between UK and EN.
I simply separate content translation from route identity.
Field | Shared | Localized |
|---|---|---|
Post ID | Yes | No |
Slug | Yes | No |
Title | No | Yes |
Content | No | Yes |
Meta Title | No | Yes |
Meta Description | No | Yes |
Public URL prefix | No | Yes |
A Shared Slug Does Not Create SEO Duplicates
The same slug fragment in two locale URLs does not automatically make them duplicate content.
Search engines see separate URLs with localized content, a self-canonical, and the correct hreflang relationship.
I covered that infrastructure separately in my article about Laravel hreflang and canonical URLs.
Sitemaps and IndexNow Benefit from Stable Identity Too
When the SEO layer receives a Post, it does not need to search the translation table for a route slug.
It starts with one entity and generates the required locale-aware URLs through the routing and localization contract.
I use the same principle in my IndexNow implementation and my locale-aware sitemap lastmod implementation.
- HreflangService generates URLs for available locales.
- The sitemap works with the same entity identity.
- IndexNow receives current public URLs instead of implementing its own slug logic.
- Changing visible translated content does not require a different slug lookup contract.
What Would Change with Translated Slugs
Translated slugs can produce more natural language-specific paths, but they move part of the complexity into infrastructure.
One entity now has several route identifiers, and each one can change independently.
The slug becomes localized content with routing consequences.
Concern | Shared slug | Translated slugs |
|---|---|---|
Lookup | slug | locale + translated slug |
Uniqueness | global slug | usually locale + slug |
Slug change | one route identity | independent per locale |
Redirects | one shared history | history per locale |
Internal links | shared entity slug | resolve target-locale slug |
SEO URL generation | route + locale | route + locale + translated slug |
Redirect History Becomes Locale-Specific
If the EN slug changes while the UK slug stays the same, only the English URL needs a redirect.
If the UK slug changes later, another redirect history starts there.
For a project where URLs change frequently, this becomes a separate domain concern that has to be stored and tested.
Admin Validation Becomes More Complex Too
A shared slug has one uniqueness rule.
With translated slugs, I need to decide whether a slug is globally unique, unique only inside one locale, or unique within a content type and locale.
I also need a rule for translations that exist while their localized slug is still empty.
When Translated Slugs Can Be the Better Choice
- The URL should read naturally in every language.
- The locales use different alphabets and the slug is an important part of the user experience.
- Keyword strategy differs significantly between locales.
- The project already has reliable locale-specific redirect history.
- CMS editors expect full URL control for each language.
- Routing infrastructure was designed around locale + slug identity from the beginning.
For ICanUp, the Trade-Off Favored a Shared Slug
For my blog, stable routing, multilingual SEO, and using the same content identity across services are more important than translating every path segment.
A shared slug gives up some localization flexibility, but it reduces the number of places where the application has to understand translated route keys.
For ICanUp, that trade-off has been the better fit.
I localize the content and URL namespace without duplicating entity identity unless I actually need to.
What I Verify in This Contract
- Post slug is unique at the posts level.
- Category slug is unique at the categories level.
- UK and EN URLs use the same shared slug.
- The default locale does not receive an unnecessary locale prefix.
- The EN URL receives the /en prefix.
- Hreflang uses the current shared slug.
- A disabled or unavailable locale is not advertised as an alternate.
- Sitemap and IndexNow use the same canonical public URLs.
- Legacy translated slugs do not return to the routing contract.
What I Kept for Next Time
- Define entity identity before deciding whether the slug should be localized.
- Do not automatically mix content translation with route identity.
- Plan redirect history before introducing translated slugs.
- Use one URL generation contract for routing, hreflang, sitemaps, RSS, and IndexNow.
- Do not let an SEO service independently decide how a localized route should look.
- Test unavailable locales separately from enabled locales.
Conclusion
A shared slug in a multilingual Laravel application can initially look less localized than a separate slug for every language.
But once routing is consumed by the frontend, hreflang, sitemaps, IndexNow, RSS, and internal links, the real cost of route identity becomes much clearer.
In ICanUp, I kept the slug shared and moved localization into the locale-aware routing and content layers.
For me, that created a simpler contract: one entity, one slug identity, and multiple fully localized public URLs.



