skip to content

In a multi-language site, what does carrying the language in a URL path segment give you that a cookie alone does not?

level: juniorimportance: must knowfreq 62%

answer

  1. identity, not preference
  2. one address per translation
  3. linkable, prerenderable, cacheable separately
  4. a cookie hides the choice from the URL
  5. outermost segment wraps the whole tree

basics

~20 s

A language in the path gives every translation its own address, so it can be linked, bookmarked, prerendered, crawled and cached as a distinct page. A cookie-only language makes one address return different text to different visitors.

solid answer

~50 s

Putting the language in the path — `/en/pricing` next to `/de/pricing` — makes the language part of the resource identity. Each translation becomes its own URL, so a shared link opens in the language the sender saw, a build can prerender one file per path per language, and a shared cache can store each language under its own address without handing one visitor's language to the next. A cookie-only locale keeps a single URL whose body changes per request: it cannot be prerendered as one artifact per path, a shared link loses the language, and any cache in front of it has to be told the response depends on the request. A hostname per language buys the same URL-level identity as a segment, at higher operational cost. The practical consequence of the segment is that it usually sits outermost in the route tree, so every internal link has to be built with the active language in it.

go deeper

for a junior

Remember the core trade: language in the path means one URL per translation, so links and bookmarks carry the language; language in a cookie means one URL that looks different to different people.

for a middle

Explain why identity matters downstream — a build can prerender per path per language, a shared cache can key on the address, and a crawler can follow each language separately only when it has its own URL.

for a senior

Show what the segment costs in practice: every internal link must carry it, the site root becomes a per-request decision, and untranslated pages still resolve under every language and need a defined fallback behaviour.

for a principal

Frame it as a commitment about resource identity rather than a routing detail, and be able to say when a stored preference is the honest choice — private, non-indexed, non-shared surfaces — and what migrating between the two later would cost.

A site published in several languages has to answer one structural question before anything else: **is the language part of the address, or part of the visitor?** Prerendering, caching, linking, crawling and the shape of the route tree all follow from that one answer. ## Three places the locale can live | Where it lives | Example address | One address returns | |---|---|---| | **Path segment** | `/en/pricing`, `/de/pricing` | one language, for everyone | | **Hostname** | `en.example.com/pricing`, `example.de/pricing` | one language, for everyone | | **Cookie or session only** | `/pricing` for everybody | different text per visitor | The first two make the language **part of the resource identity**: the address and the language are the same fact, and anything that keys on the address — a build, a cache, a crawler, a bookmark — gets the language for free. The third makes the language part of the *request context*, which is a different and far more expensive thing to be. ## What putting it in the URL buys - **A shareable link.** Whatever the sender saw is what the recipient sees. With a cookie-only locale the same link renders in the recipient's stored language instead. - **A prerenderable page.** A build can emit one finished file per path per language, because the language is known from the path before any request exists. - **A shared cache that cannot leak.** Different languages sit at different keys, so a cache in front of the app cannot hand a German body to an English visitor. With one URL for all languages the response depends on something the address does not carry, and the cache has to be told so explicitly. - **An indexable page.** A crawler that sends no language preference still reaches every language, because each one has its own address to follow. - **A debuggable report.** A bug report that pastes a URL reproduces in the right language. - **A trivial switcher.** Changing language is a link to the same path under a different segment, not a state mutation plus a re-render. ## What a cookie-only locale costs - One address, many bodies. Every cache layer in front of the app has to be told the response is request-dependent, or it will replay one visitor's language to the next. - The page cannot be prerendered as one artifact per path; at best a language-neutral shell is prerendered and the text is filled in per request or after load. - Links, bookmarks, shared URLs and screenshots all lose the language. - Automated clients and crawlers that send no preference see exactly one language of the site. ## What the segment does to the route tree - It is normally the **outermost** segment, so every route sits underneath it. The route definitions do not multiply; the addresses do. - A level of the layout chain scoped to that segment can resolve the active language once and supply its entire subtree, so individual pages never re-derive it. - Every internal link now has to be built with the active language in it. That is precisely why multi-language codebases grow a link helper instead of hand-written path strings — one forgotten prefix drops the visitor back to the default language. - An untranslated page still resolves at every language's address. The router happily matches it; something in the internationalisation layer has to decide what to show when the strings are missing. - The bare address with no language in it — the site root — becomes a special case, because it is the one URL where the language is genuinely unknown and has to be decided per request. ## Hostname instead of segment A hostname per language gives the same URL-level identity and adds hard separation: different origins, separate cookie scopes, the option to serve each from different infrastructure. It costs certificates, DNS, per-host configuration and a cross-origin language switch, and it is only honest when the locales are really different sites rather than translations of one. ## Rules of thumb 1. Public, linkable, indexable, cacheable content → put the language in the URL. 2. A signed-in application shell that nobody shares or indexes → a stored preference is defensible, and avoids duplicating every internal address. 3. Whichever you choose, resolve it once at the top of the tree and pass it down; deriving it independently in each page is how two parts of one screen end up in different languages.

  • If the language lives in a path segment, what still has to happen the first time someone arrives at the bare site root?
    The root carries no language, so it is the one address where the language must be decided per request — from the request's stated preference, a stored choice, or geography — and the visitor sent onward to a language-bearing URL. That single per-request decision is what puts request-time work in front of an otherwise fully static site, and it is the part that most often ends up wrongly cached.
  • Why does a language segment force a link helper rather than plain path strings?
    Every internal address now needs the active language in it. A hand-written path is missing that prefix, so following it silently drops the visitor into the default language mid-session, and nothing fails loudly. A helper that takes the current language and a path makes the prefix impossible to forget and gives one place to change the URL shape later.
  • Does putting the language in the URL mean the site no longer needs to read the request's stated language preference?
    No. The URL wins once it exists, but the preference is still what decides where a visitor with no language in the address should land, and it is still a useful hint for offering a switch when someone arrives on a language they probably cannot read. The rule is order, not exclusion: an explicit URL beats a stored choice, which beats a header guess.

saying these in an interview costs you the question

  • Thinks a cookie-only language is fine for public pages because the visitor sees the right text
  • Says one URL can safely return different languages to a shared cache
  • Assumes adding a language segment does not touch every internal link
  • Believes the language segment is cosmetic and does not change the route tree
  • Expects untranslated pages to disappear from the other languages automatically