Messages laden
Drei Wege, Messages hineinzubekommen, und zwei Muster, um eine Seite darauf warten zu lassen. Sie lassen sich kombinieren: Bündle, was jede Seite braucht, und hol den Rest nach.
1. Zur Build-Zeit #
createDialect({
messages: {
// eager: inlined at build time
...import.meta.glob('./messages/**/*.json', { eager: true }),
// not eager: fetched the first time a page asks for it
...import.meta.glob('./messages-lazy/**/*.json')
},
defaultLocale: 'en'
});Der Standard. import.meta.glob liest die Dateien beim Kompilieren und bettet sie ein — kein Request zur Laufzeit, nichts zu konfigurieren.
Lass eager: true im selben Glob weg, und jeder Namespace wird zu einem eigenen Chunk, der beim ersten Zugriff einer Seite geladen wird. Beide Varianten können im selben messages-Objekt stehen.
2. Bei Bedarf #
Zwei Muster, um vor dem Rendern auf einen Namespace zu warten. Unten verwendet je eine Seite eines davon — lade neu, um beide laufen zu sehen.
In einer Load-Funktion #
Eine universelle Load-Funktion darf alles zurückgeben, auch die Funktion t selbst. Funktioniert mit stabilem SvelteKit, ohne Compiler-Flags.
In einer Load-Funktion geladen
Dieser Namespace wurde in einer universellen Load-Funktion geholt, die die Funktion t selbst zurückgegeben hat. Es sind keine experimentellen Compiler-Optionen im Spiel — das ist das Muster für stabiles SvelteKit.
In der Komponente #
Direkt im <script> mit await.
Bei Bedarf geladen
Dieser Namespace ist nicht im Bundle der Seite enthalten. Er kommt über den Loader, den du konfigurierst — hier ein dynamischer Import, in deiner App genauso gut ein fetch an eine API.
In 3 Sprachen verfügbar
Hinweis
Dafür brauchst du Svelte 5.36+ und compilerOptions.experimental.async.
export const load: PageLoad = async () => await loadTranslations('billing');const { data }: PageProps = $props();
<h1>{data.t('billing:title')}</h1>// in the component's script, with experimental.async on
import { loadTranslations } from '#lib/i18n.js';
const { t } = await loadTranslations('dashboard');
// then in the markup
{t('dashboard:title')}3. Aus deiner eigenen API #
SvelteKit Remote Functions #
Eine query(), die wie eine lokale Funktion aufgerufen und in deinem Loader ausgeführt wird — kein Endpunkt zu schreiben, kein fetch, bei dem etwas schiefgehen kann. Erfordert kit.experimental.remoteFunctions und compilerOptions.experimental.async.
import * as v from 'valibot';
import { query } from '$app/server';
export const getMessages = query(
v.object({ locale: v.picklist(['en', 'ru']), namespace: v.picklist(['dashboard']) }),
async ({ locale, namespace }) => db.loadMessages(locale, namespace)
);createDialect({
defaultLocale: 'en',
locales: ['en', 'ru'],
loader: async ({ locale, namespace }) => getMessages({ locale, namespace })
});Einfaches fetch #
Die portable Variante: keine experimentellen Flags, funktioniert beim SSR, sofern die URL absolut ist — auf dem Server gibt es keine Seite, auf die sich eine relative URL beziehen könnte.
createDialect({
defaultLocale: 'en',
locales: ['en', 'ru'],
loader: async ({ locale, namespace }) => {
const res = await fetch(`https://example.com/i18n/${locale}/${namespace}.json`);
return res.json();
}
});Ein Aufruf, egal wie viele Requests #
Gleichzeitige Aufrufer für dieselbe Locale und denselben Namespace teilen sich einen laufenden Loader-Aufruf, sodass hundert gleichzeitige SSR-Requests einen fetch auslösen, nicht hundert.