diff --git a/I18N.md b/I18N.md new file mode 100644 index 0000000..1498eb1 --- /dev/null +++ b/I18N.md @@ -0,0 +1,349 @@ +# Internationalisierung (i18n) Dokumentation + +Hördle unterstützt vollständige Mehrsprachigkeit (Internationalisierung) für Deutsch und Englisch. + +## Übersicht + +Die i18n-Implementierung basiert auf [next-intl](https://next-intl-docs.vercel.app/) und nutzt den Next.js App Router mit dynamischen `[locale]`-Segmenten. + +## Unterstützte Sprachen + +- **Deutsch (de)** - Standardsprache +- **Englisch (en)** + +## URL-Struktur + +Alle Routen sind lokalisiert: + +- `http://localhost:3000/` → Redirect zu `/de` (Standard) +- `http://localhost:3000/de` → Deutsche Version +- `http://localhost:3000/en` → Englische Version +- `http://localhost:3000/de/admin` → Admin-Dashboard (Deutsch) +- `http://localhost:3000/de/Rock` → Rock Genre (Deutsch) +- `http://localhost:3000/de/special/Weihnachtslieder` → Special (Deutsch) + +## Architektur + +### Verzeichnisstruktur + +``` +app/ + [locale]/ # Lokalisierte Routen + layout.tsx # Root Layout mit i18n Provider + page.tsx # Homepage + admin/ + page.tsx # Admin Dashboard + [genre]/ + page.tsx # Genre-spezifische Seite + special/ + [name]/ + page.tsx # Special-Seite + +i18n/ + request.ts # next-intl Konfiguration + +messages/ + de.json # Deutsche Übersetzungen + en.json # Englische Übersetzungen + +lib/ + i18n.ts # Helper-Funktionen für lokalisierte DB-Werte + navigation.ts # Lokalisierte Navigation (Link, useRouter, etc.) +``` + +### Übersetzungsdateien + +Die Übersetzungen sind in JSON-Dateien unter `messages/` organisiert: + +```json +{ + "Common": { + "loading": "Laden...", + "error": "Ein Fehler ist aufgetreten" + }, + "Game": { + "play": "Abspielen", + "pause": "Pause", + "won": "Gewonnen!" + }, + "Home": { + "welcome": "Willkommen bei Hördle" + } +} +``` + +### Datenbank-Schema + +Die folgenden Modelle unterstützen mehrsprachige Felder: + +#### Genre +- `name`: JSON `{ "de": "Rock", "en": "Rock" }` +- `subtitle`: JSON `{ "de": "Klassischer Rock", "en": "Classic Rock" }` + +#### Special +- `name`: JSON `{ "de": "Weihnachtslieder", "en": "Christmas Songs" }` +- `subtitle`: JSON `{ "de": "Festliche Musik", "en": "Festive Music" }` + +#### News +- `title`: JSON `{ "de": "Neues Feature", "en": "New Feature" }` +- `content`: JSON `{ "de": "Markdown Inhalt...", "en": "Markdown content..." }` + +### Helper-Funktionen + +#### `getLocalizedValue(value, locale, fallback?)` + +Extrahiert den lokalisierten Wert aus einem JSON-Objekt: + +```typescript +import { getLocalizedValue } from '@/lib/i18n'; + +const genreName = getLocalizedValue(genre.name, 'de'); // "Rock" +const genreNameEn = getLocalizedValue(genre.name, 'en'); // "Rock" +``` + +**Fallback-Verhalten:** +1. Versucht die angeforderte Locale (`de` oder `en`) +2. Fallback zu `de` falls nicht vorhanden +3. Fallback zu `en` falls nicht vorhanden +4. Fallback zum ersten verfügbaren Schlüssel +5. Fallback zum übergebenen `fallback`-Parameter + +#### `createLocalizedObject(de, en?)` + +Erstellt ein lokalisiertes Objekt: + +```typescript +import { createLocalizedObject } from '@/lib/i18n'; + +const name = createLocalizedObject('Rock', 'Rock'); +// { de: "Rock", en: "Rock" } +``` + +## Verwendung in Komponenten + +### Server Components + +```typescript +import { getTranslations } from 'next-intl/server'; +import { getLocalizedValue } from '@/lib/i18n'; + +export default async function Page({ params }: { params: { locale: string } }) { + const { locale } = await params; + const t = await getTranslations('Home'); + + const genreName = getLocalizedValue(genre.name, locale); + + return