diff --git a/CHANGELOG.md b/CHANGELOG.md index b02389c..7d7691d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.5.0] - 2026-03-31 + +### Added +- i18n: full internationalisation system (`public/i18n.js`) with German (de) and English (en) support; language auto-detected from `navigator.language`, overridable via Settings +- i18n: all user-facing strings moved to locale files (`public/locales/de.json`, `public/locales/en.json`); 489 translation keys covering all modules +- i18n: locale switch without page reload — all pages, components and navigation re-render via `locale-changed` custom event +- i18n: `oikos-locale-picker` Web Component in Settings — three options: System (follows browser language), Deutsch, English +- i18n: dates and times formatted with `Intl.DateTimeFormat` using the active locale; `formatDate()` and `formatTime()` exported from `i18n.js` +- i18n: fallback chain (active locale → German → key) ensures no untranslated keys are shown even if a future locale file is incomplete +- i18n: adding a new language requires only one JSON file (`public/locales/xx.json`) and one line in `SUPPORTED_LOCALES` + ## [0.4.0] - 2026-03-31 ### Fixed @@ -101,7 +112,8 @@ Initial release of Oikos — a self-hosted family planner for 2–6 person house - No user data cached by service worker (API requests are network-only) - Hardened `.gitignore` and `.dockerignore` to prevent accidental secret or binary leakage -[Unreleased]: https://github.com/ulsklyc/oikos/compare/v0.4.0...HEAD +[Unreleased]: https://github.com/ulsklyc/oikos/compare/v0.5.0...HEAD +[0.5.0]: https://github.com/ulsklyc/oikos/compare/v0.4.0...v0.5.0 [0.4.0]: https://github.com/ulsklyc/oikos/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/ulsklyc/oikos/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/ulsklyc/oikos/compare/v0.1.0...v0.2.1 diff --git a/docs/SPEC.md b/docs/SPEC.md index b2512f3..8b79a73 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -232,6 +232,7 @@ Benutzerverwaltung und App-Konfiguration. Nur für eingeloggte Nutzer. - **Benutzerverwaltung (Admin):** Neue Benutzer anlegen, bestehende Benutzer bearbeiten/löschen, Rollen zuweisen (admin/member) - **Kalender-Integration:** Google Calendar OAuth verbinden/trennen, Apple Calendar (CalDAV) Credentials hinterlegen, Sync-Intervall konfigurieren - **Wetter:** OpenWeatherMap Standort konfigurieren +- **Sprache:** System (folgt `navigator.language`), Deutsch, English — via `oikos-locale-picker` Web Component; Wechsel ohne Reload - **App-Info:** Version, Lizenz ### Budget (`/budget`) @@ -313,3 +314,33 @@ Benutzerverwaltung und App-Konfiguration. Nur für eingeloggte Nutzer. - Mobil: < 768px (1 Spalte, Bottom Nav) - Tablet: 768–1024px (2 Spalten, Bottom Nav) - Desktop: > 1024px (Sidebar + Content) + +--- + +## Internationalisierung (i18n) + +Alle UI-Strings werden über `public/i18n.js` verwaltet. Kein hardcodierter Text in JS-Dateien außer in Locale-Dateien. + +### Architektur + +- **Modul:** `public/i18n.js` — exports: `initI18n()`, `setLocale()`, `t(key, params?)`, `getLocale()`, `getSupportedLocales()`, `formatDate(date)`, `formatTime(date)` +- **Locale-Dateien:** `public/locales/de.json` (Referenz), `public/locales/en.json` — Struktur: `{ "modul.camelCaseKey": "Wert" }` +- **Variablen:** `{{variable}}`-Syntax in Übersetzungsstrings, z.B. `t('tasks.assignedTo', { name: 'Anna' })` +- **Fallback-Kette:** aktive Locale → Deutsch (`de`) → Key selbst +- **Datumsformat:** `Intl.DateTimeFormat` mit aktuellem Locale — `formatDate()` und `formatTime()` aus `i18n.js` + +### Sprach-Erkennung + +1. `localStorage` Eintrag `oikos-locale` (manuelle Auswahl) +2. `navigator.languages[0]` (Browser-Sprache) +3. Fallback: `de` + +### Neue Sprache hinzufügen + +1. `public/locales/xx.json` erstellen (Kopie von `de.json`, übersetzen) +2. `SUPPORTED_LOCALES` in `public/i18n.js` um `'xx'` erweitern +3. Label in `oikos-locale-picker` ergänzen (`LOCALE_LABELS['xx'] = 'Name'`) + +### Locale-Wechsel + +`setLocale(locale)` speichert die Auswahl, lädt die neue Locale-Datei und feuert das `locale-changed` Custom Event. Alle Seiten-Module und Web Components hören dieses Event und rendern sich neu — kein Seiten-Reload nötig. diff --git a/package-lock.json b/package-lock.json index ac78d07..e819a38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "oikos", - "version": "0.3.0", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "oikos", - "version": "0.3.0", + "version": "0.5.0", "license": "MIT", "dependencies": { "bcrypt": "^5.1.1", diff --git a/package.json b/package.json index 6760a40..7fadc83 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "oikos", - "version": "0.3.0", + "version": "0.5.0", "description": "Selbstgehosteter Familienplaner — Kalender, Aufgaben, Einkauf, Essensplan, Budget und mehr. Privat, offen, ohne Abo.", "main": "server/index.js", "scripts": {