v0.253.0 — errors carry the key of the sentence they are (R-557 slice 2 release B)
gates / gates (push) Successful in 24s
gates / gates (push) Successful in 24s
179 Hungarian sentences were built deep inside a package with fmt.Errorf and printed by whoever caught them: too late to translate where they are shown, too early where they are made. Every one now carries its key across that gap. ZERO Hungarian error literals remain. util.MsgError does three things at once, each earned: - Error() is the Hungarian, byte for byte, so every un-converted printer is unchanged; - errors.Is answers for the kind AND for a wrapped cause (KindErrorf dropped the cause); - an error ARGUMENT renders recursively, so "formázás sikertelen: %w" translates whole. A foreign error — restic, docker, ssh, the stdlib — prints verbatim. It is not ours. 76 display sites go through errText, and TestNoErrErrorInPageOutput convicts any that do not. memoryVerdict returns an error rather than a sentence, so the deploy's 409 and the household's language come from one value; UpdateRefusal gained a Cause to carry it. Plurals, one rule, stated once: a key with .one/.other takes its COUNT first. Not a per-call-site flag — the producer somebody forgot would read "3 app is not running". The guard caught a real key collision (alert.deadapp.one) the day the rule landed. TWO DEFECTS FOUND IN MY OWN TOOLING, recorded rather than quietly fixed. The bulk converter silently dropped multi-line concatenations, damaging 7 producers — and the parity gate could not see it, because every surviving fragment WAS a real base literal while the CALL had lost text; two behaviour tests caught it. And the counting script was case-sensitive, so it said "0 left" while five remained. MinAgent: 0.131.0 (unchanged). No hub release needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -1,3 +1,50 @@
|
||||
## v0.253.0 — Errors carry the key of the sentence they are (2026-09-18, R-557 slice 2 release B)
|
||||
|
||||
**MinAgent: 0.131.0** (unchanged). **No hub release needed.** Every Hungarian sentence is byte-identical
|
||||
to the literal it replaced, measured by `i18n_go_parity.py`, and nothing on the wire moved.
|
||||
|
||||
179 Hungarian sentences were built deep inside a package with `fmt.Errorf` and printed by whoever
|
||||
caught them. They could not be translated where they are SHOWN (by then they are a finished string)
|
||||
nor where they are MADE (that code has no request and no language). **Every one of them now carries
|
||||
its key across that gap, and zero Hungarian error literals remain.**
|
||||
|
||||
`util.MsgError` does three things at once, and each was earned:
|
||||
|
||||
1. **`Error()` returns the Hungarian, byte for byte.** Every un-converted printer — a log line, a
|
||||
`%v`, a third-party wrapper — keeps printing exactly what it printed before. That is what made
|
||||
converting 179 producers safe without converting all their printers in the same commit.
|
||||
2. **`errors.Is` still answers, for the kind AND for a wrapped cause.** `Unwrap() []error` returns
|
||||
both. The predecessor `KindErrorf` returned the kind alone and dropped the cause; a converted
|
||||
producer usually wraps one, and a caller testing for it would have silently stopped matching.
|
||||
3. **An error ARGUMENT is rendered recursively**, so `„formázás sikertelen: %w"` translates the whole
|
||||
chain. An inner error that is not ours (restic, docker, ssh, the stdlib) prints itself — that text
|
||||
is not written here and is not translated here (R-553's rule).
|
||||
|
||||
- **Every display path goes through `errText`** (76 sites in `internal/web` and `internal/api`), and
|
||||
`TestNoErrErrorInPageOutput` keeps it that way. A `strings.Contains(err.Error(), …)` is a
|
||||
COMPARISON and is deliberately untouched — the four English ones are R-569.
|
||||
- **The memory refusal is now an error where it is made.** `memoryVerdict` returns
|
||||
`util.MsgErrorf(ErrNotEnoughMemory, …)` instead of a sentence a caller had to wrap, so the API's
|
||||
409 and the household's language come from one value. `UpdateRefusal` gained a `Cause` so the same
|
||||
error survives to the API through the update path.
|
||||
- **Plurals, one rule, stated once:** a key that carries `.one`/`.other` forms in a language is a
|
||||
plural key and its FIRST parameter is the count (`i18n.Bundle.form`). Hungarian never carries them
|
||||
— it does not inflect after a numeral — so a Hungarian render is unchanged at every count. Not a
|
||||
per-call-site flag: the one producer somebody forgot would read „3 app is not running" with nothing
|
||||
to catch it. `TestPluralFirstArgIsNumeric` pins that every plural value really does take its count
|
||||
first; `TestNoOrdinaryKeyEndsInAPluralSuffix` pins that `.one`/`.other` stay reserved — a real
|
||||
collision (`alert.deadapp.one`) was caught by it on the day the rule landed.
|
||||
|
||||
**Two defects this release found in its own tooling, both recorded rather than quietly fixed:**
|
||||
|
||||
- The bulk converter **silently dropped the continuation of a multi-line concatenation**, damaging 7
|
||||
producers. The parity gate did not catch it: every surviving fragment WAS a real base-commit
|
||||
literal, so its question was answered yes while the call had lost text. Two behaviour tests
|
||||
(`TestR356_ScenarioC`, `TestR379_ScenarioA`) caught it, because they assert the sentence a customer
|
||||
reads. All 7 rebuilt as joined keys.
|
||||
- The counting script was **case-sensitive**, so it reported "0 error literals left" while five
|
||||
remained. The R-565 shape, in the instrument. Re-measured; the five are converted.
|
||||
|
||||
## v0.252.0 — The sentences the program writes follow the language (2026-09-18, R-557 slice 2 release A)
|
||||
|
||||
**MinAgent: 0.131.0** (unchanged). **No hub release needed.** Nothing a Hungarian household reads
|
||||
|
||||
Reference in New Issue
Block a user