Untranslated strings people read: the Browser and Email notifier names, a career end-date error, the unreadable-secrets message #566
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#566
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, looking for literal messages that reach a page without passing throughgettext.Checked again on 2026-10-01 against
mainat0a5cad587: still present. The code is now atplugins/views.py:249-250(the connection form) andplugins/views.py:401-402(the result of Test); the other places are where they were, and the re-extracted catalogues still lack the three msgids.Four strings that people read on ordinary pages are English literals, so a reader in any other language meets English in the middle of translated sentences. None of them is in the catalogues (
msgid "Browser"andmsgid "This is before the start date."are absent fromlocale/fr_FR/LC_MESSAGES/django.po;"Email"is there only because another string uses it).plugins/browser/__init__.py:52:label="Browser"in theshipped(...)manifest ofBrowserNotifier, while itsdescriptionbeside it goes through_lazy.plugins/email/__init__.py:87:label="Email"in the manifest ofEmailNotifier, the same pattern. The other shipped plugins whose label is a common word wrap it (own_mail_lazy("Your own email"),localstore_("This instance"),gdpr,identifiersand so on); only brand names such asSMTP,Webhook,Europassandschema.orgstay literal, which is right for them.resume/forms.py:94:ExperienceForm.cleanaddsforms.ValidationError("This is before the start date.")although the module importsgettext_lazy as _.plugins/secrets.py:68-72:decryptraisesSecretsUnreadable("The connection's secrets cannot be read: ...")as a plain string. The text is shown as is byplugins/views.py:248(messages.error(request, str(error))on the connection form), byplugins/views.py:400(the result of Test), stored aslast_errorbyplugins/syncing.py:81-82and shown on Connections, and returned bydocuments/archiving.py:138-139as a copy's failure.templates/connections/form.html:7and:25putplugin.labelinside translated sentences). Saving a career entry whose end date precedes its start shows one English sentence under the end date. After the instance's key changes, every connection page and every test or sync of that connection reports the secrets problem in English.label=_lazy("Browser")andlabel=_lazy("Email");forms.ValidationError(_("This is before the start date."))inExperienceForm.clean; wrap theSecretsUnreadablemessage ingettextat the raise insecrets.decrypt(withPOSTULO_FIELD_KEYandSECRET_KEYas placeholders or left literal inside the sentence, so translators do not rename them). Then run the extraction so the three new msgids reach the catalogues.Done when
tests/test_notifications.pyactivates a language whose catalogue translates "Browser" and assertsregistry.find_plugin("notifier", "browser").labelis not the English word (or, independent of any catalogue, asserts both labels are lazy translation proxies).ExperienceFormwith the end before the start undertranslation.override("fr")and asserts the error is not the English sentence.tests/test_connections*.py(or the secrets tests) triggersSecretsUnreadableunder a non-English language and asserts the message shown is translated.