i18n(player): resolve PlayerViewModel messages in the composable - #641
Merged
ProdigyV21 merged 1 commit intoSep 4, 2026
Merged
Conversation
The player view model built its user-facing text itself: loading phases,
playback errors, the AI translation toast and every "Find best match"
status and result. A view model only holds the application context, whose
resources follow the system language rather than the language selected in
the app, so those strings ignored the in-app language even once they lived
in strings.xml.
The messages now travel through the UI state as a PlayerMessage - a string
resource id plus its format arguments - and PlayerScreen resolves them.
Nested messages are supported so the reference-source label ("Built-in" /
"Hearing") inside a match status is localized too. Same shape as
PluginMessage, with an extra Raw case for a platform exception message
that has no resource.
The playback error telemetry now records the stable resource entry name
instead of the displayed sentence, so error reports stay comparable
across languages.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018j1WJm8A8ZwaiUp6WmQ5qB
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Same approach as #632/#634, applied to the player's view-model messages — this
time following the pattern you added yourself in
4691412(PluginMessage+localizedText()), because these strings are built outside a composable.PlayerViewModelassembled its own user-facing text: the loading phases, theplayback errors, the AI-translation toast and every "Find best match" status and
result. A view model only holds the application context, whose resources follow
the system language rather than the language selected in the app, so those
messages ignored the in-app language — the six
context.getString(...)calls inthat file did, and the 34 remaining string literals could not be moved at all
without hitting the same problem.
PlayerUiStateasPlayerMessage(a@param:StringResid plus its format arguments) and
PlayerScreenresolves themvalues/strings.xmlin the player section, with Germanvalues in
values-de/strings.xmlcontext.getString(...)calls in the view model are gone (0 left)"Hearing") inside a match status is localized too
PlayerMessage.Rawcase carries a platform exception message, whichhas no resource — this keeps the existing behaviour of that one error path exactly
Why
Approved in Discord (28 Aug): "Yes try to also bring hardcoded things into this.
That has been kinda a long time bug. They dont have to be in English yea."
This benefits all 50 language folders, not just German — untranslated locales fall
back to English exactly as before.
Notes
an optional suffix (
" (auto-offset +2.0s)"," (best 87%)"), it became a secondfull-sentence resource instead of a concatenation, so translators get whole
sentences and word order can differ per language.
reportPlaybackErrornow records the stable resource entry name(
player_fail_render_failed) in telemetry instead of the displayed sentence, soerror reports stay comparable across languages.
"Built-in"/"Hearing"label used in theSubMatchlog line, and thelanguage names all stay English. Log and telemetry strings are out of scope.
in the app's language. Happy to add screenshots if useful.
./gradlew testSideloadDebugUnitTestin CI (compile + unit tests green).created by Claude (Anthropic) on behalf of @ReichiMD