Report: in Greek, Ukrainian and five other languages both tallies get the id tally- and share one name #629

Closed
opened 2026-10-01 10:48:30 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading the report templates and running Django's slugify over the translated headings in every catalogue.

Checked again on 2026-10-01 against main at 0a5cad587: still present.

The two tallies on the job-search report build their ids from the translated heading through slugify, which drops every character outside ASCII. Where both headings are written in another script, both sections get the same empty-suffixed id, and the second region is named by the first one's heading.

  • Where: templates/applications/partials/report_tally.html:9-10 (aria-labelledby="tally-{{ heading|slugify }}" and id="tally-{{ heading|slugify }}"), included twice from templates/applications/report.html:188-192 with the translated "Where they were found" and "What kind of employer".
  • What happens: slugify is called without allow_unicode, so slugify("Πού βρέθηκαν") and slugify("Τι είδους εργοδότης") are both "". Of the 39 catalogues that translate both headings today, seven collide: Bulgarian, Greek, Armenian, Georgian, Macedonian, Serbian and Ukrainian. Each language added in another script will join them. Both <h2> elements get id="tally-"; both sections point aria-labelledby at it, which resolves to the first, so a screen reader lists two regions called "Where they were found" and announces the employer tally under the sources heading.
  • Why it matters: region names are how a screen-reader user moves around the report; one of them is wrong, and the page has duplicate ids, in exactly the languages the project is adding next.
  • Fix: pass a fixed, untranslated key from report.html (key="sources", key="industries") and build both attributes from it, id="tally-{{ key }}". Never derive an id from translated text; a template lint that rejects |slugify inside an id= attribute would keep it that way.

Done when

  • A render test in tests/test_assistive_names.py includes report_tally.html twice with two headings written in Greek and asserts the two id values differ and each section's aria-labelledby names its own heading.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading the report templates and running Django's `slugify` over the translated headings in every catalogue. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The two tallies on the job-search report build their ids from the translated heading through `slugify`, which drops every character outside ASCII. Where both headings are written in another script, both sections get the same empty-suffixed id, and the second region is named by the first one's heading. - **Where:** `templates/applications/partials/report_tally.html:9-10` (`aria-labelledby="tally-{{ heading|slugify }}"` and `id="tally-{{ heading|slugify }}"`), included twice from `templates/applications/report.html:188-192` with the translated "Where they were found" and "What kind of employer". - **What happens:** `slugify` is called without `allow_unicode`, so `slugify("Πού βρέθηκαν")` and `slugify("Τι είδους εργοδότης")` are both `""`. Of the 39 catalogues that translate both headings today, seven collide: Bulgarian, Greek, Armenian, Georgian, Macedonian, Serbian and Ukrainian. Each language added in another script will join them. Both `<h2>` elements get `id="tally-"`; both sections point `aria-labelledby` at it, which resolves to the first, so a screen reader lists two regions called "Where they were found" and announces the employer tally under the sources heading. - **Why it matters:** region names are how a screen-reader user moves around the report; one of them is wrong, and the page has duplicate ids, in exactly the languages the project is adding next. - **Fix:** pass a fixed, untranslated key from `report.html` (`key="sources"`, `key="industries"`) and build both attributes from it, `id="tally-{{ key }}"`. Never derive an id from translated text; a template lint that rejects `|slugify` inside an `id=` attribute would keep it that way. ## Done when - A render test in `tests/test_assistive_names.py` includes `report_tally.html` twice with two headings written in Greek and asserts the two `id` values differ and each section's `aria-labelledby` names its own heading.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:48:30 +00:00
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#629
No description provided.