---
id: "packages/active-i18n/language-choice"
title: "Language choice"
description: "Who decides the reader's language, how a request is matched against your language set, and how a switch is stored."
url: "/packages/active-i18n/language-choice"
locale: "en"
revision: "6d706c29c27df42e"
---

# Language choice

**Your application decides the language.** The package reads no cookie, no header and no setting by
itself; you resolve the language and pass it in. It helps with the matching and with the switch.

## Matching a request against your set

```ts
import {
  lookupFirstSupportedLocale,
  lookupSupportedLocale,
} from '@workspace/active-i18n';

lookupSupportedLocale('en-GB', ['en', 'nl']); // 'en' (truncated one subtag at a time)
lookupSupportedLocale('pt', ['pt-BR']); // undefined: never more specific
lookupFirstSupportedLocale(['de-CH', 'fr'], ['de', 'fr']); // 'de'
```

This is RFC 4647 lookup, not a negotiation engine: no best fit, no likely subtags, no sibling
region. What follows a miss (your fallback language) is yours.

In a Next request, `getAcceptLanguageCandidates()` from
`@workspace/active-i18n/server/get-locale` gives the `Accept-Language` header as canonical tags in
priority order, unfiltered; pass them to `lookupFirstSupportedLocale`.

## Switching the language

`<I18nProvider>` never changes language in memory. `setLocale(code)` (from `useLocaleSwitcher`):

1. asks your `confirmLocaleSwitch` guard, when given (a page with unsaved work says no);
2. hands the choice to your `persistLocale`, when given (a cookie, a profile);
3. sets `<html lang>` and navigates, so the server renders the new language.

It resolves to a `LocaleSwitchOutcome` and never throws: `'switched'`, `'declined'`,
`'persist-failed'`, `'pending'` (a switch already under way), `'navigation-guarded'` and others.

## The language set

Each entry of `supportedLanguages` is a `LanguageConfig`: `code`, `label` and optionally
`direction`. Show a language by its own name, never by a flag: the package reads no flag and no
switcher may show one.
