The l10n system uses ARB files as the **single source of truth**. Generated `.dart` files are auto-derived and **must not be edited manually**.
### File Structure
```
apps/lib/l10n/
├── l10n.yaml # flutter gen-l10n configuration
├── app_zh.arb # Chinese (Simplified) source
├── app_zh_hant.arb # Chinese (Traditional) source
├── app_en.arb # English source
├── app_localizations.dart # GENERATED — do not edit
├── app_localizations_zh.dart # GENERATED — do not edit
├── app_localizations_zh_hant.dart # GENERATED — do not edit
└── app_localizations_en.dart # GENERATED — do not edit
```
### Adding or Modifying Translations
1.**Edit `.arb` files only** — never edit generated `.dart` files directly. Edits to `.dart` files will be overwritten on next `flutter gen-l10n`.
2. When adding a new translation key:
- Add it to all locale ARB files (`app_zh.arb`, `app_zh_hant.arb`, `app_en.arb`) with the same key.
- For pluralizable/interpolated strings, also add `@key` metadata blocks as shown in existing entries.
- Run `flutter gen-l10n` to regenerate all `.dart` files.
3. When adding a new locale:
- Create a new `app_<locale>.arb` file with `"@@locale": "<locale>"`.
- Add the locale to `l10n.yaml`'s `output-localization-file` / `supported-locales` if configured.
- Run `flutter gen-l10n`.
### Supported Locales
-`zh` — Chinese Simplified (default)
-`zh_Hant` — Chinese Traditional
-`en` — English
- Script-based locales in Flutter code must use `Locale.fromSubtags(...)`; do not use `Locale('zh', 'Hant')` (that treats `Hant` as countryCode, not scriptCode).
### Traditional Chinese Translation Principles
- **Canonical divination terms** (六爻、爻、动爻、世爻、应爻、五行旺衰、空亡、干支、月建等) remain in Traditional Chinese form — they are not Simplified-to-Traditional converted. These are the correct scholarly expressions in both variants.
- General UI copy uses standard Simplified↔Traditional conversion (e.g., 設置→設定、資訊→信息).
- Placeholder and variable text in ARB files must match exactly — `{name}` (single braces) and corresponding `@key.placeholders` metadata must stay in sync.
-`ToastType.info` should be minimized: do not show informational toast for normal success paths (e.g., login success). Prefer silent success unless user must take action.
- Lifecycle events are mandatory: `RUN_STARTED` and exactly one of `RUN_FINISHED` or `RUN_ERROR`.
- Current default text delivery is finalized `TEXT_MESSAGE_END` payloads; do not require token-level `TEXT_MESSAGE_CONTENT` unless backend protocol explicitly enables it.
## HTTP Error Parse Contract (Must)
- Frontend must parse backend errors as RFC7807: `type/title/status/detail/instance` + extension `code/params`.
- Error code registry single source of truth: `docs/protocols/common/http-error-codes.md`.
- Frontend mapping must be based on documented `code` only (`code -> l10n key`), not inferred from `detail` text.
- Any new/changed code requires protocol doc update first, then frontend mapping update.
- 401 invalidation must go through global callback chain; no feature-level token clearing or direct login navigation.
### Home Message Viewport
- Home message auto-scroll/anchor restore must be event-driven.
- Preserve viewport during history prepend and when user is reading above bottom.
### Cache / Repository
- Reads/writes that affect consistency must go through repository layer.
- Cache keys and invalidation policy belong to repository, not UI/Bloc.
- Shared cache infrastructure must live under `apps/lib/data/cache/`; feature modules must not duplicate low-level cache store logic.
- Shared cache infrastructure (`apps/lib/data/cache/`) must remain domain-agnostic: do not import `features/**` or business model DTOs there.
- Domain object serialization/deserialization belongs to repository/feature layer via local mappers/codecs; do not centralize feature-specific codecs in shared cache layer.
- Shared cache layer may only encode/decode primitives, collections, and cache metadata wrappers.
- Cache strategy default is `SWR + TTL + invalidation/reload`.
- Local partial cache patching is allowed only for simple single-entity updates with clear rollback paths; complex cross-list/cross-feature states must invalidate and refetch.
- Feature TTL policy must be defined in each feature repository; do not add centralized feature TTL registries in shared cache infra.
- Runtime cache is hybrid (`memory + local persistent`) managed by DI singletons; do not create per-screen/per-widget cache store instances.
- Cross-feature data access must go through app-level facade/usecase boundaries; do not import another feature's data implementation directly from UI/Bloc.
- Repository instances should be resolved from DI singletons to reuse cache and avoid per-feature re-creation.
### Reminder / Notification Rewrite Boundary
- Reminder/notification data-interaction logic is under rewrite. Do not reintroduce local-notification scheduling/callback execution paths in `apps/lib/data/services/`.
- During rewrite, keep protocol/orchestration in `core/notification/**` and reusable rendering in `shared/widgets/notification/**`.
## Testing Policy
- Prioritize tests for model parsing, service logic, and high-regression interaction flows.
- Simple static UI changes may skip tests.
- Auth/Home/Cache changes must include targeted regression tests.