Notation like Home Assistant, each screen in its own language, and the language in every build
From the end-to-end test on the bench boards and an independent review: - Units spaced as Home Assistant does (54% / 54 % in German and French, 18°, 21.5 °C), in the firmware and the app. - Grouping from five digits where the language does (1234 but 12.345 in Spanish, Polish, Portuguese): the layout message carries group_min and percent_space; an unknown number style no longer refuses a layout. - Automatic follows Home Assistant's own language for the clock and numbers, also without a translation (Swedish: 24 hours, 1 234,5; pt-BR: 1.234,5): regions.json from the CLDR for all 63 languages Home Assistant offers. - 12-hour clock: the top bar says 3:48 PM, the clock card 3:48 (not 03:48), Last runs follow the clock. - The climate setpoint font has the decimal comma; the value fonts have ², ³ and µ (m³ was a box). - Weather days: at most three letters without the dot (mié, sáb, czw); the screen took three bytes. - Texts fall back per key through the base language (pt-BR -> pt -> en) in the firmware and the app. - Each screen gets the app's words in the language its firmware speaks; firmware from before the languages gets English and its own letters, not boxes. - set_language re-reads what it writes (indentation, comments, quoted keys, CRLF, !include) and every build writes the language first; the 24-hour pin no longer hits a fresh install and waits for the old clock switches. - Tests: region and notation, plural parity with the C++ rules, set_language edge cases, the pin, PUT /api/language. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -94,19 +94,29 @@ def cpp_string(text):
|
||||
return '"' + ''.join(out) + '"'
|
||||
|
||||
|
||||
def chain(language, folder=TRANSLATIONS):
|
||||
"""The files a language's texts come from, most specific first: pt-BR, then pt, then English."""
|
||||
found = [language]
|
||||
base = language.split('-')[0]
|
||||
if base != language and load(base, folder) is not None:
|
||||
found.append(base)
|
||||
return found + ([] if 'en' in found else ['en'])
|
||||
|
||||
|
||||
def table(code, folder=TRANSLATIONS):
|
||||
"""(language, keys, texts, plural rule) of a build: every English key, in its language where it has one."""
|
||||
"""(language, keys, texts, plural rule) of a build: every English key, in its language where it has one, else in its
|
||||
base language (a small pt-BR file takes the rest from pt), else in English."""
|
||||
english = load('en', folder)
|
||||
language = resolve(code, folder)
|
||||
own = dict(screen_pairs(load(language, folder))) if language != 'en' else {}
|
||||
files = [load(name, folder) or {} for name in chain(language, folder)]
|
||||
texts_of = [dict(screen_pairs(data)) for data in files]
|
||||
keys, texts = [], []
|
||||
for key, text in screen_pairs(english):
|
||||
keys.append(key)
|
||||
translated = own.get(key)
|
||||
# Only an empty text is missing: a separator of one space (French thousands) is a text.
|
||||
texts.append(translated if isinstance(translated, str) and translated != '' else text)
|
||||
meta = (load(language, folder) or {}).get('_meta', {})
|
||||
rule = meta.get('plural') if meta.get('plural') in PLURAL_RULES else 'one_other'
|
||||
texts.append(next((own[key] for own in texts_of if isinstance(own.get(key), str) and own[key] != ''), text))
|
||||
plural = next((data.get('_meta', {}).get('plural') for data in files if data.get('_meta', {}).get('plural')), None)
|
||||
rule = plural if plural in PLURAL_RULES else 'one_other'
|
||||
return language, keys, texts, rule
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user