From 286a431adf3cfc562580cb205b1bdc2c1a45257b Mon Sep 17 00:00:00 2001 From: Max Gramser Date: Sat, 19 Sep 2026 14:36:40 +0200 Subject: [PATCH] Explain how to check or add a language, and run the translation checks with the others Co-Authored-By: Claude Opus 5 --- README.md | 8 ++ docs/TRANSLATING.md | 177 ++++++++++++++++++++++++++++++++++---------- tools/check.sh | 4 + 3 files changed, 151 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index ef2928c..4b6e710 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,14 @@ https://github.com/user-attachments/assets/f9f6a933-d388-4c8b-9c9a-011dfa37617b

Other hardware, such as a different display controller? Every screen has an Override YAML of its own, checked by ESPHome before a build and kept through every update.

+## In your language + +The screens, the editor and the app speak English (US and UK), Dutch, German, French, Italian, Spanish, Portuguese and +Polish. ESP Screens takes Home Assistant's language and uses its words, so a door says what it says in the Home +Assistant app. Settings → Language & region picks another language, the clock and how numbers are written, for every +screen at once. Most languages still need someone who speaks them to check the texts: +[Translating ESP Screens](docs/TRANSLATING.md) says how, and how to add a language. + ## Alerts

diff --git a/docs/TRANSLATING.md b/docs/TRANSLATING.md index 775714c..8eae450 100644 --- a/docs/TRANSLATING.md +++ b/docs/TRANSLATING.md @@ -1,55 +1,156 @@ # Translating ESP Screens -Every text of ESP Screens lives in one file per language: `screen_manager/translations/.json`. The screens, the -app and the editor all read the same file. English (`en.json`) is the source: every other file has the same keys, and a -key a language doesn't have yet shows in English. +ESP Screens speaks every language it has a file for: the screens, the editor in Home Assistant and the messages of the +app. Each language is one JSON file in [`screen_manager/translations/`](../screen_manager/translations/). English +(`en.json`) is the source. Every other file has the same keys, and a text a language doesn't have yet shows in English, +so a language can grow bit by bit. -The code is the one Home Assistant uses for the language: `nl`, `de`, `fr`, `pt-BR`, `zh-Hans`. A screen takes Home -Assistant's language unless someone picks another one under Settings in ESP Screens; the editor follows the language of -your own Home Assistant profile. +You can help in two ways, and neither needs you to write code: -## The sections +- **Check a language** that is already there. Most were drafted by Claude and need someone who speaks the language. +- **Add a language** that isn't there yet. -| Section | Where it shows | Keep in mind | +## Where the texts show + +| Section | Where you see it | Keep in mind | | --- | --- | --- | -| `screen` | On the screen itself: built into its firmware when it is installed or updated | Small screens: keep it as short as the English. One language per screen, so this costs almost no room. | -| `addon` | Messages of the ESP Screens app, and the texts it sends to the screens | Error messages are whole sentences. | -| `editor` | The ESP Screens editor in Home Assistant | | -| `_meta` | The language itself | `name` in the language itself, `english` in English, `plural` (below), `checked` | +| `screen` | On the screens themselves | Screens are small, especially the CYD. Keep it as short as the English. A screen gets new texts with its next firmware update. | +| `addon` | Messages of the app, and texts it sends to the screens (tile names, the top bar) | Error messages are whole sentences. | +| `editor` | The ESP Screens editor in Home Assistant | Shows up as soon as the app is updated. | +| `_meta` | The language itself | See [The `_meta` block](#the-_meta-block). | -`screen.ha` holds Home Assistant's own words (on, off, open, heating, ...). They come from Home Assistant's translations -through `tools/i18n.py`; don't change them by hand, change them in Home Assistant's translations instead. -`screen.date` holds day and month names and date orders from the Unicode CLDR, the same data browsers use. +Three parts fill themselves. Don't change them by hand: + +- `screen.ha` holds Home Assistant's own words for states: on and off, open and closed, heating, the weather. + `tools/i18n.py ha-words` copies them from Home Assistant's translations, so a screen says exactly what the Home + Assistant app says. To improve one of these words, change it in + [Home Assistant's translations](https://developers.home-assistant.io/docs/translations/); we pick it up from there. +- `screen.date` holds day and month names and the order of a date. `screen.number` says how numbers are written. + `screen.time.am` and `.pm` are the day periods. All of this comes from the Unicode CLDR, the same data every browser + uses, through `tools/i18n.py cldr`. +- `_meta.clock`, 12 or 24 hours, also comes from the CLDR. + +## Check a language + +1. Open the file of your language, for example + [`nl.json`](../screen_manager/translations/nl.json), next to [`en.json`](../screen_manager/translations/en.json). + `_meta.checked` says whether someone checked it already. +2. Read it through. Look for three things: + - wrong words; + - words that differ from the ones the Home Assistant app uses in your language (the Home Assistant app is the + reference: *Dashboard*, *Automation*, *Entity* are what people know); + - texts that are too long for a small screen. +3. Look at it for real, if you can. In ESP Screens open **Settings → Language & region** and choose your language. The + editor itself follows the language of your Home Assistant profile. The screens show the new texts after their + firmware update. +4. Change what needs changing. When the whole file is checked, set `"checked": true` in `_meta`. +5. Send it in (see [Sending your work](#sending-your-work)). Say in the pull request which parts you checked. + +A partial check helps too. Say which sections you went through, and leave `checked` at `false`. + +## Add a language + +1. Pick the code Home Assistant uses for your language (`sv`, `da`, `cs`, `pt-BR`); ESP Screens follows Home Assistant's + language setting by that code. A variant such as `pt-BR` may be a small file with only the texts that differ from + `pt`. That is how `en-GB` works: it holds the 24-hour clock and British spelling, and the rest falls back to `en`. +2. Create the file. If you have Node.js and Python: + + ```bash + python3 tools/i18n.py new sv Svenska Swedish one_other + ``` + + This writes `sv.json` with its `_meta` and the calendar from the CLDR. The last word is the plural rule (see + [Plurals](#plurals)). Without these tools, copy `en.json`, keep only `_meta` and the texts you translate, and a + maintainer adds the calendar. +3. Translate. Keep the keys and the structure of `en.json`. Translate the text values only. Start with `screen`, which + is short and what people see every day, then `editor` and `addon`. +4. Check it: + + ```bash + python3 tools/i18n.py check + ``` + +5. Send it in. A maintainer fills `screen.ha` from Home Assistant (`tools/i18n.py ha-words`). + +### Which languages fit + +| Script | Languages | Screens | +| --- | --- | --- | +| Latin | English, Dutch, German, French, Italian, Spanish, Portuguese, Polish, Czech, the Nordic languages, Turkish, ... | Every screen: the fonts carry every letter European languages use | +| Cyrillic, Greek | Russian, Ukrainian, Bulgarian, Greek | Possible: those letters go only onto the screens that speak the language. Ask first: a maintainer adds them. | +| Chinese, Japanese, Korean | | Only on a Guition, with the characters the texts need; a CYD has too little room and shows English | +| Right-to-left, or letters that join | Arabic, Hebrew, Persian, Thai, Hindi | Not yet: the screens' graphics library doesn't write them without extra work | + +The editor and the app's messages work in any language, whatever the screens can draw. ## The format -- **Placeholders** such as `{n}` or `{name}` stay exactly as they are; move them where the sentence needs them. -- **Plurals** are the forms of a sentence separated by ` | `, in the order of the file's `_meta.plural` rule: +- **Placeholders** such as `{n}`, `{name}` or `{time}` stay exactly as they are. Move them to where your sentence needs + them: `"Last {time}"` can become `"Zuletzt {time}"` or `"{time} geleden"`. +- **Plurals** are the forms of one sentence, separated by ` | `, in the order of your language's rule: + `"1 hour ago | {n} hours ago"`. +- **Brand names stay:** ESP Screens, Home Assistant, ESPHome, Claude, Guition, CYD. +- **Keep the characters `{ } | @` out of ordinary text:** the editor reads them as instructions. +- **Match the tone:** short and plain, like the English. The screens and the editor talk to people at home, not to + engineers. - | Rule | Languages | Forms | - | --- | --- | --- | - | `one_other` | English, Dutch, German, Italian, Spanish, the Nordic languages | `1 hour ago \| {n} hours ago` | - | `one_upto_1` | French, Portuguese | the first form for 0 and 1 | - | `slavic_pl` | Polish | one \| few (2-4, 22-24, ...) \| many | - | `east_slavic` | Russian, Ukrainian | one \| few \| many | - | `none` | Chinese, Japanese, Korean | one form | +### Plurals -- Don't use `{`, `}`, `|` or `@` as ordinary characters. -- `_meta.checked` is `true` once someone who speaks the language has checked the whole file. The settings in ESP Screens - show a language that isn't checked yet with a request for help. +| Rule | Languages | Forms | +| --- | --- | --- | +| `one_other` | English, Dutch, German, Italian, Spanish, the Nordic languages | one \| other: `1 hour ago \| {n} hours ago` | +| `one_upto_1` | French, Portuguese | the first form for 0 and 1 | +| `slavic_pl` | Polish | one \| few (2-4, 22-24, ...) \| many | +| `east_slavic` | Russian, Ukrainian | one \| few \| many | +| `none` | Chinese, Japanese, Korean | one form | -## Letters the screens can draw +### The `_meta` block -The screens carry every letter European languages write with the Latin alphabet. A language in another script -(Cyrillic, Greek, Chinese) gets its letters added only on the screens that use it, and only where they fit: a CYD has -too little room for Chinese and shows English then. `tools/i18n.py check` says when a text uses a letter the screens -can't draw. +| Field | Meaning | +| --- | --- | +| `name` | The language in itself: `Nederlands`, `Deutsch` | +| `english` | The language in English | +| `script` | `latin`, `cyrillic`, `greek`, `han`, ... | +| `plural` | One of the plural rules above | +| `clock` | `12` or `24`: what *Automatic* means for the clock (from the CLDR) | +| `checked` | `true` once someone who speaks the language has checked the whole file | -## Checking your work +## Sending your work -```bash -python3 tools/i18n.py check -``` +- **On GitHub, without Git:** open the file on GitHub and press the pencil. GitHub makes a copy and a pull request for + you. +- **With Git:** fork the repository, change the file, run `python3 tools/i18n.py check`, open a pull request. +- **No GitHub account?** Open an issue or mail the file. We'll take it from there. -It lists missing keys, placeholders that differ from English, the wrong number of plural forms, letters the screens -can't draw, and screen texts that are much longer than the English. +Translations ship with the next release of ESP Screens: the editor and messages right away, the screens with their next +firmware update. + +## For maintainers + +- **A new English text:** + - Screen texts: add the key to `en.json` and run `python3 tools/i18n.py header`. That writes + `components/smart_display/screen_text_keys.h`, which the build checks against the JSON. The code uses + `screen_text::tr(txt::...)`. + - App texts: use `i18n.t(...)` (the editor's language) or `i18n.screen_t(...)` (the screens' language). + - Editor texts: go through vue-i18n. +- **Every release:** Claude drafts the new texts for every language, with Home Assistant's own words as the glossary, + and leaves them unchecked for a speaker of the language. A missing text shows in English and never blocks a release. +- **Before a release:** + - `python3 tools/i18n.py check`: keys, placeholders, plurals, letters the screens can't draw, long screen texts. + - `python3 tools/i18n.py lint`: English left in the firmware's code. What stays English on purpose is listed in + `LINT_KEEP`, with the reason. + - `python3 tools/i18n.py header --check`. +- **Refreshing the words from Home Assistant and the calendar:** + + ```bash + python3 tools/i18n.py ha-words --write + python3 tools/i18n.py cldr --write + ``` + + `ha-words` needs a Home Assistant: `HA_URL` and `HA_TOKEN` in the environment. +- **What stays English everywhere:** + - the names of the screens' own entities in Home Assistant (renaming one gives it a new entity id); + - log lines; + - the statuses the app reads from a screen; + - release notes; + - the Claude skill. diff --git a/tools/check.sh b/tools/check.sh index ecce5d3..71970c4 100755 --- a/tools/check.sh +++ b/tools/check.sh @@ -122,6 +122,9 @@ cpp_tests() { packages_current() { cd "$ROOT" && "$PYTHON" tools/check_packages.py; } icons_current() { cd "$ROOT" && "$PYTHON" tools/generate_icons.py --check; } +# The translations (app 0.2.90, docs/TRANSLATING.md): every language against English, the key header the firmware +# builds against, and no English left in the firmware's code. +translations_check() { cd "$ROOT" && "$PYTHON" tools/i18n.py check > "$WORK/i18n.txt" && "$PYTHON" tools/i18n.py header --check && "$PYTHON" tools/i18n.py lint; } editor_install() { cd "$ROOT/web" && npm ci --no-audit --no-fund; } editor_tests() { cd "$ROOT/web" && npm test; } editor_types() { cd "$ROOT/web" && npm run check; } @@ -258,6 +261,7 @@ if ((want_fast)); then run "C++ tests" cpp_tests run "Packages fit together" packages_current run "Icons match tile_icons.py" icons_current + run "Translations" translations_check run "Editor: npm ci" editor_install if ((last_ok)); then run "Editor: tests (Vitest)" editor_tests