README: the languages as a table with their flags, generated from the language registry #937

Closed
opened 2026-10-16 13:43:26 +00:00 by tiagoagueda · 0 comments
Owner

The README's In your language section is a hand-kept bulleted list that has fallen behind the languages Postulo actually has. Make it a table with each language's flag, the same flags the app's language picker draws, and generate it from the language registry so it cannot fall behind again.

What exists today

  • The section. README.md, In your language, lists 38 languages as bullets: **own name** — one sentence saying what Postulo is, in that language. These are the EU's official languages and the rest of Europe.
  • Brazilian Portuguese is missing. The paragraph above the list says "Brazilian Portuguese beside the European", but the list has a single português.
  • Every language added since 0.4.0 is missing:
    • fr-CA, en-CA, es-MX;
    • zh-Hans, zh-Hant, ar, hi, bn, ur, id;
    • az, be, kk, cnr, nn, rm, fo (d70365523).
  • Nothing ties the list to the registry. The list is typed by hand, and nothing compares it with core/languages.py (NATIVE_NAMES) or with what is actually translated.

What would change

1. Each language with its flag

  • The app's SVG flags, not emoji flags. Emoji flags draw as the bare letters "FR" on Windows (#88). The SVGs in src/postulo/static/flags/ are what the language picker uses, and they render everywhere: <img src="src/postulo/static/flags/fr.svg" width="20" height="15" alt="">.
  • The same mapping as the app, FLAG_COUNTRIES. A language is not a country, and the mapping already says so:
    • regions: Catalan uses Catalonia's flag (ES-CT), Basque the Basque Country's (ES-PV), Welsh Wales's (GB-WLS);
    • regional variants: pt-BR / pt-PT, fr-FR / fr-CA and en-GB / en-CA each get their own country's flag;
    • no flag on purpose: the languages with none (ar, ee, ff, ha, ig, ln, om, ss, st, sw, ti, tn, yo) get an empty cell. "No flag beats a wrong flag."
  • The flag is decoration. It gets empty alt text, because the language's own name beside it is what is read.

2. A table instead of bullets

Language What Postulo is
(flag) français (France) Postulo est un gestionnaire de candidatures auto-hébergé : …
  • Columns: flag, the language's own name with its lang attribute where the renderer allows it, and the sentence.
  • Why a table: images line up in table cells, where they don't at the start of a bullet line.
  • Order: by the language's own name, as the picker sorts.

3. Generated, never hand-kept

  • A script writes the section. The script is scripts/readme_languages.py, or a messages.py subcommand. It writes the section between two marker comments, from:
    • NATIVE_NAMES and FLAG_COUNTRIES;
    • which languages are begun (translated at all, as status.json / languages.begun() decide). A scaffolded but empty catalogue is not listed.
    • for each language's sentence, a string in its catalogue (one msgid, translated in Weblate like everything else), so a new language arrives with its sentence. The current hand-written sentences become that string's first translations, entered in Weblate.
  • A test keeps it honest. It fails when the README's section differs from what the script would write, the same way extract --check keeps the catalogues current.
  • The prose follows the facts. The paragraph introducing the section stops naming groups of languages ("every official language of the European Union…") that go stale. It says instead how many languages Postulo offers and links to Weblate for the live progress (#936 proposes a translation badge for the same).

#88 (flags as SVG, not emoji pairs), #936 (README badges), #347 (each release's language list).

The README's *In your language* section is a hand-kept bulleted list that has fallen behind the languages Postulo actually has. Make it a table with each language's flag, the same flags the app's language picker draws, and generate it from the language registry so it cannot fall behind again. ## What exists today - **The section.** `README.md`, *In your language*, lists **38 languages** as bullets: `**own name** — one sentence saying what Postulo is, in that language`. These are the EU's official languages and the rest of Europe. - **Brazilian Portuguese is missing.** The paragraph above the list says "Brazilian Portuguese beside the European", but the list has a single **português**. - **Every language added since 0.4.0 is missing:** - fr-CA, en-CA, es-MX; - zh-Hans, zh-Hant, ar, hi, bn, ur, id; - az, be, kk, cnr, nn, rm, fo (`d70365523`). - **Nothing ties the list to the registry.** The list is typed by hand, and nothing compares it with `core/languages.py` (`NATIVE_NAMES`) or with what is actually translated. ## What would change ### 1. Each language with its flag - **The app's SVG flags, not emoji flags.** Emoji flags draw as the bare letters "FR" on Windows (#88). The SVGs in `src/postulo/static/flags/` are what the language picker uses, and they render everywhere: `<img src="src/postulo/static/flags/fr.svg" width="20" height="15" alt="">`. - **The same mapping as the app, `FLAG_COUNTRIES`.** A language is not a country, and the mapping already says so: - **regions:** Catalan uses Catalonia's flag (`ES-CT`), Basque the Basque Country's (`ES-PV`), Welsh Wales's (`GB-WLS`); - **regional variants:** pt-BR / pt-PT, fr-FR / fr-CA and en-GB / en-CA each get their own country's flag; - **no flag on purpose:** the languages with none (`ar`, `ee`, `ff`, `ha`, `ig`, `ln`, `om`, `ss`, `st`, `sw`, `ti`, `tn`, `yo`) get an empty cell. "No flag beats a wrong flag." - **The flag is decoration.** It gets empty alt text, because the language's own name beside it is what is read. ### 2. A table instead of bullets | | Language | What Postulo is | |---|---|---| | (flag) | **français (France)** | Postulo est un gestionnaire de candidatures auto-hébergé : … | - **Columns:** flag, the language's own name with its `lang` attribute where the renderer allows it, and the sentence. - **Why a table:** images line up in table cells, where they don't at the start of a bullet line. - **Order:** by the language's own name, as the picker sorts. ### 3. Generated, never hand-kept - **A script writes the section.** The script is `scripts/readme_languages.py`, or a `messages.py` subcommand. It writes the section between two marker comments, from: - `NATIVE_NAMES` and `FLAG_COUNTRIES`; - which languages are **begun** (translated at all, as `status.json` / `languages.begun()` decide). A scaffolded but empty catalogue is not listed. - for each language's sentence, a string in its catalogue (one msgid, translated in Weblate like everything else), so a new language arrives with its sentence. The current hand-written sentences become that string's first translations, entered in Weblate. - **A test keeps it honest.** It fails when the README's section differs from what the script would write, the same way `extract --check` keeps the catalogues current. - **The prose follows the facts.** The paragraph introducing the section stops naming groups of languages ("every official language of the European Union…") that go stale. It says instead how many languages Postulo offers and links to Weblate for the live progress (#936 proposes a translation badge for the same). ## Related #88 (flags as SVG, not emoji pairs), #936 (README badges), #347 (each release's language list).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#937
No description provided.