Plugins pages: every shipped plugin's description is shown in English, whatever language the reader uses #633
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#633
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, checking which manifest fields of the built-in plugins are still lazy once the classes exist.Checked again on 2026-10-01 against
mainat0a5cad587: still present.plugins/base.py:319and:287-289are where they were; the row built inplugins/policy.pyis now at:294, and the two incore/server_views.pyat:1072and:1094.shipped()turns a built-in plugin's description into a plain string when the plugin's module is imported, which is at start-up, inLANGUAGE_CODE(en-gb). The translations of these paragraphs, present in every plugin's catalogue, can never be shown.plugins/base.py:319(shipped):description=str(description),whilelabel=labelis passed as given.plugins/base.py:287-289(description_of),plugins/policy.py:303,core/server_views.py:1071and:1093,core/gdpr.py:390: each hands the already-resolved string on.templates/settings/plugins.html:95-96,templates/server/plugins.html:61,templates/server/person_plugins.html:54-55,templates/server/email.html:41: printed as{{ row.description }}or{{ manifest.description }}, with no second translation.gettext_lazystring, for exampleplugins/gdpr/__init__.py:45-52andplugins/postal_rules/__init__.py:85-91. The modules are imported from the apps'ready()(core/apps.py:13-19,plugins/apps.py:17-34).shipped(), in every language. Run against the snapshot: for every built-in,isinstance(manifest.description, Promise)is false, while the feature labels are lazy. With apt-ptcatalogue entry added in memory for both strings of thegdprplugin andtranslation.override("pt-pt"),label_ofreturned the Portuguese entry anddescription_ofreturned "The data the instance keeps about other people: …". The Portuguese text for that paragraph is inplugins/gdpr/locale/pt_PT/LC_MESSAGES/django.po.Manifest(description=_(…))itself is not affected.shipped()(drop thestr()), so the manifest keeps the lazy string anddescription_of()resolves it per request, as it already does withstr(manifest_of(plugin).description). The templates that printmanifest.descriptionthen resolve it at render time. Where a manifest is serialised or compared, callstr()at that point.Done when
tests/test_plugin_manifests.pyasserts that, undertranslation.overridewith a catalogue entry for the description,description_of(<a shipped plugin>)returns the translation; it fails today.manifest.descriptionis a plainstrresolved at import.