Skip to content

i18n(android): translate the Settings screen's hardcoded copy - #2498

Open
paradix86 wants to merge 2 commits into
ryanbr:mainfrom
paradix86:i18n/android-hardcoded-settings
Open

paradix86 wants to merge 2 commits into
ryanbr:mainfrom
paradix86:i18n/android-hardcoded-settings

Conversation

@paradix86

@paradix86 paradix86 commented Sep 26, 2026 •

Copy link
Copy Markdown

What

The Android Settings screen still showed about 90 English literals whatever the phone's language: card blurbs, button labels, toggle details, toasts, screen-reader text, the strap status pill and detail, the sex options, and the "SETTINGS" overline on every card. On an Italian phone, for example, the Profile card read "These power your heart-rate zones…", "Choose photo" and "Male / Female / Non-binary".

This PR moves them into string resources:

  • 96 new keys, translated into all nine locales (en, de, es, fr, it, pl, pt-PT, ru, zh).
  • 14 literals reuse an existing key with identical English, and therefore an existing translation: Add, Metric/Imperial, Male/Female, Connected, Bonded · streaming, Searching…, Garmin, Classic, and Settings.

Scope is the Settings screen only: SettingsScreen.kt, SettingsLogic.kt, SettingsComponents.kt. Other screens will follow as separate PRs, one concern each.

Notes

  • Testable helpers. strapStatusTitle / strapStatusDetail become strapStatusTitleRes / strapStatusDetailRes, returning @StringRes, following spo2MissingCaptionRes. uiString needs the Application, so returning text would make the branches untestable on the JVM. StrapStatusDetailTest keeps every wording assertion by resolving each id to its English value in values/strings.xml. It fails rather than skips if that file cannot be found.
  • SexOption carries a labelRes in place of a label.
  • Formatted strings use positional placeholders, e.g. Age, %1$s years, Step calibration, %1$.1f counter ticks per step. The HRV-window toast became two whole sentences instead of splicing "deep-sleep" / "whole-night" into English.
  • Left in English on purpose:
    • the "NOOP" wordmark;
    • the support email subject, which is read by the maintainer;
    • the four strings in the 5/MG card that is compiled out (if (false && showFiveMGControls)).
  • Consistency with existing locale terms. Translations reuse each locale file's established terms (Charge, Live, Lab Book, Test Centre, Re-scan, strap, …) and its register. For Russian, the new strings use уд/мин, ВСР and ЭКГ, as the rest of values-ru does.
  • i18n baseline. Tools/i18n_audit_baseline.json drops the 26 SettingsScreen.kt entries this extracts. It was edited narrowly rather than via --update-baseline, which on a Windows checkout would rewrite path separators and touch unrelated entries.

Out of scope, noticed along the way

  • The accent colour names (Mint, WHOOP Blue, Custom) come from PaletteTokens.kt and are still English.
  • Some existing translations are wrong, and new strings here do not repeat them. Examples: pl "Searching…" = "Badawczy…", pl "Cycle awareness" = "Świadomość rowerowa", pt-PT "Rescan" = "Digitalizar novamente".
  • In Appearance, long locale strings squeeze the "Clock" / "Theme" row labels to one letter per line (pre-existing layout).

Verification

  • Tools/i18n_audit.py --ci origin/main: Android OK. No new hardcoded literals; the tool counts 213 on main and 188 here. Every focus locale is complete.
  • Tools/doc_comment_lint.py: OK.
  • testFullDebugUnitTest: 6464 tests, StrapStatusDetailTest 4/4. The 9 failures are Windows-host-only (CRLF / file-lock) in GlowRingFlatArcTest, StrapLogArchiveTest and WhoopDatabaseUpgradeTest; none touches this change.
  • Emulator (Android 16, Full debug, app locale Italian): walked the whole Settings screen through the accessibility tree. The only English left is the accent names noted above. Segment pills fit, e.g. the sleep chart pill "Classico / Riempi / Garmin / Nastro". Screenshots below.
  • No BLE, analytics or schema change.

Related

Refs #2493 (Android: use profile weight from Health Connect). Both PRs edit the Profile card in SettingsScreen.kt and the nine strings.xml files, so whichever merges second will need a rebase. I will rebase this one onto the other, in either order.


Italian translations reviewed by a native Italian speaker (the author). The other languages follow each locale file's existing terminology; native review welcome.

Settings still rendered about 90 English literals from SettingsScreen.kt,
SettingsLogic.kt and SettingsComponents.kt regardless of locale: card
blurbs, button labels, toggle details, toasts, screen-reader text, the
strap status pill and detail, the sex options and the "Settings" overline.

They now resolve through string resources: 96 new keys, translated into
all nine locales, and 14 literals reuse existing keys with identical
English. strapStatusTitle/strapStatusDetail become strapStatusTitleRes/
strapStatusDetailRes returning @stringres, following spo2MissingCaptionRes,
so the branches stay testable on the JVM; StrapStatusDetailTest keeps its
wording checks by reading the English values from values/strings.xml.

Left in English on purpose: the "NOOP" wordmark, the support email
subject, and four strings inside the 5/MG card that is compiled out
(if (false && ...)).

The Android i18n baseline drops the 26 SettingsScreen.kt entries this
extracts.
…nglish

The Tanaka caption was left as 'Auto · %1$s bpm (Tanaka)' in de, es, fr, it,
pl and pt-PT, which the i18n echo ratchet counts as untranslated. Spell the
word out in each locale, agreeing with the heart-rate noun it qualifies.
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