The interface's own translations break outside English: plurals chosen in JavaScript, English password advice, fixed date formats, sentences in pieces #225
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
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#225
Loading…
Add table
Add a link
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?
These will get worse with every language #70–#72 adds. Found in the 2026-09-15 code audit.
1. "N rows ticked" chooses its plural by hand
partials/table/bulk.html:65-66supplies only "One row ticked." and "{count} rows ticked.", andstatic/js/app.js:495picks withticked === 1 ? one : many. That is wrong for Polish, Czech, Slovak, Slovene, Croatian, Serbian, Bosnian, Ukrainian, Lithuanian, Latvian, Irish, Maltese and Welsh.Fix: render the
ngettextresult for n = 1 up to the page size into a JSON data attribute and index it from the script. The page size is bounded, so this is exact without CLDR rules in JavaScript.2. Password-strength advice is always English
account/partials/password_meter.html:6-8loads only zxcvbn'slanguage-en, andapp.js:283,370-371appends itswarning/suggestionsto the translated strength word, inside a polite live region. A French user hears "Fort · Add another word or two…" on every keystroke.Fix: show the advice only when the interface is English, or map zxcvbn's warning keys to translated strings through data attributes. Announce only when the strength word changes.
3. 73 fixed date formats, against
docs/TRANSLATING.md:192|date:"…"formats across 33 templates (22 ×"j M Y", 14 ×"j M Y, H:i", …); only 7 useDATE_FORMAT/DATETIME_FORMAT.{{ share }}%(widgets/funnel.html:12,widgets/insight_counters.html:21), while French writes "42 %" and Turkish "%42".Fix: named formats, with
FORMAT_MODULE_PATHentries for a short month-name date; atest_template_lint.pyrule that rejects literal date formats; a translatable%(n)s%%.4. Sentences assembled from fragments
api/token_list.html:67-77: "created" + date · "expires"/"expired" + date · "last used" + date and time.applications/partials/board.html:10-15: ablocktranslateending in ";", then a separate "see them in the table", then a literal ".".settings/appearance.html:52: a standalone "days" after a number field, with no plural.Fix: whole sentences with placeholders (
Created %(date)s), the<a>inside theblocktranslatewith its URL as a variable, andngettextfor units.