Skip to content

UI: show the app in Spruce's language when a translation exists - #30

Merged
abalakh merged 1 commit into
spruceUI:masterfrom
abalakh:localization_support
Nov 1, 2026
Merged

abalakh merged 1 commit into
spruceUI:masterfrom
abalakh:localization_support

Conversation

@abalakh

@abalakh abalakh commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

Every user-facing string was English. Cheevos now reads Spruce's UI language from PyUI when a session starts and applies its translation from src/cheevos/res/lang/.json, named as PyUI names its own language files. Translations ship with Cheevos rather than in PyUI's lang/ files, so a release's string names and {fields} always match its translations. None ships yet, so English is unchanged.

  • Add ui/language.py: loads a translation over the English values in strings.py. A missing string stays English, and so does a value that wouldn't format like the English one (an unknown or missing field, another format spec, a stray brace, the wrong shape). Each is logged.
  • Add ui/plurals.py with CLDR's rules for the languages PyUI has. Strings that count by {count} are now Plural values, formatted with format.count(). POINT, AWARDS_EVENT, MORE_CONSOLE and EVENT_POINT became the "one" forms of their plurals, and {points}, {days} and {minutes} became {count}.
  • Make dates and numbers translatable: MONTHS, DATE, DATETIME, the separators, PERCENT, SIZE and SIZE_UNITS replace strftime's %b and hard-coded formats.
  • Read strings when the text is shown. The relative-time steps, the keyboard hints and the sync failure messages were read at import and would have stayed English. check_conventions.py now rejects that (CV007).
  • Break text without spaces (Chinese, Japanese) where the line ends. wrap() moves to ui/pyui/text.py. The achievement card's detail lines wrap instead of running off the screen.
  • Desktop: --lang, or UI_LANGUAGE= for make run and make screens, shows the app and PyUI's own text in that language, with screenshots in build/screens//. UI_LANGUAGE=Pseudo is a generated language (accented, longer, bracketed) that shows text that can't be translated or gets cut. make languages checks the translations and writes the English template to build/lang/English.json.
  • Docs: "Translating" in CONTRIBUTING.md, "Languages" in TESTING.md and .agents/product.md, code.md, pyui.md, AGENTS.md, and a Language section on the wiki's Themes and devices page. res/lang/README.md ships in the package, so someone who finds the folder in Spruce's App/Cheevos knows to send translations here.

English screens are pixel-identical to before. Counts now take their singular ("1 game", not "1 games"), and Home's game count gets a thousands separator.

Every user-facing string was English. Cheevos now reads Spruce's UI
language from PyUI when a session starts and applies its translation
from src/cheevos/res/lang/<Language>.json, named as PyUI names its own
language files. Translations ship with Cheevos rather than in PyUI's
lang/ files, so a release's string names and {fields} always match its
translations. None ships yet, so English is unchanged.

- Add ui/language.py: loads a translation over the English values in
  strings.py. A missing string stays English, and so does a value that
  wouldn't format like the English one (an unknown or missing field,
  another format spec, a stray brace, the wrong shape). Each is logged.
- Add ui/plurals.py with CLDR's rules for the languages PyUI has.
  Strings that count by {count} are now Plural values, formatted with
  format.count(). POINT, AWARDS_EVENT, MORE_CONSOLE and EVENT_POINT
  became the "one" forms of their plurals, and {points}, {days} and
  {minutes} became {count}.
- Make dates and numbers translatable: MONTHS, DATE, DATETIME, the
  separators, PERCENT, SIZE and SIZE_UNITS replace strftime's %b and
  hard-coded formats.
- Read strings when the text is shown. The relative-time steps, the
  keyboard hints and the sync failure messages were read at import
  and would have stayed English. check_conventions.py now rejects
  that (CV007).
- Break text without spaces (Chinese, Japanese) where the line ends.
  wrap() moves to ui/pyui/text.py. The achievement card's detail lines
  wrap instead of running off the screen.
- Desktop: --lang, or UI_LANGUAGE=<Language> for make run and make
  screens, shows the app and PyUI's own text in that language, with
  screenshots in build/screens/<Language>/. UI_LANGUAGE=Pseudo is a
  generated language (accented, longer, bracketed) that shows text
  that can't be translated or gets cut. make languages checks the
  translations and writes the English template to
  build/lang/English.json.
- Docs: "Translating" in CONTRIBUTING.md, "Languages" in TESTING.md
  and .agents/product.md, code.md, pyui.md, AGENTS.md, and a Language
  section on the wiki's Themes and devices page. res/lang/README.md
  ships in the package, so someone who finds the folder in Spruce's
  App/Cheevos knows to send translations here.

English screens are pixel-identical to before. Counts now take their
singular ("1 game", not "1 games"), and Home's game count gets a
thousands separator.
@abalakh
abalakh merged commit b6dbc0c into spruceUI:master Nov 1, 2026
4 checks passed
@abalakh
abalakh deleted the localization_support branch November 1, 2026 16:04
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