Internationalisierung (i18n)
Roestify verwendet next-intl für die Mehrsprachigkeit. Aktuell werden 4 Sprachen unterstützt.
Unterstützte Sprachen
| Locale | Sprache | Status |
|---|---|---|
de | Deutsch | Vollständig (Standard) |
en | Englisch | Vollständig |
fr | Französisch | EN-Fallback (in Arbeit) |
es | Spanisch | EN-Fallback (in Arbeit) |
Architektur
Config
src/i18n/config.ts # Locale-Liste, Default-Locale
src/i18n/request.ts # Server-seitige Locale-Erkennung
messages/
├── de.json # Deutsche Übersetzungen (~2562 Keys)
├── en.json # Englische Übersetzungen
├── fr.json # Französisch (EN-Fallback)
└── es.json # Spanisch (EN-Fallback)
Locale-Routing
- App-Seiten (Dashboard): Cookie-basiert (
NEXT_LOCALE), kein URL-Prefix - Public Pages (Pricing, Legal): URL-Prefix (
/de/pricing,/en/pricing) +hreflang-Tags
DB-Persistenz
Die Sprache wird im Profil gespeichert:
profiles.locale → "de" | "en" | "fr" | "es"
Mutation: tenant.profile.updateLocale (tRPC)
Verwendung
In Client Components
'use client';
import { useTranslations } from 'next-intl';
export function MyComponent() {
const t = useTranslations('dashboard');
return <h1>{t('title')}</h1>;
}
In Server Components
import { getTranslations } from 'next-intl/server';
export default async function Page() {
const t = await getTranslations('dashboard');
return <h1>{t('title')}</h1>;
}
Message-Struktur
Keys sind nach Sektion gruppiert:
{
"dashboard": {
"title": "Dashboard",
"greeting": "Guten {timeOfDay}, {name}"
},
"roles": {
"admin": "Admin",
"adminDescription": "Voller Zugriff auf alle Bereiche"
}
}
Listen in Messages
Für Listen wird der |-Separator verwendet:
{
"features": "Feature 1|Feature 2|Feature 3"
}
const items = t('features').split('|');
Konventionen
- Niemals hardcoded deutsche Strings in Komponenten
- Niemals Sternchen
*in Label-Strings (Pflichtfelder werden nicht markiert) - Rollen-Labels:
useTranslations("roles")verwenden, nichtROLE_LABELS - E-Mail-Templates: Bleiben Deutsch (serverseitig, kein
useTranslations) - Optionale Felder:
"(optional)"im Label-String