Repository navigation
i18n: English-first interface, plus CI/CD for Linux, Windows and Android - #1
Merged
Merged
Conversation
The repository was French throughout: UI strings, comments, errors, docs.
English is now the source language everywhere, French ships as a translation,
and no user-facing string is written inline anymore.
Go no longer sends display text across the Wails boundary. app.go emits
Message{Key, Args} values that the frontend renders from its own catalogue,
so a string lives in exactly one catalogue instead of being translated on
both sides where the two copies would drift apart. One side effect is worth
keeping: switching language re-renders the whole log retroactively, because
the lines were never text to begin with.
Three catalogues, split by which layer renders the text:
frontend/src/locales/*.json everything inside the window
internal/i18n/locales/*.json desktop notifications, peatsctl
android/.../values*/strings.xml the Android app
An argument value prefixed with "@:" is itself a catalogue key, which keeps a
nested reason translated inside a sentence Go assembled ("Reconnect 2/10:
control channel busy").
The desktop app picks the system language up, offers a picker in the top bar
and remembers the choice, then reports it to Go so a notification never
arrives in a different language from the window that triggered it. Android
follows the system language through resource qualifiers.
Documentation is English only, except README.fr.md. PROTOCOL.md is
deliberately not translated: duplicating a 20 kB reference means maintaining
two that eventually disagree.
Two things noticed on the way are fixed here as well: probe/main.go now
declares the //go:build linux constraint it always needed, and the Windows
transport no longer claims to be untested, having been validated on hardware.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI runs Go vet and tests on both Linux and Windows, because the two transports
share no code and a build error in one is invisible from the other, plus the
probe module, the frontend build and an Android debug build.
Three checkers keep the translation catalogues honest: missing keys, dead keys
and mismatched {placeholders} all fail the build. They already caught a
mis-sorted key while being written.
Releases are cut from a v* tag and produce, with SHA256SUMS:
Linux .deb, .tar.gz, peatsctl
Windows NSIS installer, portable .zip, peatsctl.exe
Android .apk, .aab
Version numbers derive from the tag everywhere, so nothing has to be edited by
hand at release time. Android signing is optional on purpose: with no secrets
configured the workflow still produces an unsigned APK rather than failing,
which keeps a fork able to run it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two CI failures, both structural rather than incidental. gofmt reported every Go file as unformatted on windows-latest and none on Linux: the runner checks out with autocrlf and gofmt wants LF. A .gitattributes pinning the tree to LF fixes that at the source instead of exempting the Windows job, and incidentally silences the CRLF warnings a Windows clone produces locally. Binding generation failed with "pattern all:frontend/dist: no matching files found". Wails loads the main package to extract the bindings before it compiles the frontend, so the embedded directory has to exist beforehand, which means wails build was already broken on any fresh clone rather than only in CI. frontend/dist/.gitkeep is now tracked, with a vite plugin putting it back after each build since vite empties outDir. Tracking it took untangling three overlapping ignore rules: peatsaudio/ excluded the directory outright, which stops git descending into it and makes any negation unreachable, and the release staging rule "dist/" was unanchored so it matched this path too. That fix also invalidated the documented claim that go vet ./... fails on a clean tree. It now only needs the GTK headers on Linux, for an unrelated cgo reason. The three affected documents are updated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Converts the whole project to an English-first interface translated at
runtime, and adds the CI/CD needed to ship it.
i18n
No user-facing string is written inline anymore. English is the source
language; French ships as a translation and falls back to English key by key,
so a partial translation degrades gracefully instead of showing raw
identifiers.
Go no longer sends display text across the Wails boundary.
app.goemitsMessage{Key, Args}values and the frontend renders them from its owncatalogue, so a string exists in exactly one place rather than being
translated on both sides where the copies would drift apart. A consequence
worth knowing: switching language re-renders the whole log retroactively,
because the lines were never text to begin with.
frontend/src/locales/*.jsoninternal/i18n/locales/*.jsonpeatsctl(58 keys)android/.../values*/strings.xmlThe Svelte i18n module is ~60 lines with no npm dependency. It supports linked
messages: an argument value prefixed with
@:is itself a catalogue key,which keeps a nested reason translated inside a sentence Go assembled
("Reconnect 2/10: control channel busy").
The desktop app detects the system language, offers a picker in the top bar,
remembers the choice and reports it to Go, so a notification never arrives in
a different language from the window that triggered it. Android follows the
system language through resource qualifiers.
Docs are English only, except
README.fr.md.PROTOCOL.mdis deliberatelynot translated: duplicating a 20 kB reference means maintaining two that
eventually disagree.
CI/CD
ci.yml— Go vet and tests on Linux and Windows (the two transports share nocode, so a build error in one is invisible from the other), the probe module,
catalogue consistency, the frontend build, and an Android debug build.
release.yml— cut from av*tag, produces.deb/.tar.gz/peatsctl,an NSIS installer / portable
.zip/peatsctl.exe, and.apk/.aab,with
SHA256SUMS. Versions derive from the tag everywhere. Android signing isoptional: with no secrets configured the workflow still produces an unsigned
APK rather than failing.
Three checkers keep the catalogues honest — missing keys, dead keys and
mismatched
{placeholders}all fail the build. They already caught amis-sorted key while being written.
Also fixed along the way
probe/main.gonow declares the//go:build linuxconstraint it alwaysneeded; without it the package failed to typecheck anywhere else.
hardware.
Verified locally
gofmt,go vet,go test, the three catalogue checkers, the frontendbuild, a full application build with embedded assets, and
peatsctl -lang frrendering its help in French. The Android build was not run locally (no SDK
here); instead every one of the 67
R.stringreferences was checked againstthe resources.
🤖 Generated with Claude Code