Skip to content

Weblate update with new translations and crash fix - #1047

Merged
davecraig merged 49 commits into
Scottish-Tech-Army:mainfrom
davecraig:main
Aug 28, 2026
Merged

Weblate update with new translations and crash fix#1047
davecraig merged 49 commits into
Scottish-Tech-Army:mainfrom
davecraig:main

Conversation

@davecraig

Copy link
Copy Markdown
Contributor

No description provided.

Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/arz/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/da/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/de/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/el/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/en_GB/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/es/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/et/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/fa/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/fi/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/fr_CA/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/fr/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/hi/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/is/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/it/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ja/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/nb_NO/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/nl/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/pl/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/pt_BR/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/pt/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ro/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ru/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/sv/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/tr/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/uk/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/zh_Hans/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/bn/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/vi/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/sw/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ur/
davecraig and others added 19 commits August 28, 2026 15:03
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ha/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/id/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/te/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/hu/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/cs/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/sk/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/sr/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/hr/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ar/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/mr/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ta/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ko/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/th/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/sl/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/bg/
Currently translated at 100.0% (1429 of 1429 strings)

Translation: Soundscape Android/AndroidKMP
Translate-URL: https://hosted.weblate.org/projects/soundscape-android/androidkmp/ca/
Tapping the info button on the home screen's route player killed the app:

  java.lang.IllegalArgumentException: Navigation destination that matches route
  route_details_screen/0 cannot be found in the navigation graph

The button navigated to "route_details_screen/<routeId>", but there is no such
destination. The graph registers a bare "route_details_screen" and passes the
route through the NavigationStateHolder, keyed by back stack entry, which is how
every per-entry payload in this graph travels - see the comment on SharedRoutes.
The route details screen reads its route from navStateHolder.selectedLocationFor,
so the id in the path was never going to be looked at even had the destination
matched.

The button now hands over a LocationDescription for the playing route and the
graph navigates with navigateWithLocation, exactly as onSelectLocation next to it
already does. The description is built the way RoutesViewModel builds one, first
waypoint standing in for the route's location, so the details screen sees the
same shape whether it was reached from the home screen or the routes list.

Every other route in the graph checks out. HELP is the only other destination
taking a path argument and it is registered as "help_screen/{topic}", with both
call sites building a single path segment. Both onboarding graphs have nothing
navigated-but-unregistered. SharedRoutes.LANGUAGE is neither registered nor
navigated to, so it can't crash, but it is the same trap armed for whoever wires
it up - left alone here rather than widening this fix. The root cause is that
onNavigate takes a free-form String, so a destination that doesn't exist is a
runtime crash rather than a compile error.

The regression test drives the button and asserts the route is handed over rather
than turned into a route string; it fails against the old code with
"expected:<7> but was:<null>" rather than merely passing against the new.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Ecp7eBi3ozoQqzk5H8v5n
SharedRoutes.LANGUAGE ("language_screen") had no composable registered for it in
the shared graph and nothing ever navigated to it, on either platform. It
couldn't crash as it stood, but it was the same trap that
"route_details_screen/<id>" fell into one commit ago: a route constant that looks
like a destination, and isn't. Language selection is reached through
OnboardingRoutes.LANGUAGE ("onboarding_language"), which is a different constant
and is registered and in use.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Ecp7eBi3ozoQqzk5H8v5n
Every change here comes from a way the last run of this skill went wrong.

Weblate throttled a whole-component fetch and 23 of 46 languages failed. The
output directory still held files from a previous run, and a stale cache file
is indistinguishable from a fresh one, so those languages were translated
against a stale list of which strings were untranslated. Nothing caught it
until the keys were compared by hand at the end. fetch now deletes its outputs
before fetching rather than overwriting them at the end, so a failure leaves
nothing behind to be mistaken for current data, names the languages that
failed, and exits non-zero.

Uploads land as live translations with no suggestion or review queue, so there
is no undo and nothing was checking them. A new validate subcommand, which
upload also runs itself, rejects a file whose keys aren't actually untranslated
(which is what a stale cache looks like, and would have caught the above on its
own), whose placeholders don't match the source in count, which invents a
placeholder the source doesn't have, or which is empty. upload --all validates
every language before uploading any of them, so a batch that is going to be
rejected halfway doesn't publish its first half.

Validation distinguishes errors from notes because weblate-add-language reuses
this script to upload a new language in ~50 batches: an unknown key or a broken
placeholder blocks the upload, but untranslated keys simply absent from the
file are a note, since a partial batch is a normal way to work. Pass
--require-complete when a file is meant to cover the whole language.

Requests now retry with backoff on throttling and transient server errors, and
fetch/upload --all pace themselves between languages; auth failures are not
retried, since four backoffs only obscure them. The defaults are empirical -
back to back fails roughly 40 of 46 languages, ~10s between them fails none.
--all exists mainly so that nobody hand-rolls a shell loop around fetch, which
is exactly what hid the original failures.

Also fixes an upload bug found while adding the retry: the file handle was
opened once outside the request, so a retried upload would have posted a spent
handle and uploaded zero bytes.

Finally, SKILL.md now records the approach that made the last run come out
well: anchor each new string to the sibling strings already approved in that
language rather than translating from English cold. That is what keeps a
"%1$s, %2$s" joiner rendering with Arabic "،", Japanese "、" and Chinese ","
instead of an ASCII comma, and what tells you to restructure for head-final
languages rather than swapping words in place.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Ecp7eBi3ozoQqzk5H8v5n
@davecraig
davecraig merged commit 5f64547 into Scottish-Tech-Army:main Aug 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant