We've shipped multilingual marketing sites, multilingual documentation, and multilingual back-office applications - sometimes for the same client, in the same year - and the same mistake keeps showing up in different projects: someone picks one URL strategy for "internationalization" and applies it everywhere, because the problem looks like one problem when it is actually two completely different ones that happen to share the word "language."
It doesn't work. The rules for language handling are entirely different depending on whether you're publishing content or running an application, and getting this wrong produces two distinct failure modes: broken SEO on the content side, and quietly absurd edge cases on the application side that nobody can cleanly answer.
The Webpage Case: Language Belongs in the URL
When you're publishing content - a blog, a marketing site, a documentation portal - the URL is the identity of the page. Search engines index URLs. People share links. The URL is part of the document, not metadata about it.
If your landing page lives at example.com/ and you serve French to French visitors and English to English visitors based on the Accept-Language header alone, you've created an invisible problem: two people sharing "the same link" are seeing different content. Worse, a search engine sees one URL with one language, and that's the only version it indexes. Your French SEO is dead before you've written a single French sentence.
A locale prefix like /fr/ is a step in the right direction, but it only goes halfway. The slug itself needs to be translated too - a French speaker searching for "premiers pas" won't find /fr/getting-started, because the URL is still English to them.
❌ /en/getting-started - locale prefix, English slug
❌ /fr/getting-started - locale prefix, still English slug
✅ /getting-started - English page, English slug
✅ /premiers-pas - French page, French slug
✅ /erste-schritte - German page, German slug
Each URL is a fully localized, independently addressable document, because the slug is part of the content and not metadata about it, and it should be translated like everything else on the page.
The Hybrid Approach: Locale Prefix and Translated Slug
There's a valid middle ground, especially useful at scale: combine the locale prefix with a translated slug.
✅ /en/getting-started - English prefix, English slug
✅ /fr/premiers-pas - French prefix, French slug
✅ /de/erste-schritte - German prefix, German slug
This gives you the best of both. The locale prefix makes routing trivial - your server knows which language tree to serve without a slug lookup. The translated slug still captures local search keywords and reads natively to a French or German speaker. It also makes the site structure visually obvious from the address bar: everything under /fr/ is French, full stop.
The tradeoff is a slightly longer URL and a slug-translation map you have to maintain per language. For most content sites that's a fair price, and it pairs cleanly with hreflang annotations so search engines understand these are equivalent pages in different languages:
<link rel="alternate" hreflang="en" href="https://example.com/en/getting-started" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/premiers-pas" />
<link rel="alternate" hreflang="de" href="https://example.com/de/erste-schritte" />
Either approach - translated slug alone, or locale prefix with translated slug - is fine. What is never fine is a locale prefix with an untranslated slug. That's the worst of both: longer URLs that still aren't readable in the user's language, and no SEO upside to show for it.
The App Case: Language Does Not Belong in the URL
Now open any major project management tool, or your company's internal back-office system. The URL doesn't say /en/. It doesn't carry English slugs. That's correct, and it's intentional.
In an application, you're not publishing documents - you're giving a person access to their data. The content isn't "an English article" or "a French article." It's your tasks, your calendar, your records. Language is a property of the user, not the resource.
Your coworker in Tokyo and your coworker in Berlin are looking at the same sprint board. It has one URL. One canonical identity. They each see it in their own language because their profile says so - not because they're at different addresses.
❌ app.example.com/en/projects/42 - locale in the URL
❌ app.example.com/projets/42 - translated slug in an app
✅ app.example.com/projects/42 - canonical, language-agnostic
If you put the language in the URL of an app, you immediately run into a stack of edge cases that nobody can answer cleanly. A user switches their language in settings - do you redirect them to a new URL? What happens to their open tabs? You're sending an email notification with a link to a ticket - which language prefix do you use, the sender's or the recipient's? Someone shares a link in a channel where half the team speaks Spanish and half speaks English - does the link change shape depending on who clicked it?
There is no clean answer to any of these. You've modeled the problem incorrectly from the start.
The Mental Model
| Webpage / Content Site | Application | |
|---|---|---|
| What's being served | A document | A user's data |
| Language is a property of | The content | The user |
| Language stored in | The URL and slug | User profile or session |
| Slug translated? | Yes | No |
| Locale prefix? | Optional (slug must match) | Never |
| Shareable link behavior | Both users see the same language | Each user sees their language |
| SEO matters | Yes | No |
Where It Gets Blurry
Some products live in both worlds. A public marketing site with a "Log in" button that transitions into an authenticated application is the most common shape I deal with, and we usually reach for a clean subdomain split: the marketing and docs subdomain uses fully localized URLs with translated slugs, while the application subdomain does not. This isn't pedantry - it's being honest about what each URL represents. The marketing page is a document you want indexed and shared in a specific language. The project board is a workspace your user happens to view in a specific language. Those are different things, and the URL structure should reflect that distinction clearly enough that a new developer joining the project understands it without being told.
If two people with different languages can share a URL and should see the same content, give it a fully localized URL with a translated slug. If they should each see it their way, keep language out of the URL entirely.
Webpages are documents with identities that need to be indexed, shared, and found in the right language while apps are mirrors that reflect a user's data back at them in whatever language they prefer. The URL structure should reflect that distinction clearly enough that a new developer joining the project understands it without being told.