Locale auswählen
Die Locale wird bestimmt, indem eine Liste von Quellen durchlaufen wird; der erste Treffer gewinnt. Quellen, die auf der aktuellen Seite nicht zutreffen, werden übersprungen, sodass dieselbe Liste auf dem Server und im Browser funktioniert.
Die Standardreihenfolge #
strategy: ['url', 'cookie', 'lang', 'header', 'navigator', 'default'];url bewirkt nur etwas, wenn Routing aktiv ist. header (Accept-Language) gibt es nur auf dem Server. lang (<html lang>) und navigator gibt es nur im Browser, wobei lang ignoriert wird, wenn es defaultLocale entspricht — eine prerenderte Seite nennt immer die Standard-Locale, dieser Wert trägt also keine Entscheidung.
Die Reihenfolge ändern #
Kürze oder ordne die Liste nach Bedarf um — rate etwa nie anhand des Browsers, sondern nimm nur das Cookie oder den Standard:
createDialect({
strategy: ['cookie', 'default'],
// …
});Caching #
Wenn header mitspielt, tragen die Antworten Vary: Accept-Language, und wenn cookie mitspielt, Vary: Cookie — damit ein geteilter Cache nie die Sprache eines Besuchers an einen anderen ausliefert.
Request-Isolation #
Auf dem Server wird jeder Request in seinem eigenen AsyncLocalStorage-Kontext aufgelöst, sodass gleichzeitige Requests mit unterschiedlichen Sprachen einander nicht beeinflussen können — t() und getLocale() sehen während eines Renders immer die Locale genau dieses Requests. Laufzeiten ohne async_hooks greifen stattdessen auf einen einzigen gemeinsamen Slot zurück.
Zur Laufzeit bestimmte Locales #
createDialect läuft beim Modulimport, bevor die Einstellungstabelle eines Betreibers oder eine beim Start gelesene Umgebungsvariable erreichbar ist. configure ersetzt die Menge der Locales und die Standard-Locale nachträglich, und jeder nachgelagerte Leser — Aushandlung, setLocale, reroute, localizeHref — übernimmt die neuen Werte.
Rufe es einmal auf dem Server beim Start auf, vor dem ersten Request, und noch einmal auf dem Client bei der App-Initialisierung mit dem, was der Server über Page Data geliefert hat — configure ist idempotent, ein erneuter Aufruf bei jeder Navigation kostet also nichts.
import { configure, handle as dialect } from '#lib/i18n.js';
const settings = await loadLocaleSettings();
configure({ defaultLocale: settings.defaultLocale, locales: settings.locales });
export const handle = dialect;import { configure } from '#lib/i18n.js';
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = async ({ data }) => {
configure(data.i18n);
return data;
};locales ersetzt die Menge vollständig, statt sie zu ergänzen, und defaultLocale muss zur resultierenden Menge gehören; ein Aufruf, der eine der beiden Regeln verletzt, warnt und ändert nichts. reroute ist der einzige Teil, der nicht darauf warten kann — SvelteKit ruft ihn synchron vor jeder Load-Funktion auf —, daher ist ein Präfix, das configure entfernt, überhaupt keine Route mehr.