localize transient messages and the download notification

Route user-facing messages produced below the UI through a typed UiMessage
(string-resource id plus format args) instead of pre-built English strings:
showMessage, SyncStatus.Failed, playback errors and download toasts now
resolve in the current locale at the UI edge. Subsonic and page-cap
exceptions carry a UiMessage alongside their developer message, and the
download progress notification is formatted from resources.

Internal invariants and log tags stay plain strings.
This commit is contained in:
austinried
2026-10-04 00:30:07 +00:00
parent a1e45380cc
commit 3162ac07d5
24 changed files with 165 additions and 61 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ Resource names are `snake_case`. They were derived once from the old Flutter ARB
Per-app language selection (Android 13+) is generated by AGP: `androidResources.generateLocaleConfig = true` with `res/resources.properties` supplying the default locale. `StringResourcesTest` guards the translations: every locale resource must exist in the default with the same kind and no placeholder the default lacks, which is what caught a duplicated `{value}` in the Thai ARB during migration.
Some text is still English-only: transient toasts and status strings produced below the UI (`showMessage` and `SyncStatus.Failed`), the download progress notification, playback error messages, and Subsonic parser exceptions. Persisted download failures are no longer free text: `SongDownload.error` is a `DownloadError` enum mapped to `@StringRes` and stored by name (unknown legacy values degrade to `DownloadError.Failed`), so `SongInfoDialog` resolves it in the current locale.
Text produced below the UI is typed, not free-form English. Repositories, `SyncManager` and playback report a `UiMessage` (a string-resource id plus format args) through `showMessage`, and the UI resolves it in the current locale; `SyncStatus.Failed` carries one too. Subsonic and playback failures set a localized `UiMessage` on the exception (the raw message stays as the developer detail/log text), and the download progress notification is formatted from resources. Persisted download failures are also typed: `SongDownload.error` is a `DownloadError` enum mapped to `@StringRes` and stored by name (unknown legacy values degrade to `DownloadError.Failed`), so `SongInfoDialog` resolves it in the current locale. The remaining non-localized strings are internal invariants and log tags that are never shown.
## Security and privacy