Skip to content

Screen language & translations

The Tab5 screen speaks French (the source language), English, German, Dutch, Spanish, Italian or Turkish. Everything the screen shows or the tablet says follows the chosen language: popups, cards, dates, the alarm clock and its spoken reminders, and the eight games. Two exceptions: the quiz questions of Trial Poursuite stay French (more than 720 of them), and the console names (Fil d'Or, Roi Noir…) are proper names, kept as they are.

Every language was written by an AI, like the rest of the project. The author checked the French; the English, and the German, Dutch, Spanish, Italian and Turkish translations (made with Claude from the French and English texts) have not been reviewed yet. Corrections are welcome: an issue, or a pull request on Tab5/lang/en.yaml, de.yaml, nl.yaml, es.yaml, it.yaml or tr.yaml. The Home Assistant integration (HACS) speaks the same seven languages, from the server language: custom_components/tab5/translations/*.json, messages.py and the TEXTES / LIBELLES tables of assistant.py, translated the same way and not reviewed either.

Choosing the language

  • From Home Assistant: the tablet exposes a select entity « Langue » (Configuration). Pick Français, English, Deutsch, Nederlands, Español, Italiano or Türkçe: the tablet restarts and comes back in the new language. It remembers the choice.
  • Spoken sentences (alarm reminders, « shutter stopped ») follow the screen language, but the voice that reads them is the one of the tablet's voice pipeline in Home Assistant: give it a voice of the same language.
  • The Home Assistant dashboard written by custom_templates/tab5_dashboard.jinja (labels and explanations of the Tab5, Settings and Health views) follows the screen language too, when you write it again after changing the language (installation). Its German, Dutch, Spanish, Italian and Turkish texts were written by an AI too and have not been reviewed.
  • The tablet's entities in Home Assistant (its device page) keep their French names in every language: Home Assistant identifies an ESPHome entity by its name, so translating them would create new entities on every tablet already installed. The dashboard above shows the settings and sensors with labels in the screen language (settings).
  • Default of a first boot: tab5_langue: English in Tab5/user_entities.yaml (the native name of the language). Without that line, French.

What does not change: entity names, select options and the states Home Assistant reads (for example « Heure fixe », « Écran courant »). Renaming them would break your history and automations, so they stay as they are in every language. Since lot 4c, Home Assistant no longer sends sentences: it sends codes (rain level and start time, update and error counts…), and the tablet writes the sentence in its own language — « Averses dans 12 mn » or “Showers in 12 min”, counted down on the tablet's clock. Forecast day labels are translated when shown. What stays as HA sends it: your own data (calendar event titles, update names, sensor names).

How it works

It works like gettext: the French text written in the code is the key.

  • In C++ and YAML lambdas, a displayed text goes through tr("Calendrier"), which returns Calendar in English and the French text itself in French. In a language that is not complete yet, a missing text shows in English (French if English lacks it too): tools/gen_i18n.py writes that fallback into the generated tables.
  • Texts laid out by the YAML (text: "Calendrier") keep their French text; i18n_apply_boot() translates them once at the end of the setup, before the first frame.
  • A word with two meanings gets a context: tr_ctx("mardi", "M") → T, tr_ctx("mercredi", "M") → W, tr_ctx("echecs", "Dame") → Queen but tr_ctx("dames", "Dame") → King.
  • Word order that changes with the language goes through a template: tr_fill("{jour} {quantieme} {mois}", …) → {jour}, {mois} {quantieme} in English.
  • A text kept in a table (static const char* const kModes[] = {…}) is marked tr_noop("Joueur contre Tab") and translated where it is shown, tr(kModes[i]). tr_noop() translates nothing; it only tells tools/i18n_keys.py that the text is a key.

Each language is one file, Tab5/lang/<code>.yaml: a flat mapping "French text": "translation". tools/gen_i18n.py turns them into Tab5/socle/tab5_i18n_data.h (generated, committed).

Adding a language

  1. Copy Tab5/lang/en.yaml to Tab5/lang/<code>.yaml (for example pt.yaml).
  2. Change _langue (the native name, as shown in the select: Português), _code (pt) and _index (the next free number: the tablet stores the index, so existing languages never move). Remove _statut: complet until the translation is complete: missing texts then show in English, so a partial language is usable (English stays complete for that reason).
  3. Translate the right-hand side of each line. Keep the %d/%s in the same order and the {names} as they are.
  4. Add the native name at the end of the options: of the select « Langue » (Tab5/paquets/tab5-ha-controls.yaml).
  5. Run:
python tools/gen_i18n.py        # regenerates Tab5/socle/tab5_i18n_data.h
python tools/i18n_keys.py       # lists the texts still missing, per language
python -m pytest tests/test_i18n.py
  1. The Home Assistant dashboard (HomeAssistant_Config/custom_templates/tab5_dashboard.jinja) has its own table: add the language to code (top of the macro) and its translation to each entry of TRADUCTIONS (end of the file); tests/test_tableau_de_bord.py lists what is missing.

Characters: the screen fonts carry Latin-1, the Windows-1252 punctuation and the Turkish letters Ğ ğ İ ı Ş ş (&latin1 in Tab5/paquets/tab5-styles.yaml). That covers English, German, Spanish, Italian, Portuguese, Dutch, Turkish and the Nordic languages. Polish, Czech, Cyrillic or Greek need that glyph set extended first: it costs flash on every text font (the five Turkish letters added 2,464 bytes to the firmware); the names Home Assistant sends for the tiles are filtered to the same set (kHorsLatin1 in Tab5/ecran/tab5_tuiles.cpp, kept equal by tests/test_tuiles_firmware.py); tests/test_i18n.py refuses a translation whose characters the fonts don't have — they would show as empty boxes.

Rules for contributors

  • A new text on the screen is written in French in the code, wrapped in tr() (C++, lambdas) or laid out by the YAML, and gets its line in each complete language file. tests/test_i18n.py fails if a complete language (English, German, Dutch, Spanish, Italian, Turkish) misses it. Keep the literal on the same line as tr(: the key finder reads one line at a time.
  • The French text itself must use only characters the fonts carry: the tests check French too.
  • Never translate what Home Assistant reads: entity name:, select options, text-sensor states, payload codes (En_mouvement, Rouge…). A HA value shown on screen is translated at display time: tr(state.c_str()).
  • A key that no longer matches any text of the code fails the tests: change the key when you change the French text.