mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 23:21:59 +01:00
localize user-facing text into string resources
Move every exposed UI string into res/values/strings.xml (+ plurals) and read it via stringResource/pluralStringResource or getString, with 27 locale files carried over from the Flutter app's Weblate translations. Only strings whose English is unchanged reuse an old translation; reworded ones get fresh keys. Persisted download failures become a DownloadError enum mapped to string resources (stored by name, unknown legacy values degrade to Failed), the per-app locale config is generated by AGP, and StringResourcesTest guards locale keys and placeholders.
This commit is contained in:
@@ -136,6 +136,18 @@ The two branches do not fold case identically: the trigram tokenizer lowercases
|
||||
|
||||
`SubsonicClient` speaks the Subsonic REST API over OkHttp. Auth is the token scheme (`t = md5(password + salt)`), salted freshly on every request including media URLs; plaintext `p=` is supported as a fallback for old servers. Responses are parsed as a stream with SAX (`SAXParserFactory`, hardened best-effort — Android's parser rejects some flags, so unsupported ones are ignored), so entities are mapped as elements close rather than through a DOM. The client rejects any document that is not a `<subsonic-response>` and classifies malformed or truncated bodies as a `SubsonicException`, so a captive portal or login page can never be mistaken for an empty library and wipe the local mirror.
|
||||
|
||||
## Internationalization
|
||||
|
||||
All user-facing text lives in Android string resources: `res/values/strings.xml` (the English source, including `<plurals>`) and `res/values-*/strings.xml` for translations. This is the platform-native mechanism, needs no extra dependency, and is a first-class Weblate format ("Android String Resource": monolingual base `res/values/strings.xml`, file mask `res/values-*/strings.xml`, plurals supported). Code reads it through `stringResource`/`pluralStringResource` in Compose and `getString`/`getQuantityString` elsewhere.
|
||||
|
||||
Resource names are `snake_case`. They were derived once from the old Flutter ARB keys: resources whose English matched an old string (the "identical" set) reuse the old key's translations, mechanically renamed (`settingsServersFieldsName` -> `settings_servers_fields_name`); everything else is a new key. Strings whose wording changed were deliberately given new keys rather than reusing a translation with stale meaning. The migration is one-time; there is no generator in the build.
|
||||
|
||||
27 locales were carried over from the Flutter app: `ar, ca, cs, da, de, es, eu, fr, gl, hu, it, ja, ko, nb, pa, pl, pt, pt-BR, ru, sv, ta, th, tr, uk, vi, zh, zh-Hant` (PR #178 plus `ar/ca/cs/pa/pt` from the frozen Flutter branches). Locale files contain only translated keys; anything missing falls back to English. Chinese uses script qualifiers (`values-b+zh+Hans`, `values-b+zh+Hant`) and Brazilian Portuguese is `values-b+pt+BR`.
|
||||
|
||||
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.
|
||||
|
||||
## Security and privacy
|
||||
|
||||
No analytics or third-party telemetry. Credentials are stored locally in app data and are only ever sent to the configured server. Cleartext HTTP is permitted because self-hosted servers often run on a LAN; users can still configure HTTPS.
|
||||
|
||||
Reference in New Issue
Block a user