Files
homeassistant_espscreen/docs/TRANSLATING.md
T
2026-09-19 23:41:50 +02:00

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.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; 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. One list is yours: screen.date.weekdays_min, the days of the weather card in two letters (di, lu, ma in French), because the small screen has room for no more. cldr starts a new language with a guess and then leaves the list alone. screen.number.percent follows 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

  1. Open the file of your language, for example nl.json, next to 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. tools/i18n.py check measures 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_short is that line's short wording, which a tile falls back to when yesterday_time doesn't fit there: keep both the same where your word is short enough.
  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. 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 in en.json holds the English. A word under screen.ha is Home Assistant's own: change it in Home Assistant's translations instead, or the next tools/i18n.py ha-words puts Home Assistant's word back. When the whole file is checked, set "checked": true in _meta.
  5. 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

  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:

    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). 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:

    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}, {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.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::...). A number with a unit goes through screen_text::with_unit, a percentage through screen_text::percent, so the spacing is Home Assistant's.
    • App texts: use i18n.t(...) for the editor's language, and i18n.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 through i18n.screen_number(...) and i18n.screen_clock(...), units through i18n.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_one sets that screen for the texts it writes (i18n.SCREEN).
    • 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:

    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. When Home Assistant adds a language, add its code to HA_LANGUAGES in tools/i18n.py and run cldr --write for 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.