timetracker/.tasks/done/TT-011-localisation-i18n.md
2026-08-03 21:51:48 +02:00

131 lines
3 KiB
Markdown

# TT-011 — Localisation (i18n)
**Type:** Story
**Priority:** Medium
**Labels:** i18n, l10n, infrastructure
**Depends on:** TT-001
**Blocks:** TT-006, TT-007, TT-008, TT-009, TT-010
---
## Summary
Set up `flutter_localizations` with ARB files for English (`en`) and German
(`de`). All UI strings must be externalised — no hardcoded display text in
widget files.
## Setup
### l10n.yaml (project root)
```yaml
arb-dir: lib/core/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
```
### File structure
```
lib/core/l10n/
app_en.arb ← template (English)
app_de.arb ← German translations
```
Generated: `lib/core/l10n/app_localizations.dart` (do not edit manually)
### Usage in widgets
```dart
import 'package:timetrack/core/l10n/app_localizations.dart';
// ...
Text(AppLocalizations.of(context)!.timerStart)
```
## Strings to externalise (minimum set)
### Navigation
```json
"navTimer": "Timer",
"navEntries": "Entries",
"navProjects": "Projects",
"navReports": "Reports",
"navSettings": "Settings"
```
### Timer
```json
"timerStart": "Start",
"timerStop": "Stop",
"timerDiscard": "Discard",
"timerDiscardConfirm": "Discard this entry?",
"timerSelectProject": "Select project",
"timerAddNote": "Add a note…",
"timerTodayTotal": "Today: {duration}"
```
### Entries
```json
"entriesTitle": "Entries",
"entriesEmpty": "No entries yet",
"entriesAdd": "Add entry",
"entriesDeleteUndo": "Entry deleted",
"entriesUndo": "Undo"
```
### Projects
```json
"projectsTitle": "Projects",
"projectsEmpty": "No projects yet",
"projectsAdd": "Add project",
"projectsActive": "Active",
"projectsArchived": "Archived",
"projectsName": "Name",
"projectsDescription": "Description",
"projectsArchive": "Archive",
"projectsDeleteBlocked": "Cannot delete — project has entries"
```
### Reports
```json
"reportsTitle": "Reports",
"reportsDay": "Day",
"reportsWeek": "Week",
"reportsMonth": "Month",
"reportsTotal": "Total",
"reportsNoData": "No data for this period"
```
### Settings / Export
```json
"settingsTitle": "Settings",
"settingsTheme": "Theme",
"settingsThemeSystem": "System",
"settingsThemeLight": "Light",
"settingsThemeDark": "Dark",
"settingsLanguage": "Language",
"settingsExport": "Export data",
"exportFormat": "Format",
"exportRange": "Date range",
"exportShare": "Share"
```
### Common
```json
"cancel": "Cancel",
"save": "Save",
"delete": "Delete",
"edit": "Edit",
"confirm": "Confirm"
```
## Acceptance Criteria
- [ ] `l10n.yaml` present at project root
- [ ] `app_en.arb` contains all strings listed above
- [ ] `app_de.arb` contains all German translations (no English fallback strings)
- [ ] `flutter gen-l10n` (or `flutter pub get`) generates `app_localizations.dart`
- [ ] Zero hardcoded display strings in any `presentation/` file
- [ ] Switching language in Settings updates all visible strings immediately
- [ ] Widget test: locale override renders German strings
## Files to create
- `l10n.yaml`
- `lib/core/l10n/app_en.arb`
- `lib/core/l10n/app_de.arb`