ADR-213: Approval preview lines are in the acting user's language
- Status
-
Accepted
- Date
-
2026-10-06
- Authors
-
Netresearch DTT GmbH
Context
A run that needs a human approval suspends, and every tool that implements
Tool describes the pending call in lines of text
(ADR-136). The lines are produced at the moment of suspension,
persisted in the suspended state, shown on the approval card after a per-viewer
authorisation, and produced a second time when the run resumes, to compare them
with what the approver was shown (ADR-184).
All of them are English literals. For a German editor that makes the card a mix:
the buttons and the labels around it are German, the lines in the middle read
New page under page , navigation title: and
first among the subpages. The editorial guidelines for the assistant
(rules 14 to 18) ask for approval texts in the editor's language, in editor
vocabulary, in a fixed order, without internal field names.
Two constraints follow from the design above and decide where the language can come from:
- The lines are compared byte for byte at resume. Their language must be the same at suspend and at resume, on the synchronous path and in the queue worker, or every approval of a localised tool bounces as stale.
- The run owner and the person who approves can be different people (ADR-130, ADR-133). One set of lines is persisted per pending call.
Decision
The language of a preview line is the language of the run's acting backend
user, the lang column of the user the run executes as, read from the
Tool (ADR-083). Never the ambient
$GLOBALS, which belongs to whoever runs the call, and never the
viewer's language.
- A user without a
langvalue gets English, which is what TYPO3 itself does for such a user. A language without a catalogue of its own gets the English source text. - When the viewer's language differs from the acting user's, the card shows the lines in the acting user's language, complete and in one language. It does not mix, and it does not retranslate. In the usual case, an editor who starts the run in the chat and approves it there, the two are the same person.
- When the acting user changes their language between suspend and resume, the re-computed lines differ from the persisted ones and the approval bounces once, with the current lines shown again (ADR-184). That is the existing staleness path doing its job; no special case.
The texts live in the extension's catalogue, locallang. and
de., under approval. A closed enum,
Approval, names every entry, and
Approval resolves one for a given user. Tools do not
build a sentence from English words: they pick labels and pass the values.
Quotation marks, the word for "empty" and every sentence are catalogue entries,
so a language decides its own.
A unit test walks the enum and fails when a label has no English or no
German text, when the two texts take different placeholders, when the German
text is the English one, when a text names an internal field or tool, or when
the catalogue holds an approval entry that no label names.
The order of the lines follows rule 16 of the guidelines: what changes, where, the current state, the new state, the consequences. The last line is "Technical details": UIDs and table names, for support (rules 10 and 26). It is not an optional extra: it keeps the approval bound to the exact records the call names, because the lines above it name pages by title and two pages can share one (ADR-184).
What stays English. A refusal line is the string the tool's execute
hands the model as well; it is shared on purpose, and a refusal at preview time
tells the approver the call would fail, not what it would do. The tool results
that go back to the model stay English too; they are not approval text.
Scope of this decision. It is applied to create_,
move_ and delete_. The other tools that implement
Tool keep their English lines until they are converted
to the same mechanism; each of them needs its own list of labels and its own
expected text, and the guidelines' rules 19 to 21 (consequences) need to be
checked against what each tool actually reads.
No new reads. The consequence lines show what the tools already read for
their plan: translations, subpages, the number of records stored on a page,
the number of references, recoverability. A line the tool cannot know is not
shown. In particular delete_ does not say anything about redirects:
it does not look at them, and whether core creates one on a delete is not
something this decision verifies.
Considered alternatives
English only (the status quo). Rejected: it contradicts rule 17 and mixes languages on every German card.
The viewer's language at render time. The right answer to the second constraint, and the larger change: the persisted state would have to hold label identifiers and values instead of text, the comparator would compare those, and both card renderers would translate at display time. The loop, the state encoding and the chat panels all change. Not rejected as a goal; rejected as part of this step, because it is a format change of persisted state and the acting user is the viewer in the common case. If approvals by someone other than the run owner turn out to be common, this is the next step.
The ambient backend language ($GLOBALS). Rejected: it is the
language of the process that happens to run the call, and it differs between
the request that suspends and the worker that resumes (ADR-083).
Consequences
● A German editor reads a German approval card for these three tools: the heading names the editorial action, the lines carry no field name, and the consequences of a delete are listed line by line.
● The English text is the catalogue's source text, so an installation in any other language sees the same English lines as before in structure, and a translation file for that language works without code.
◐ The lines of these three tools changed in wording and order. A caller that matched on the old English strings, rather than showing the lines, has to change; none in this repository did except the tools' own tests.
◐ A viewer whose language differs from the run owner's reads the owner's language (see above).
✕ The other tools' previews are still English, so a card for one of them still mixes languages until it is converted.
✕ A refusal shown in a preview is still English.