Found while working #14894; unrelated to that card's defect and deliberately not fixed there.
What is wrong
extractTranslations returns counts[locale] as the number of EXPECTED ENTRIES it walked — every entry, metadataForms included (packages/cli/src/utils/i18n-extract.ts, the count += 1 in the per-locale loop). The command then uses that one number for two things it is not:
- The per-file line.
packages/cli/src/commands/i18n/extract.ts pushes each emitted bundle with keys: result.counts[locale] and prints Wrote PATH (N keys). Under the default --objects-only the file written holds only the objects sub-tree, so N counts keys that are not in it.
- The skeleton summary. The same
counts value is printed as N key(s) (of N expected) and then + M metadataForms key(s) is appended — but those M are already inside N, so the line reads as N+M.
Measured
Fixture: one object with one field, one app, i18n.defaultLocale: 'zh-CN', --locales=zh-CN. Leaf counts taken structurally off the emitted modules.
$ os i18n extract FIXTURE --locales=zh-CN --no-metadata-forms --out=OUT
Skeleton summary
zh-CN 776 key(s) (of 776 expected) + 773 metadataForms key(s)
Wrote OUT/zh-CN.objects.generated.ts (776 keys)
The file that run wrote has 2 leaves. The true split of the 776 is 2 objects + 1 app + 773 metadataForms, so the summary's + 773 is the same 773 counted twice, and (776 keys) describes no file the run produced.
Reproduced on main at 2648774 and unchanged by #14894's fix (that card moves which keys are EMITTED, never how they are counted).
Why it is worth a card rather than a shrug
The number is the operator's only feedback that the extract did what they asked. It is what a reader compares against os i18n check's report and against the coverage ratchet, and it is off by two orders of magnitude on the common path (the default --objects-only, which all nine of this repo's extract configs use).
Not in scope of #14894
That card is about which keys are emitted; this is about which number is printed. Fixing this changes stdout for every extract invocation, which is a wider verification surface than that card's repair, so it is filed rather than ridden along.
Dedupe
Searched before filing; the near neighbours are all different or closed — #14816 (a docstring's inline-locale-map count), #14728 (coverage double-counting an action key, closed), #13837 (os i18n check --help under-counting kinds, closed). No open card covers the extract command's own count lines.
Found while working #14894; unrelated to that card's defect and deliberately not fixed there.
What is wrong
extractTranslationsreturnscounts[locale]as the number of EXPECTED ENTRIES it walked — every entry,metadataFormsincluded (packages/cli/src/utils/i18n-extract.ts, thecount += 1in the per-locale loop). The command then uses that one number for two things it is not:packages/cli/src/commands/i18n/extract.tspushes each emitted bundle withkeys: result.counts[locale]and printsWrote PATH (N keys). Under the default--objects-onlythe file written holds only theobjectssub-tree, so N counts keys that are not in it.countsvalue is printed asN key(s) (of N expected)and then+ M metadataForms key(s)is appended — but those M are already inside N, so the line reads as N+M.Measured
Fixture: one object with one field, one app,
i18n.defaultLocale: 'zh-CN',--locales=zh-CN. Leaf counts taken structurally off the emitted modules.The file that run wrote has 2 leaves. The true split of the 776 is 2 objects + 1 app + 773 metadataForms, so the summary's
+ 773is the same 773 counted twice, and(776 keys)describes no file the run produced.Reproduced on
mainat 2648774 and unchanged by #14894's fix (that card moves which keys are EMITTED, never how they are counted).Why it is worth a card rather than a shrug
The number is the operator's only feedback that the extract did what they asked. It is what a reader compares against
os i18n check's report and against the coverage ratchet, and it is off by two orders of magnitude on the common path (the default--objects-only, which all nine of this repo's extract configs use).Not in scope of #14894
That card is about which keys are emitted; this is about which number is printed. Fixing this changes stdout for every extract invocation, which is a wider verification surface than that card's repair, so it is filed rather than ridden along.
Dedupe
Searched before filing; the near neighbours are all different or closed — #14816 (a docstring's inline-locale-map count), #14728 (coverage double-counting an action key, closed), #13837 (
os i18n check --helpunder-counting kinds, closed). No open card covers the extract command's own count lines.