CodePark/ questions / Locale detection & routing
START PRACTICINGPRACTICE
Frontend question · Internationalization › Locale detection & routing

How should a web app decide which locale to show a user?

Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, *;q=0.5

App supports: en, fr-FR, ar
Best match:   fr-FR

Use a clear order of signals, from the most explicit to the least, and always let the user change it.

The usual order:

  • The user's saved choice: a setting in their account, or a cookie from a language switcher.
  • The URL: /fr/pricing or fr.example.com. A shared link should open in the language it was shared in.
  • The browser's languages: the Accept-Language request header on the server, or navigator.languages in the browser. They list the user's languages in order of preference, with q weights.
  • A default locale, like en.

Negotiation means matching the user's list to the locales you support. Exact matches are rare, so fall back step by step. fr-CH (French in Switzerland) has no exact match above, so it falls back to French, and fr-FR is the closest. Libraries like @formatjs/intl-localematcher do this matching.

Things to avoid:

  • Don't choose the language from the IP address's country. A traveller or an English speaker in Egypt gets the wrong language. Country is fine for currency or shipping suggestions.
  • Don't redirect automatically on every visit. Redirect once, or show a banner like "View this page in French?".
  • Don't hide the language switcher. Show each language in its own name: "Français", "العربية".
  • A saved user choice beats everything else.
  • The locale in the URL makes links shareable in one language.
  • Accept-Language and navigator.languages give the browser's preferred languages in order.
  • Negotiation falls back from a specific locale like fr-CH to fr and then to a default.
  • Don't choose the language from the IP address's country.
  • Always offer a visible language switcher.