Address notes: a label pasted into a sentence gives \"a address\", \"A Eircode\" and wrong agreement in translation #642

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

Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading how the address notes are built and rendering them with the plugin's own English, German, Portuguese, French and Polish catalogues compiled into a scratch folder.

The two notes the address rules produce are each one sentence with a slot, and the slot is filled at run time with a field label that has been lower-cased in Python. A noun dropped into a sentence cannot agree with it: the article is wrong in English for some labels, and in translation the gender, the case and the capital letter are wrong for most. This is the pattern #168 (closed) removed from a CV's heading, with the same two objections.

Checked again on 2026-10-01 against main at 0a5cad587: still present; plugins/postal_rules/ is unchanged.

  • Where:
    • plugins/postal_rules/__init__.py:131-147 (warnings_for): _("Post to %(country)s usually needs a %(part)s.") and _("A %(name)s in %(country)s usually looks like %(example)s."), filled with _lower(label_for(…)).
    • plugins/postal_rules/__init__.py:179-182 (_lower): lower-cases the translated label unless it is all capitals, contains " (", or is the literal Eircode.
    • plugins/postal_rules/__init__.py:173-176 (_country_name), which returns phones.country_name (core/phones.py:337-348): the English name, for every reader.
    • The catalogues had to choose one article: plugins/postal_rules/locale/de/LC_MESSAGES/django.po:73-74 has "eine %(part)s", locale/pt_PT/LC_MESSAGES/django.po:73-74 has "um %(part)s", locale/fr_FR/LC_MESSAGES/django.po:73-74 has "d'un %(part)s".
  • What happens: rendered with the snapshot's catalogues.
    • English: "Post to Germany usually needs a address." (no street line); "A Eircode in Ireland usually looks like D02 AF30."; "Post to United States usually needs a zip code." (the label is ZIP code); "A Postcode (CAP) in Italy usually looks like 00184."
    • German: "Post nach United States braucht üblicherweise eine ort." and "… eine bundesstaat." (der Ort, der Bundesstaat, and German nouns take a capital); "Post nach Germany braucht üblicherweise eine adresse."; "Eine zip-code in United States sieht üblicherweise aus wie 20500."
    • Portuguese: "O correio para Germany costuma precisar de um morada." and "… de um localidade." (both feminine).
    • French: "… a habituellement besoin d'un adresse.", "… d'un ville."
    • Polish: "Poczta do kraju United States zwykle potrzebuje miejscowość." (the verb takes the genitive), and the postcode note begins with a lower-case letter: "kod zip w kraju United States zwykle wygląda tak: 20500."
    • In every language the country is named in English inside the translated sentence. core/phones.py:32-37 keeps the names in English on purpose for the country list ("this is a list somebody scans for their own country"); that reason does not carry over to a sentence.
  • Where a person meets them: on the review page of a candidate-file import (resume/candidate.py:911), and on Your details under an address row (templates/partials/postal_addresses.html:99-100). On Your details the notes are computed in PostalAddressForm._post_clean (core/postal.py:226-235) and the view redirects after a successful save (accounts/views.py:177-189), so today they appear only when the page comes back with an error somewhere else. That is worth deciding at the same time: a note about a saved address that is never shown after saving is not doing its job.
  • Why it matters: the notes are the only thing this plugin says to a person. They read as broken text in English and as pasted-together text in every other language, and no catalogue can repair them, because the article and the label are chosen in different places.
  • Fix: stop composing.
    • Either one whole translatable sentence per label key, in a dictionary beside LABELS ("Post to %(country)s usually needs a postcode.", "… a state.", "An Eircode in %(country)s usually looks like %(example)s.", and so on; one short string for each label a note can name), or a form that needs no agreement and no change of case, such as "Usually expected for %(country)s: %(part)s" with the label as the catalogue wrote it.
    • Remove _lower.
    • Name the country in the reader's language where a sentence shows it.
    • #306 adds refusals with messages of their own beside these notes; the same rule should hold for them.

The review's issue on translated labels lower-cased in Python names _lower in one line; this issue is the full account for the address notes.

Done when

  • A test in tests/test_postal_rules.py asserts, with English active, that an address in Germany with no street line gives a note without "a address", and that a wrong Eircode gives a note without "A Eircode". It fails today.
  • A test in tests/test_postal_rules.py asserts that no msgid of the plugin puts a label placeholder after an article (a %(part)s, A %(name)s), and that postal_rules has no _lower.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading how the address notes are built and rendering them with the plugin's own English, German, Portuguese, French and Polish catalogues compiled into a scratch folder. The two notes the address rules produce are each one sentence with a slot, and the slot is filled at run time with a field label that has been lower-cased in Python. A noun dropped into a sentence cannot agree with it: the article is wrong in English for some labels, and in translation the gender, the case and the capital letter are wrong for most. This is the pattern #168 (closed) removed from a CV's heading, with the same two objections. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present; `plugins/postal_rules/` is unchanged. - **Where:** - `plugins/postal_rules/__init__.py:131-147` (`warnings_for`): `_("Post to %(country)s usually needs a %(part)s.")` and `_("A %(name)s in %(country)s usually looks like %(example)s.")`, filled with `_lower(label_for(…))`. - `plugins/postal_rules/__init__.py:179-182` (`_lower`): lower-cases the translated label unless it is all capitals, contains " (", or is the literal `Eircode`. - `plugins/postal_rules/__init__.py:173-176` (`_country_name`), which returns `phones.country_name` (`core/phones.py:337-348`): the English name, for every reader. - The catalogues had to choose one article: `plugins/postal_rules/locale/de/LC_MESSAGES/django.po:73-74` has "eine %(part)s", `locale/pt_PT/LC_MESSAGES/django.po:73-74` has "um %(part)s", `locale/fr_FR/LC_MESSAGES/django.po:73-74` has "d'un %(part)s". - **What happens:** rendered with the snapshot's catalogues. - English: "Post to Germany usually needs a address." (no street line); "A Eircode in Ireland usually looks like D02 AF30."; "Post to United States usually needs a zip code." (the label is *ZIP code*); "A Postcode (CAP) in Italy usually looks like 00184." - German: "Post nach United States braucht üblicherweise eine ort." and "… eine bundesstaat." (*der Ort*, *der Bundesstaat*, and German nouns take a capital); "Post nach Germany braucht üblicherweise eine adresse."; "Eine zip-code in United States sieht üblicherweise aus wie 20500." - Portuguese: "O correio para Germany costuma precisar de um morada." and "… de um localidade." (both feminine). - French: "… a habituellement besoin d'un adresse.", "… d'un ville." - Polish: "Poczta do kraju United States zwykle potrzebuje miejscowość." (the verb takes the genitive), and the postcode note begins with a lower-case letter: "kod zip w kraju United States zwykle wygląda tak: 20500." - In every language the country is named in English inside the translated sentence. `core/phones.py:32-37` keeps the names in English on purpose for the country list ("this is a list somebody scans for their own country"); that reason does not carry over to a sentence. - **Where a person meets them:** on the review page of a candidate-file import (`resume/candidate.py:911`), and on *Your details* under an address row (`templates/partials/postal_addresses.html:99-100`). On *Your details* the notes are computed in `PostalAddressForm._post_clean` (`core/postal.py:226-235`) and the view redirects after a successful save (`accounts/views.py:177-189`), so today they appear only when the page comes back with an error somewhere else. That is worth deciding at the same time: a note about a saved address that is never shown after saving is not doing its job. - **Why it matters:** the notes are the only thing this plugin says to a person. They read as broken text in English and as pasted-together text in every other language, and no catalogue can repair them, because the article and the label are chosen in different places. - **Fix:** stop composing. - Either one whole translatable sentence per label key, in a dictionary beside `LABELS` ("Post to %(country)s usually needs a postcode.", "… a state.", "An Eircode in %(country)s usually looks like %(example)s.", and so on; one short string for each label a note can name), or a form that needs no agreement and no change of case, such as "Usually expected for %(country)s: %(part)s" with the label as the catalogue wrote it. - Remove `_lower`. - Name the country in the reader's language where a sentence shows it. - #306 adds refusals with messages of their own beside these notes; the same rule should hold for them. The review's issue on translated labels lower-cased in Python names `_lower` in one line; this issue is the full account for the address notes. ## Done when - A test in `tests/test_postal_rules.py` asserts, with English active, that an address in Germany with no street line gives a note without "a address", and that a wrong Eircode gives a note without "A Eircode". It fails today. - A test in `tests/test_postal_rules.py` asserts that no msgid of the plugin puts a label placeholder after an article (`a %(part)s`, `A %(name)s`), and that `postal_rules` has no `_lower`.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:48:36 +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#642
No description provided.