Your details: form of address, pronouns and gender carried to their equivalent when the language changes, and kept under Other where there is none #921

Closed
opened 2026-10-15 17:19:42 +00:00 by tiagoagueda · 1 comment
Owner

On Your details, when the language the lists are offered in changes, a chosen form of address, pronoun set or gender becomes its equivalent in the new language (he/him becomes il going from English to French). A value with no equivalent is kept as it is under Other…, not dropped or switched to something else.

What exists today

  • accounts/addressing.py holds three lists per language (en, fr, pt-PT, pt-BR): FORMS_OF_ADDRESS, PRONOUNS and GENDERS. The module says they "are data, not translations" and that what is stored is the text itself, never a key ("Dr.ª" and not "pt-PT:3"), so a value survives a change of language.
  • Which list is offered: addressing.language_of(profile) returns the career record's language (record_language) and, when that is blank, the interface language of the request. Changing the interface language changes the lists only when the record has no language of its own.
  • What happens on a change today (accounts/forms.py, ProfileForm._offer): the stored text is compared with the new list. If it is not in it, the menu shows Other… and the box beside it holds the old text (self.initial[name] = addressing.OTHER, initial[f"{name}_other"] = stored). So after switching English → French, he/him is shown as Other…: he/him. Nothing maps it to il, and nothing is lost. Saving the page stores he/him again. A CV prints the stored text whatever its language.
  • A precedent for mapping words: LEGACY_GENDERS and current_gender_word (#864) replace an old list word with the new one in the migration, the importer and the candidate reader.

What would change

  • An equivalence table in addressing.py: a language-neutral concept for each list entry, with that concept's word in each language.
    • Pronouns and genders line up one to one in the four languages (she / he / they: she/her, elle, ela/dela; he/him, il, ele/dele; they/them, iel, elu/delu. Female / Male / Non-binary likewise).
    • Forms of address do not. Possible pairs: Mr = M. = Sr.; Mrs and Ms = Mme = Sr.ª (pt-PT) / Sra. (pt-BR); Prof. = Pr = Prof. / Prof.ª; Dr = Dr = Dr. / Dr.ª. No equivalent: Miss, Mx, Me, Eng., Eng.ª. Portuguese marks gender where English and French Dr and Prof. do not, so those only map from Portuguese, not to it. Portuguese Dr. is also a courtesy for any graduate, not English Dr. Each pair needs a reason written beside it, as the module's sources are.
  • When the lists are drawn (_offer), a stored value that is another language's word for a concept with a word in this language selects that word in the menu. One with no equivalent stays under Other… with its text, as today.
  • What is stored, two options:
    1. Map on save. The menu shows the equivalent, and saving stores the new language's text. Simple, and keeps "the text itself" as the stored value. But a CV in the old language then prints the new word.
    2. Store the concept, print per document. Store a concept key where the value is a list word, and the text only for Other…. A CV prints the word in its own language. This reverses the module's "never a key" rule and touches the archive format, the API schema, the vCard mapping (#660) and the importers.
  • Never set one field from another: gender never decides pronouns, and the reverse (#681's promise). This mapping works only within one field.

Notes

  • This is i18n data, not catalogue text: the words stay in addressing.py and are not translated through Weblate. Any new sentence (for example one saying a value was carried over from another language) is a catalogue string.
  • Tests: switch record_language and the interface language, check each list for each pair, check that a value with no equivalent survives under Other…, and check a bound form that comes back with an error (_offer's "a page that comes back keeps what it was sent").

To decide

  • Option 1 or 2.
  • Whether the mapping applies when the career record's language changes, or only when the interface's does. Today the record's language decides the lists.

Related: #309, #681, #864.

Checked against main at 56fc9d531.

On *Your details*, when the language the lists are offered in changes, a chosen form of address, pronoun set or gender becomes its equivalent in the new language (*he/him* becomes *il* going from English to French). A value with no equivalent is kept as it is under *Other…*, not dropped or switched to something else. ## What exists today - `accounts/addressing.py` holds three lists per language (`en`, `fr`, `pt-PT`, `pt-BR`): `FORMS_OF_ADDRESS`, `PRONOUNS` and `GENDERS`. The module says they "are data, not translations" and that **what is stored is the text itself, never a key** ("Dr.ª" and not "pt-PT:3"), so a value survives a change of language. - **Which list is offered**: `addressing.language_of(profile)` returns the career record's language (`record_language`) and, when that is blank, the interface language of the request. Changing the interface language changes the lists only when the record has no language of its own. - **What happens on a change today** (`accounts/forms.py`, `ProfileForm._offer`): the stored text is compared with the new list. If it is not in it, the menu shows ***Other…*** and the box beside it holds the old text (`self.initial[name] = addressing.OTHER`, `initial[f"{name}_other"] = stored`). So after switching English → French, *he/him* is shown as *Other…: he/him*. Nothing maps it to *il*, and nothing is lost. Saving the page stores *he/him* again. A CV prints the stored text whatever its language. - A precedent for mapping words: `LEGACY_GENDERS` and `current_gender_word` (#864) replace an old list word with the new one in the migration, the importer and the candidate reader. ## What would change - An equivalence table in `addressing.py`: a language-neutral concept for each list entry, with that concept's word in each language. - Pronouns and genders line up one to one in the four languages (she / he / they: *she/her, elle, ela/dela*; *he/him, il, ele/dele*; *they/them, iel, elu/delu*. Female / Male / Non-binary likewise). - Forms of address do not. Possible pairs: *Mr* = *M.* = *Sr.*; *Mrs* and *Ms* = *Mme* = *Sr.ª* (pt-PT) / *Sra.* (pt-BR); *Prof.* = *Pr* = *Prof.* / *Prof.ª*; *Dr* = *Dr* = *Dr.* / *Dr.ª*. No equivalent: *Miss*, *Mx*, *Me*, *Eng.*, *Eng.ª*. Portuguese marks gender where English and French *Dr* and *Prof.* do not, so those only map from Portuguese, not to it. Portuguese *Dr.* is also a courtesy for any graduate, not English *Dr*. Each pair needs a reason written beside it, as the module's sources are. - When the lists are drawn (`_offer`), a stored value that is another language's word for a concept with a word in this language selects that word in the menu. One with no equivalent stays under *Other…* with its text, as today. - What is stored, two options: 1. **Map on save.** The menu shows the equivalent, and saving stores the new language's text. Simple, and keeps "the text itself" as the stored value. But a CV in the old language then prints the new word. 2. **Store the concept, print per document.** Store a concept key where the value is a list word, and the text only for *Other…*. A CV prints the word in its own language. This reverses the module's "never a key" rule and touches the archive format, the API schema, the vCard mapping (#660) and the importers. - Never set one field from another: gender never decides pronouns, and the reverse (#681's promise). This mapping works only within one field. ## Notes - This is i18n data, not catalogue text: the words stay in `addressing.py` and are not translated through Weblate. Any new sentence (for example one saying a value was carried over from another language) is a catalogue string. - Tests: switch `record_language` and the interface language, check each list for each pair, check that a value with no equivalent survives under *Other…*, and check a bound form that comes back with an error (`_offer`'s "a page that comes back keeps what it was sent"). ## To decide - Option 1 or 2. - Whether the mapping applies when the career record's language changes, or only when the interface's does. Today the record's language decides the lists. Related: #309, #681, #864. Checked against `main` at `56fc9d531`.
Author
Owner

Decision (maintainer, 2026-10-15): store a language-neutral value, except for "Other".

  • What is stored. Form of address, pronouns and gender are stored as concepts (for example he/him, formal), never as the words of one language.
  • What is shown. The interface and every document print the concept in the language they are drawn in. Switching from EN to FR shows «il» for he/him without changing anything stored.
  • "Other" is the one exception. It holds free text that the person typed in their own words. It is stored as typed and shown as typed, in every language.
  • Migration. Existing values become concepts where they match one in any catalogued language. A value that matches none goes under "Other", unchanged.
  • Translation. The labels for the concepts go through the catalogues (Weblate). No new free text is translated.
**Decision (maintainer, 2026-10-15): store a language-neutral value, except for "Other".** - **What is stored.** Form of address, pronouns and gender are stored as concepts (for example `he/him`, `formal`), never as the words of one language. - **What is shown.** The interface and every document print the concept in the language they are drawn in. Switching from EN to FR shows «il» for `he/him` without changing anything stored. - **"Other" is the one exception.** It holds free text that the person typed in their own words. It is stored as typed and shown as typed, in every language. - **Migration.** Existing values become concepts where they match one in any catalogued language. A value that matches none goes under "Other", unchanged. - **Translation.** The labels for the concepts go through the catalogues (Weblate). No new free text is translated.
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#921
No description provided.