You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(cli): inline label: is the default-locale source for i18n coverage (#3103)
A fresh `npm create objectstack` scaffold linted with 4 user-side i18n errors
out of the box, for its own `<ns>_note` object — every one of them for a string
the template *does* author inline (`label: 'Note'`, `pluralLabel: 'Notes'`,
`label: 'Title'`, `label: 'Body'`).
They were false positives. The inline `label:` is the default-locale source
text, and the framework already says so everywhere except here:
- the runtime resolver falls back to it when a bundle carries no entry
(`i18n-resolver` `translateObject`: `lookupObjectField(...) ?? doc.label`),
and its docstring documents the order `locale → fallbackChain → literal
label from the metadata`;
- `os i18n extract` *generates* bundles from it (`obj.label ?? objectName`).
So coverage was demanding an `en` bundle that mechanically restates data the
linter already holds, for text the runtime renders correctly. Worse, an object
with no `pluralLabel` was told its `pluralLabel` was "missing translation" — a
demand for a translation of a string that does not exist, unfixable by
authoring anything but a bundle entry.
Honour the contract instead: an inline label satisfies the default locale, and
a bundle is what *other* locales need. A key with no source string anywhere is
no longer an i18n gap — a missing label is `required/label`'s finding, and this
file already only expected `confirmText`/`successMessage`/`description` when
authored; `label`/`pluralLabel` were the outliers.
Platform form fields keep their key: they omit `label` by design and let the
renderer humanize the path ("name" → "Name"), so that derived text is a real
source string other locales still owe a translation for. Mirrors the
extractor's seed value, which the walker's docstring already promises.
Verified on the issue's repro and against a real multi-locale project — the
non-default-locale signal is preserved exactly:
examples/app-todo before after
os lint 39 errors, 79 warn 0 errors, 79 warn
os i18n check 856 err, 1712 warn 0 err, 1712 warn
Warnings are byte-identical; only the default-locale duplicates are gone. The
platform baseline drops 2451 → 1634 hidden issues, a delta of exactly 817 —
its `en` third (817×3 → 817×2) — because the platform ships English labels
inline too.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pushKey(out,['metadataForms',type,'sections',sectionName,'description'],'metadataForm',`Metadata form ${type}.sections.${sectionName} description`);
298
+
if(sectionName){
299
+
pushKey(out,['metadataForms',type,'sections',sectionName,'label'],'metadataForm',`Metadata form ${type}.sections.${sectionName} label`,inlineText(section.label));
300
+
pushKey(out,['metadataForms',type,'sections',sectionName,'description'],'metadataForm',`Metadata form ${type}.sections.${sectionName} description`,inlineText(section.description));
pushKey(out,['metadataForms',type,'fields',path,'placeholder'],'metadataForm',`Metadata form ${type}.fields.${path}placeholder`);
268
-
}
314
+
// Platform form fields routinely omit `label` and let the renderer
315
+
// humanize the field path ("name" → "Name"). That derived text is the
316
+
// source string — the field is not unlabelled — so other locales still
317
+
// owe it a translation. Mirrors the extractor's seed value.
318
+
pushKey(out,['metadataForms',type,'fields',path,'label'],'metadataForm',`Metadata form ${type}.fields.${path} label`,inlineText(field.label)??humanizeFieldPath(path));
319
+
pushKey(out,['metadataForms',type,'fields',path,'helpText'],'metadataForm',`Metadata form ${type}.fields.${path}helpText`,inlineText(field.helpText));
320
+
pushKey(out,['metadataForms',type,'fields',path,'placeholder'],'metadataForm',`Metadata form ${type}.fields.${path} placeholder`,inlineText(field.placeholder));
0 commit comments