Navigation
LocaleSwitcher
A compact language selector for public headers, with options in their own language and an async onselect.
<script>
import { LocaleSwitcher } from "@codeatlasdev/ui";
import { goto } from "$app/navigation";
const options = [
{ value: "pt-BR", label: "Português", short: "PT" },
{ value: "en", label: "English" },
];
let { data } = $props();
async function onselect(locale) {
await fetch("/api/preferences", { method: "POST", body: JSON.stringify({ locale }) });
document.cookie = `locale=${locale}; path=/; max-age=31536000`;
await goto(`/${locale}/login`);
}
</script>
<LocaleSwitcher {options} value={data.locale} {onselect} />
Options are data, the callback is yours: the component knows no router, cookie or store, so it fits an app with localized URLs (/en/login) as well as one that only sets a cookie. onselect(locale) may return a promise. While it is pending the trigger is disabled and aria-busy, and value changes only after it resolves; if it rejects the old value stays and onerror receives the error. Choosing the current language does nothing.
Each option is named in its own language and its menu item carries a lang attribute (default the option value, override with lang), so screen readers pronounce “Português” in Portuguese. The trigger shows a globe and the native name from 600px, and the short code (short, default the first two letters of value uppercased) below it; compact always shows the code. The accessible name is “Language: “ plus the visible text, so it always contains what is on screen. It has a 44px hit area on touch. The menu is a DropdownMenu radio group, so it opens with Enter, Space and the arrow keys.
To put it in a header, use the trailing slot of SiteHeader (the end of the bar), next to the primary call to action.
Basic
Native names, a short code on narrow screens and an async onselect that keeps the switcher busy.
Pick a language: the switcher stays busy until onselect resolves.
Reference #501 · Pick in the gallery
Code
In header
The SiteHeader trailing slot holds the switcher and a Sign up button.
Reference #502 · Pick in the gallery
Code
Props
| Prop | Type | Default | Description |
|---|---|---|---|
options | { value: string; label: string; short?: string; lang?: string }[] | – | The languages on offer, each `label` in its own language. `short` is the narrow-screen code, `lang` the BCP 47 tag of the item (default `value`). |
value | string | – | Current locale, an option `value`. Bindable; changes only after `onselect` succeeds. |
onselect | (value: string) => void | Promise<void> | – | Called with the picked locale. Await your save, cookie and navigation here. |
onerror | (error: unknown) => void | – | Called when `onselect` throws or rejects; `value` keeps its previous value. |
compact | boolean | false | Always show the short code. Without it the name shows from 600px. |
label | string | 'Language' | Accessible name prefix. Localized by default. |
align | 'start' | 'center' | 'end' | 'end' | Menu alignment to the trigger. |
class | string | '' | Extra classes on the trigger. |