A CV's page says “What is on this cv”, and lowercases the noun in every language #168

Closed
opened 2026-09-10 11:16:29 +00:00 by tiagoagueda · 1 comment
Owner

Observation

Found while measuring a CV's page for #165. The heading above a CV's entries is built by putting the kind's label, lowercased, into a sentence:

{% blocktranslate trimmed with kind=cv.get_kind_display|lower %}
  What is on this {{ kind }}
{% endblocktranslate %}

(templates/documents/cv_detail.html, added with portfolios in #133, 29b85e0a.)

What it prints, on every CV's page:

Language Heading
English What is on this cv
German Was auf diesem lebenslauf steht
French Ce qui figure dans ce cv
Portuguese O que há neste cv
Greek Τι υπάρχει σε αυτό το βιογραφικό

What is wrong with it

  • |lower is English typography applied to every language. It flattens an acronym (CV) in English, French and Portuguese, and in German, where every noun is capitalised, it makes a spelling mistake.
  • A noun dropped into a sentence cannot, in general, agree with it. The translations work today because in the catalogues I checked the two kinds happen to take the same form of the words around them: German diesem fits both Lebenslauf and Portfolio, and French, Portuguese and Greek use the same article for both. A language where the two differ in gender or case cannot translate one sentence with a slot correctly for both kinds. That is not a failure yet, but it is why the pattern is worth removing rather than patching with a better filter.

What fixing it is

Two sentences, chosen by kind in the template:

{% if cv.kind == "portfolio" %}{% translate "What is on this portfolio" %}{% else %}{% translate "What is on this CV" %}{% endif %}

This retires What is on this %(kind)s and adds two strings to every catalogue, filled in the 39 European ones and flagged draft. Grep the templates for other get_…_display|lower inside a sentence while you are there.

Classification

Bug, internationalisation. Visible in English on every CV's page, so before 0.3.0 rather than after.

## Observation Found while measuring a CV's page for #165. The heading above a CV's entries is built by putting the kind's label, lowercased, into a sentence: ```django {% blocktranslate trimmed with kind=cv.get_kind_display|lower %} What is on this {{ kind }} {% endblocktranslate %} ``` (`templates/documents/cv_detail.html`, added with portfolios in #133, `29b85e0a`.) What it prints, on every CV's page: | Language | Heading | | --- | --- | | English | What is on this **cv** | | German | Was auf diesem **lebenslauf** steht | | French | Ce qui figure dans ce **cv** | | Portuguese | O que há neste **cv** | | Greek | Τι υπάρχει σε αυτό το βιογραφικό | ## What is wrong with it - **`|lower` is English typography applied to every language.** It flattens an acronym (*CV*) in English, French and Portuguese, and in German, where every noun is capitalised, it makes a spelling mistake. - **A noun dropped into a sentence cannot, in general, agree with it.** The translations work today because in the catalogues I checked the two kinds happen to take the same form of the words around them: German *diesem* fits both *Lebenslauf* and *Portfolio*, and French, Portuguese and Greek use the same article for both. A language where the two differ in gender or case cannot translate one sentence with a slot correctly for both kinds. That is not a failure yet, but it is why the pattern is worth removing rather than patching with a better filter. ## What fixing it is Two sentences, chosen by kind in the template: ```django {% if cv.kind == "portfolio" %}{% translate "What is on this portfolio" %}{% else %}{% translate "What is on this CV" %}{% endif %} ``` This retires `What is on this %(kind)s` and adds two strings to every catalogue, filled in the 39 European ones and flagged `draft`. Grep the templates for other `get_…_display|lower` inside a sentence while you are there. ## Classification Bug, internationalisation. Visible in English on every CV's page, so before 0.3.0 rather than after.
tiagoagueda added this to the 0.3.0 milestone 2026-09-10 11:16:29 +00:00
Author
Owner

Landed on main as 789f0d9d4, the way this issue proposed: two sentences chosen by
kind, What is on this CV and What is on this portfolio. The if is exact rather than a
guess -- CV.kind draws on CVKind, which has precisely those two values; the
plugin-extensible registry is for uploads and renders, not this model. Filled in French and
both Portuguese catalogues, flagged draft; the rest carry empty slots until the release
sweep. What is on this %(kind)s is retired.

The grep this issue asked for found the same |lower twice more, both fixed the same
way -- the label as the catalogue wrote it:

  • a salary's period on the application page, where Pro Jahr lowercased was a spelling
    mistake; the line reads 65,000 · Per year now, a middle dot instead of brackets so the
    capitalised label reads as a label;
  • a copy's status after a store's name (My shelf: Archived).

And a guard: tests/test_template_lint.py now fails any template that applies |lower to
a get_…_display, so this class of bug cannot return through a new template.

Landed on `main` as `789f0d9d4`, the way this issue proposed: two sentences chosen by kind, *What is on this CV* and *What is on this portfolio*. The `if` is exact rather than a guess -- `CV.kind` draws on `CVKind`, which has precisely those two values; the plugin-extensible registry is for uploads and renders, not this model. Filled in French and both Portuguese catalogues, flagged draft; the rest carry empty slots until the release sweep. `What is on this %(kind)s` is retired. **The grep this issue asked for found the same `|lower` twice more**, both fixed the same way -- the label as the catalogue wrote it: - a salary's period on the application page, where *Pro Jahr* lowercased was a spelling mistake; the line reads `65,000 · Per year` now, a middle dot instead of brackets so the capitalised label reads as a label; - a copy's status after a store's name (`My shelf: Archived`). And a guard: `tests/test_template_lint.py` now fails any template that applies `|lower` to a `get_…_display`, so this class of bug cannot return through a new template.
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#168
No description provided.