Filed unassigned by the dev seat implementing objectui#6888, as an out-of-scope finding. Recording, not choosing.
Dedup before filing: one directed search_issues for "number input widget badInputMessage refusal sentence hard-coded English literal not routed through useFieldTranslation locale packs" — five hits, all closed and all a different surface (objectui#3342 TagsField placeholder, objectui#5717, objectui#5675, objectui#4386, objectui#3222). Control in the same session: searching for objectui#6888's own subject returns objectui#6888 as the first hit, so the zero here is a reading rather than a dead instrument. REST was 403 for this seat (session gate closed), so the channel was MCP search_issues plus a local grep — declared as a channel switch.
What
objectui#6755 ruled (2026-08-29, maintainer) that a widget's OWN refusal sentence goes through useFieldTranslation + FIELD_DEFAULTS. objectui#6888 has just applied that to LocationField's residue arm, the fourth sentence. There is a fifth, and it is the widest of them all:
packages/fields/src/widgets/numberBadInput.tsx:88
export function badInputMessage(example: string): string {
return `Not saved: the text in this box is not a number. Enter a plain decimal (example: ${example}).`;
}
It is a string literal in the source, in objectui#6716's own Not saved: … shape, and unlike the four already keyed it is not one widget's sentence — numberBadInput.tsx is shared, and the literal reaches:
packages/fields/src/widgets/NumberField.tsx
packages/fields/src/widgets/CurrencyField.tsx
packages/fields/src/widgets/PercentField.tsx
packages/fields/src/widgets/GeolocationField.tsx
Why it is filed rather than folded into the objectui#6888 PR
objectui#6888's scope is LocationField's residue arm. Its dev seat is not the one to decide that a ruling written about three sentences, already stretched once to a fourth by triage, now also covers a fifth in four other widgets — that is the same judgement objectui#6888's filer correctly declined to make for itself.
The measured consequence
Same shape as objectui#6888's, one package wider. NumberField, CurrencyField and PercentField render this sentence into the widget's own diagnostic element beside labels, gate hints and validation copy that are all translated. GeolocationField is the sharpest case: it sits next to LocationField, whose three refusal sentences are now all keyed, so two adjacent coordinate widgets refuse bad input in two different languages.
Cost if it is ruled in
Mechanically what objectui#6888 did, minus its hard part. One key with one {{example}} hole plus ten pack entries; the English value stays byte-identical, so NumberInputWidgets.badInputAnnounce.test.tsx — which asserts through badInputMessage(example) rather than against a literal — keeps passing unchanged.
⭐ It does not have objectui#6888's arity question. The sentence has no grammatical number: one box, one verb. {{example}} is a decimal numeral, which is data. So this really is the two-line copy objectui#6888 was not.
⚠️ One thing to measure before keying, which objectui#6888 did not have to: example is produced per widget (30.2741 / 120.1551 / 1234), and a pack that writes its decimals with a comma separator would collide with the latitude, longitude example pair. Whether the example belongs in the hole or per-widget in the key is that card's own small authoring question.
Related
objectui#6755 (the ruling) · objectui#6888 (the fourth sentence, and the arity precedent it set) · objectui#6716 (the Not saved: … shape) · objectui#4752 (the same class in @object-ui/components, still its own card)
Filed unassigned by the dev seat implementing objectui#6888, as an out-of-scope finding. Recording, not choosing.
Dedup before filing: one directed
search_issuesfor "number input widget badInputMessage refusal sentence hard-coded English literal not routed through useFieldTranslation locale packs" — five hits, all closed and all a different surface (objectui#3342 TagsField placeholder, objectui#5717, objectui#5675, objectui#4386, objectui#3222). Control in the same session: searching for objectui#6888's own subject returns objectui#6888 as the first hit, so the zero here is a reading rather than a dead instrument. REST was 403 for this seat (session gate closed), so the channel was MCPsearch_issuesplus a local grep — declared as a channel switch.What
objectui#6755 ruled (2026-08-29, maintainer) that a widget's OWN refusal sentence goes through
useFieldTranslation+FIELD_DEFAULTS. objectui#6888 has just applied that toLocationField's residue arm, the fourth sentence. There is a fifth, and it is the widest of them all:It is a string literal in the source, in objectui#6716's own
Not saved: …shape, and unlike the four already keyed it is not one widget's sentence —numberBadInput.tsxis shared, and the literal reaches:packages/fields/src/widgets/NumberField.tsxpackages/fields/src/widgets/CurrencyField.tsxpackages/fields/src/widgets/PercentField.tsxpackages/fields/src/widgets/GeolocationField.tsxWhy it is filed rather than folded into the objectui#6888 PR
objectui#6888's scope is
LocationField's residue arm. Its dev seat is not the one to decide that a ruling written about three sentences, already stretched once to a fourth by triage, now also covers a fifth in four other widgets — that is the same judgement objectui#6888's filer correctly declined to make for itself.The measured consequence
Same shape as objectui#6888's, one package wider.
NumberField,CurrencyFieldandPercentFieldrender this sentence into the widget's own diagnostic element beside labels, gate hints and validation copy that are all translated.GeolocationFieldis the sharpest case: it sits next toLocationField, whose three refusal sentences are now all keyed, so two adjacent coordinate widgets refuse bad input in two different languages.Cost if it is ruled in
Mechanically what objectui#6888 did, minus its hard part. One key with one
{{example}}hole plus ten pack entries; the English value stays byte-identical, soNumberInputWidgets.badInputAnnounce.test.tsx— which asserts throughbadInputMessage(example)rather than against a literal — keeps passing unchanged.⭐ It does not have objectui#6888's arity question. The sentence has no grammatical number: one box, one verb.
{{example}}is a decimal numeral, which is data. So this really is the two-line copy objectui#6888 was not.exampleis produced per widget (30.2741/120.1551/1234), and a pack that writes its decimals with a comma separator would collide with thelatitude, longitudeexample pair. Whether the example belongs in the hole or per-widget in the key is that card's own small authoring question.Related
objectui#6755 (the ruling) · objectui#6888 (the fourth sentence, and the arity precedent it set) · objectui#6716 (the
Not saved: …shape) · objectui#4752 (the same class in@object-ui/components, still its own card)