42 lines
2.3 KiB
Plaintext
42 lines
2.3 KiB
Plaintext
---
|
||
description: Übersetzungssystem (i18n) – Keys, CMS, Nutzung in Astro und Svelte
|
||
globs: "src/lib/translations.ts,**/Layout.astro,src/pages/**/*.astro,src/components/**/*.svelte,src/middleware.ts"
|
||
alwaysApply: false
|
||
---
|
||
|
||
# Übersetzungssystem (i18n)
|
||
|
||
Alle sichtbaren UI-Texte kommen aus dem CMS (RustyCMS) über das Translation-Bundle.
|
||
|
||
## Quelle
|
||
|
||
- **CMS:** Translation-Bundle über API (Single Source of Truth). Slug `app`, geladen in der Middleware mit `_resolve=all`.
|
||
- **Slug:** Konstante `TRANSLATION_BUNDLE_SLUG = "app"` in `src/lib/constants.ts`.
|
||
- **Middleware:** `src/middleware.ts` lädt das Bundle einmal pro Request und setzt `Astro.locals.translations`.
|
||
|
||
## Keys definieren
|
||
|
||
1. **Key in `src/lib/translations.ts`** in das Array `TRANSLATION_KEYS` eintragen (damit `T.key_name` und Typ `TranslationKey` existieren).
|
||
2. **String in RustyCMS** in `content/de/translation_bundle/app.json5` unter `strings` eintragen. Platzhalter: `{{name}}` wird durch `t(..., { name: value })` ersetzt.
|
||
|
||
## Nutzung
|
||
|
||
### In Astro (.astro)
|
||
|
||
- `translations = Astro.locals.translations ?? {}`
|
||
- `t(translations, T.xy)` oder mit Ersetzungen: `t(translations, T.xy, { count: 5 })`
|
||
- Breadcrumbs: optional `translationKey: T.nav_start` statt `label: "Start"`; Layout löst das mit `t(translations, item.translationKey)` auf.
|
||
|
||
### In Svelte
|
||
|
||
- **Innerhalb von TranslationProvider** (z. B. Header, Footer): `const t = useTranslate();` dann `t(T.xy)`.
|
||
- **client:load-Inseln (Astro Islands):** `useTranslate()` hat keinen Zugriff auf den Svelte-Context, und beim SSR gibt es kein `window` → Übersetzungen fehlen, es erscheint der Key (z. B. `blog_tag_all`).
|
||
**Lösung:** Übersetzungen immer als Prop von der Astro-Seite übergeben und die statische `t()` nutzen:
|
||
- Komponente: Prop `translations?: Translations`; keine `useTranslate()`, sondern lokale Hilfsfunktion `t(key, replacements) => t(translations ?? null, key, replacements)` mit `t` aus `../lib/translations`.
|
||
- Astro-Seite: `<BlogOverview ... translations={translations} />` mit `translations = Astro.locals.translations ?? {}`.
|
||
- Siehe `BlogOverview.svelte` als Referenz.
|
||
|
||
### Neue UI-Texte
|
||
|
||
Keine hartkodierten deutschen/englischen Sätze in Komponenten oder Seiten. Stattdessen: Key in `TRANSLATION_KEYS` + Eintrag in `app.json5`, dann überall `t(translations, T.key)` bzw. `t(T.key)` nutzen.
|