Explain how to check or add a language, and run the translation checks with the others

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-19 14:36:40 +02:00
parent 951dceebf9
commit 286a431adf
3 changed files with 151 additions and 38 deletions
+8
View File
@@ -136,6 +136,14 @@ https://github.com/user-attachments/assets/f9f6a933-d388-4c8b-9c9a-011dfa37617b
</p>
<p align="center"><sub>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.</sub></p>
## 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
<p align="center">
+139 -38
View File
@@ -1,55 +1,156 @@
# Translating ESP Screens
Every text of ESP Screens lives in one file per language: `screen_manager/translations/<code>.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.
+4
View File
@@ -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