Repository navigation
Show catalogue copy for API errors on participant screens - #449
Merged
Merged
Conversation
Four places printed the server's developer-facing English, which a Dutch reader cannot read and no translator ever sees: the Explore composer's submit error, the "consultation unavailable" screen, the join form's error, and the not-eligible page's reason. Each now maps the error's code to its own message, through tables in i18n/server-labels.ts, and anything the table does not know (a new code, a rate limit, a network failure) gets that form's generic message rather than the server text. The composer reuses the unused conv-err-proposal-limit, conv-err-similarity and conv-err-submit-statement. An unknown outcome gets its own message telling the participant not to resubmit as a new statement, since a fresh composer means a fresh idempotency key and a possible duplicate. The workspace reuses the 404 page's line for a consultation that does not exist. The not-eligible page ignores details.displayMessage, which since #425 only carries Proto's own diagnostics about its checker, and picks its reason from the code. Four new messages, in English and Dutch, plus Dutch for the three reused composer messages. The i18n README carries the new counts. Closes #397. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…are about A failed read of the original statement, before anything is sent upstream, was reported as command_outcome_unknown, so a participant rewording a statement during an outage was told it might have been posted. It is now upstream_unavailable, like the sibling preparation failures. The unknown-outcome message invited a retry that could only show it again: nothing reconciles the pending attempt, and edited text under the same key is an idempotency conflict. It now says the statement was sent, may already be in, need not be sent again, and that the participant can cancel and carry on. The removed-original message gives the steps the reword composer actually allows: copy the text before cancelling, then add it as a new statement. A 409 (statements no longer taken, or not joined) and a 403 (banned) now say the participant cannot add statements right now, in a new message, rather than "try again". A 401 keeps the generic message; no participant message says "sign in again" yet. The composer's error uses the form-error style, has an id the textarea points at, and marks the field invalid only when the rewording was too far from the original. The not-eligible page takes focus from the form it replaces. A consultation that does not exist gets the 404 heading rather than "Consultation unavailable". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A statement or join refused with 401 said "try again", which fails the same
way every time. Both forms now show common-err-nologin, whose text is
MediaWiki core's exception-nologin-text copied exactly, so translation
memory offers translators core's existing translations; qqq cites it with
{{msg-mw|exception-nologin-text}}. The workspace load needs no entry: it
redirects a 401 to the login before its error branch.
The i18n README's "reuse before you mint" step and rule 5 of plan_i18n.md
now say to look for a MediaWiki core message before minting one, and to
copy it exactly when it fits. The README carries the new counts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Following "reuse before you mint", eleven messages now carry text copied
from MediaWiki and its components, with MediaWiki's Dutch where it has one:
the toast's close button is Codex's "Close", the skip link is Vector's
"Jump to content", the new-tab hint is core's newwindow, the countdown units
are core's days/hours/minutes-abbrev ("2 d 4 h 30 min"), and the statement
steppers are core's "Previous"/"Next". errorpage-500-title already matched
OOUI's ooui-dialog-process-error.
The three loading texts become one message, common-loading, which is
MobileFrontend's "Loading…": the app shell placeholder (still server-stamped),
the workspace placeholder, and the reroll button while it is busy. It
replaces base-loading-conversations, conv-loading and accept-reroll-loading.
Decorative glyphs leave the messages for the markup, aria-hidden: the
steppers' arrows and the reroll button's ↻ (so accept-reroll loses it too).
The new-tab hint's leading space moves into the markup as well.
Thirty-two short labels already read exactly like a MediaWiki message in the
same sense ("Cancel", "Reason", "$1 of $2"...). Their English is unchanged,
their Dutch too where it differs from MediaWiki's; qqq now cites the source.
Every copied message is listed in the new i18n/ATTRIBUTION.md with its
source key, file and licence, with the MIT notices of OOUI and VisualEditor
and a credit to translatewiki.net's translators. All sources are
GPL-2.0-or-later or MIT, so compatible with GPL-3.0. Each copied message's
qqq cites the source with {{msg-mw|...}} and names the licence;
common-err-nologin gets the same treatment. test_i18n.py fails if qqq and
ATTRIBUTION.md disagree on which messages are copied, if a qqq entry does
not name its licence, or if the English recorded there no longer ships.
Six messages no call site uses on any branch are deleted: conv-network-error,
conv-network-error-retry, conv-err-connect, conv-error-load,
conv-err-change-vote and conv-vote-loading.
The README's "reuse before you mint" step and rule 5 of plan_i18n.md now say
to copy only from GPL-3.0-compatible sources and to record the source and
licence. The README carries the new counts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…h it elsewhere Where our Dutch differed from MediaWiki's for a message we copy, MediaWiki's wins, lowercased where the English is: - conv-arg-unhide: "tonen" -> "zichtbaar maken" - conv-orient-collapse: "inklappen" -> "samenvouwen" - errorpage-403-title: "Geen toegang" -> "Niet toegestaan" - conv-results-quoted: curly -> straight quotes, as quotation-marks has them The other Dutch messages that used the same words for the same thing follow: the statement panel's accessible names now say "uitvouwen"/"samenvouwen". ATTRIBUTION.md records these as copied Dutch too. The qqq entries for the copied short labels tell translators to use MediaWiki's translation, not that it "usually fits". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
main gained the voucher flow (#441, #442), which appended its messages where this branch appended accept-err-join, and its refusal tests where this branch added its error-copy tests. Both are kept. common-cancel takes main's {{Identical|Cancel}} (voucher-switch-cancel now shares its text). The README counts are recomputed: 975 keys, 597 offered, 378 held back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
common-cancel keeps its MediaWiki citation and takes main's
{{Identical|Cancel}}. main's new voucher-switch-cancel is also "Cancel", so it
cites core's cancel as well and gets its row in ATTRIBUTION.md (English only;
the voucher pages have no Dutch yet). The README counts are recomputed: 967
keys, 589 offered, 378 held back, 539 Dutch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The two lists still have to agree on which messages are copied, and a citation still has to name its licence. Re-asserting every copied English string here as well only turns a wording change into a second edit in a second file, which is a chore rather than a guard: nothing user-visible breaks if the quoted English drifts. ATTRIBUTION.md no longer promises that check. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#447 merged while this branch was open, so main carries conv-bar-title and conv-bar-label without their literal "%" (the number brings its own) and their rewritten qqq. Those win. The messages this branch deletes as unused — conv-network-error, conv-network-error-retry, conv-err-change-vote — stay deleted, and the conv-err-* documentation stays as rewritten here. Counts: 969 keys, 591 offered, 378 held back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"This looks like a different claim" judges what the participant meant; the check only measures how far the text is from the original. It now says that, in both languages, and the qqq notes the check is off unless an organizer sets a threshold. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
#443 and #398 merged while this branch was open. The "still English on purpose" list drops the moderation-log fallbacks (#398 fixed them) and no longer names server error messages, which is what this branch fixes; it keeps the sentence saying participant screens map an error's code to catalogue copy. Counts recomputed: 978 keys, 600 offered, 378 held back, 542 Dutch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
That branch reworded conv-err-similarity (it now says the text deviates from the original rather than judging it a different claim), which lands next to the network messages this branch deletes. Its wording wins, the deletions stay. Counts: 970 keys, 592 offered, 378 held back, 540 Dutch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…wn word From the review panel on #450: - Arrows in the markup cannot be mirrored by a translator and are not mirrored by Unicode either, so a right-to-left page pointed them the wrong way. Every decorative ← and → in the SPA now carries .dir-glyph, which flips under [dir="rtl"] — the 18 spans this branch and earlier work introduced, plus the identity-reveal back link, whose arrow was a bare literal inside the link's accessible name. Arrows that live inside a message stay the translator's. - common-loading is written for a whole line and read wrong in the reroll button: capitalised next to a lowercase label, and 18 characters of Dutch in a control a few characters wide. The button has accept-reroll-loading back ("loading…" / "laden…"); common-loading keeps the page-level states. - accept-reroll-aria did not contain the word the button shows, so voice control could not target it (WCAG 2.5.3). It now reads "Reroll: generate new pseudonym options", and the qqq for it and for the two nav labels says the visible text has to appear in the accessible name. - test_spa_shell_locale used a temp catalogue value identical to app.py's hardcoded fallback, so deleting the key left it green. It now stamps CATALOGUE-EN-LOADING, and the missing-catalogue test still asserts the fallback. Counts: 971 keys, 593 offered, 378 held back, 541 Dutch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reuse MediaWiki's messages where they fit, and credit them
lgelauff
added a commit
that referenced
this pull request
Sep 23, 2026
The reservation case built its time at import — five minutes ahead — so the suite had five minutes to reach the test. A CI run that took 5m41s found the reservation lapsed, and a lapsed reservation is claimable (services/vouchers.py:225 blocks only while reserved_until > now, :255 sweeps it up), so the code redeemed and the test that expects a refusal failed. It failed on #449, whose diff has nothing to do with vouchers. #470 fixed the timing by turning both times into offsets from now, which left the direction of time carried by a minus sign — {'expires_at': -timedelta(days=1)} beside {'reserved_until': timedelta(minutes=5)} — and put the rule that read them (any timedelta means now plus that) eleven lines below the list. Neither case cares how far a date is from now, only which side it falls on: one code is past its expiry, another is still reserved by someone else. Two sentinels say that, the values are plain dicts again, and a date cannot be overtaken by a slow suite. The cases are named as well, so the next failure says "reserved" instead of "kwargs2". Checked, beyond the suite: a throwaway matrix over status x expiry x reservation (84 cases) agreed with the rule in services/vouchers.py; with the clock moved forward 6 minutes, 2 hours, 400 days and 60 years the sentinel cases kept their meaning, while the old five-minute reservation flipped to redeemable at 6 minutes; tz-aware and naive values classify alike. That matrix was deliberately not kept. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
main gained #470/#471 (the voucher reservation test no longer races the clock, which is what failed this branch's CI, nothing here touched vouchers) and #468 (the status table says "committed" rather than a tick). Main's wording wins; counts recomputed: 971 keys, 593 offered, 378 held back, 541 Dutch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #397.
Why
Four participant screens printed the server's developer-facing English error text, which a Dutch reader can't read and no translator ever sees:
What changes
i18n/server-labels.ts, one per screen, each with a generic fallback. The server'smessageis never rendered.conv-err-proposal-limit,conv-err-similarityandconv-err-submit-statement.command_outcome_unknownsays the statement was sent and may already be in, so it need not be sent again.exception-nologin-text, copied exactly ("Please log in to be able to access this page or action."), and the join form uses it too.command_outcome_unknown. It is nowupstream_unavailable(app.py), with a test.details.displayMessage(Proto's own diagnostics since Switch join eligibility gate to canivote (#406) #425) and takes its reason from the error code.aria-describedby, andaria-invalidfor the similarity error).plan_i18n.mdnow say to look for a MediaWiki core message first and copy it exactly.Merged with main
maingained the voucher flow (#441, #442), which appended messages and tests at the same spots as this PR.mainis merged in with both sides kept;common-canceltakes main's{{Identical|Cancel}}. README counts: 975 keys, 597 offered, 378 held back.Tests
Review
This PR had a review panel with a cross-review round. Its findings are fixed in the second and third commits.
🤖 Generated with Claude Code