Add opt-in i18n foundation for apps (Language setting + injected helpers) - #56
Open
avandeputte wants to merge 2 commits into
Open
Add opt-in i18n foundation for apps (Language setting + injected helpers)#56avandeputte wants to merge 2 commits into
avandeputte wants to merge 2 commits into
Conversation
…ers) Adds an opt-in internationalization foundation that apps can adopt without breaking the existing app contract: - server/i18n.py + server/i18n_data.json: logic/data split. Translations are grouped by semantic topic domain (gettext msgctxt model) so homographs stay distinct (weather HIGH vs tides HIGH). ~34 languages, incl. regional variants that inherit their base language. Each key carries a translator 'context' note. - server/location.py + server/weather.py: one shared geocoder, babel-backed currency/country (no hardcoded tables), 10-minute TTL-cached weather. - Runtime injection: get_plugin_pages inspects fetch()'s signature and passes i18n / get_weather / get_location only when the app declares them. Classic 4-arg apps are completely untouched. - Settings: an 'Enable internationalization' master toggle (DEFAULT OFF) gates the Language selector and the app badge. With it off the UI and behaviour are identical to today -- the toggle carries a disclaimer that it needs modules on Universal Firmware with configurable character maps. - babel is a soft dependency; i18n.py falls back to English without it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The gateway receive path decoded/re-encoded frames as UTF-8 with
errors=ignore, which silently dropped lone high bytes (0x80-0xFF). That
corrupted a module's A-command character-map sync for any reel set with
extended (international) glyphs. Decode and re-encode with latin-1 instead
-- a transparent byte<->code-point codec -- so the raw cp1252 bytes survive
to the downstream .decode('cp1252'). Adds a regression test.
Co-Authored-By: Claude Opus 4.8 (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.
Summary
Adds an opt-in internationalization foundation so apps can render in the user's language — without changing the contract for any existing app.
The whole feature sits behind a new "Enable internationalization" master toggle, which defaults to OFF. With it off, the UI and behaviour are identical to today.
What's in it
server/i18n.py+server/i18n_data.json— a logic/data split so translations live in data, not code. Strings are grouped by semantic topic domain (the gettextmsgctxtmodel), which keeps homographs distinct (weatherHIGHvs tidesHIGH;Mas minutes vs metres). ~34 languages including regional variants (pt-BR, es-MX, fr-CA…) that inherit their base language's translations. Every key carries acontextnote for translators.server/location.py+server/weather.py— one shared geocoder, babel-backed currency/country lookup (no hardcoded tables), and a 10-minute TTL cache on weather so the helper can't be called excessively.get_plugin_pages()inspectsfetch()'s signature and passesi18n/get_weather/get_locationonly when the app declares them. Classic 4-arg apps are completely untouched.errors="ignore", which silently dropped lone high bytes (0x80–0xFF). That corrupted a module'sA-command character-map sync for any reel set containing extended glyphs. It now useslatin-1, a transparent byte↔code-point codec, so the raw cp1252 bytes survive to the downstream.decode('cp1252'). This is a standalone bug fix and can be cherry-picked separately if you'd prefer.Compatibility
babelis a soft dependency;i18n.pyfalls back to English/strftimewithout it.Testing
tests/test_i18n.pyandtests/test_gateway_transport.py.The apps that adopt this foundation are in a follow-up PR.
🤖 Generated with Claude Code