Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 KiB
Translating ESP Screens
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/. 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.
You can help in two ways, and neither needs you to write code:
- 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.
Where the texts show
| Section | Where you see it | Keep in mind |
|---|---|---|
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. |
Three parts fill themselves. Don't change them by hand:
screen.haholds Home Assistant's own words for states: on and off, open and closed, heating, the weather.tools/i18n.py ha-wordscopies 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; we pick it up from there.screen.dateholds day and month names and the order of a date.screen.numbersays how numbers are written.screen.time.amand.pmare the day periods. All of this comes from the Unicode CLDR, the same data every browser uses, throughtools/i18n.py cldr. One list is yours:screen.date.weekdays_min, the days of the weather card in two letters (di,lu,main French), because the small screen has room for no more.cldrstarts a new language with a guess and then leaves the list alone.screen.number.percentfollows Home Assistant's own rule: a space before%in Czech, German, Finnish, French, Slovak and Swedish, none in the other languages._meta.clock, 12 or 24 hours, also comes from the CLDR.
How the clock and numbers are written doesn't wait for a translation: screen_manager/app/regions.json holds them for
every language Home Assistant offers, also from the CLDR. A Swedish Home Assistant gets English texts on the screens until
there is a sv.json, but already the Swedish 24-hour clock and 1 234,5.
Check a language
- Open the file of your language, for example
nl.json, next toen.json._meta.checkedsays whether someone checked it already. - 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.
tools/i18n.py checkmeasures the line under a tile's name with the screens' own font (a{time}in it as a 12-hour clock, the widest a screen writes) and says when it doesn't fit; for the rest, compare with the English.screen.script.yesterday_time_shortis that line's short wording, which a tile falls back to whenyesterday_timedoesn't fit there: keep both the same where your word is short enough.
- 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.
- Change what needs changing. To find a word you saw, search for it in the file: the key it sits under says where it
shows (
screen,addon,editor), and the same key inen.jsonholds the English. A word underscreen.hais Home Assistant's own: change it in Home Assistant's translations instead, or the nexttools/i18n.py ha-wordsputs Home Assistant's word back. When the whole file is checked, set"checked": truein_meta. - Send it in (see 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
-
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 aspt-BRmay be a small file with only the texts that differ frompt. That is howen-GBworks: it holds the 24-hour clock and British spelling, and the rest falls back toen. -
Create the file. If you have Node.js and Python:
python3 tools/i18n.py new sv Svenska Swedish one_otherThis writes
sv.jsonwith its_metaand the calendar from the CLDR. The last word is the plural rule (see Plurals). Without these tools, copyen.json, keep only_metaand the texts you translate, and a maintainer adds the calendar. -
Translate. Keep the keys and the structure of
en.json. Translate the text values only. Start withscreen, which is short and what people see every day, theneditorandaddon. -
Check it:
python3 tools/i18n.py check -
Send it in. A maintainer fills
screen.hafrom 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},{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.
Plurals
| Rule | Languages | Forms |
|---|---|---|
one_other |
English, Dutch, German, Italian, Spanish, Portuguese (Portugal), the Nordic languages | one | other: 1 hour ago | {n} hours ago |
one_upto_1 |
French, Brazilian 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 |
The _meta block
| 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 |
Sending your work
- 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.
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.jsonand runpython3 tools/i18n.py header. That writescomponents/smart_display/screen_text_keys.h, which the build checks against the JSON. The code usesscreen_text::tr(txt::...). A number with a unit goes throughscreen_text::with_unit, a percentage throughscreen_text::percent, so the spacing is Home Assistant's. - App texts: use
i18n.t(...)for the editor's language, andi18n.screen_t(...)for the screens' language. - A text that is stored or made outside a request uses
i18n.english(...). That covers a delivery status and an update result.i18n.shown(...)puts it in the language of the editor that asks. Numbers and times for the screens go throughi18n.screen_number(...)andi18n.screen_clock(...), units throughi18n.unit_suffix(...). - A screen gets the app's words in the language its firmware speaks (its "Screen language" sensor), so a screen that
isn't updated yet stays in one language; firmware from before the languages gets English and its own letters.
Manager.sync_onesets that screen for the texts it writes (i18n.SCREEN). - Editor texts: go through vue-i18n.
- Screen texts: add the key to
-
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 inLINT_KEEP, with the reason.python3 tools/i18n.py header --check.
-
Refreshing the words from Home Assistant and the calendar:
python3 tools/i18n.py ha-words --write python3 tools/i18n.py cldr --writeha-wordsneeds a Home Assistant:HA_URLandHA_TOKENin the environment. When Home Assistant adds a language, add its code toHA_LANGUAGESintools/i18n.pyand runcldr --writefor its clock and numbers. -
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.