I'm working on the Portuguese (and pt-BR) UI translations. While using breeze ui check-translation-completeness I ran into behaviour that felt inconsistent and made it hard to know what to translate or remove.
The checker wasn’t clear on which keys are actually required per locale: sometimes it asked for plural forms that don’t exist in English (e.g. only _one there), and sometimes it reported keys as "extra" when they were just plural variants that the app never uses because it never passes count for that key. So we had "extra" (typos, legacy) and "unused" (those plural forms) as two different things, but for the translator both mean "not required." Coverage was also misleading because it counted keys that still had TODO: translate, so it didn’t reflect how much was really translated. And the flag --remove-extra didn’t make it obvious that the goal is to remove anything that isn’t required (unused at runtime); I’d find --remove-unused clearer.
To understand when a key is really used, I looked at how English, Arabic and Portuguese use the same keys.
English is the source. It often has only _one and _other. When the UI passes a count, the message has {{count}} in the value (e.g. deleteConnection_other: "Delete {{count}} connections"). Some keys have only _one and no count, e.g. dagWarnings.error_one: "1 Error"; the code never calls that with count, so no error_other is ever used. For file upload, EN has only files_other: "{{count}} files"; a locale can add files_one for "1 file" but EN doesn’t define it.
admin.json (EN):
"delete": {
"deleteConnection_one": "Delete 1 connection",
"deleteConnection_other": "Delete {{count}} connections",
...
}
components.json (EN):
"dagWarnings": { "error_one": "1 Error", ... },
"fileUpload": { "files_other": "{{count}} files" }
So for deleteConnection the app does use count, so each locale needs all its plural forms for that base. For dagWarnings.error it never uses count, so only error_one is needed; any error_other or error_zero in a locale is never used. For fileUpload.files the app uses count; something like files_one in PT is optional.
Arabic has zero, one, two, few, many, other. For bases where EN has {{count}}, AR needs all of those (e.g. deleteConnection_zero/one/two/few/many/other). For dagWarnings.error, EN has only error_one, so at runtime only that is used; if AR has error_zero, error_other, etc., they’re never used and the checker should list them in one "unused" bucket, not as a separate "extra" category.
Portuguese usually needs only _one and _other. Same idea: if EN has no {{count}} for a base, only the EN keys are required; anything else in the locale (e.g. error_other, error_zero) is unused. If EN has {{count}}, PT only needs the plural forms that PT’s rules use; adding files_one for "1 arquivo" is fine but not required by EN.
I’m proposing the checker behave like this:
- Required: EN keys plus, for each plural base where EN has
{{count}}, all plural forms that the locale’s language needs. So required = EN keys ∪ locale plural expansion only for those bases.
- Missing: required keys that the locale doesn’t have.
- Unused: any key in the locale that isn’t required (typos, legacy, or plural forms for bases that don’t use
{{count}} in EN). One list, no separate "extra."
- Coverage: translated / total required, where translated = keys with a real value (not
TODO: translate).
- Table: Required (base EN), Required (plural), Total required, Translated, Missing, Coverage, TODOs, Unused.
- Flag: rename
--remove-extra to --remove-unused and update docs/help.
Acceptance criteria
I'm working on the Portuguese (and pt-BR) UI translations. While using
breeze ui check-translation-completenessI ran into behaviour that felt inconsistent and made it hard to know what to translate or remove.The checker wasn’t clear on which keys are actually required per locale: sometimes it asked for plural forms that don’t exist in English (e.g. only
_onethere), and sometimes it reported keys as "extra" when they were just plural variants that the app never uses because it never passescountfor that key. So we had "extra" (typos, legacy) and "unused" (those plural forms) as two different things, but for the translator both mean "not required." Coverage was also misleading because it counted keys that still hadTODO: translate, so it didn’t reflect how much was really translated. And the flag--remove-extradidn’t make it obvious that the goal is to remove anything that isn’t required (unused at runtime); I’d find--remove-unusedclearer.To understand when a key is really used, I looked at how English, Arabic and Portuguese use the same keys.
English is the source. It often has only
_oneand_other. When the UI passes a count, the message has{{count}}in the value (e.g.deleteConnection_other: "Delete {{count}} connections"). Some keys have only_oneand no count, e.g.dagWarnings.error_one: "1 Error"; the code never calls that with count, so noerror_otheris ever used. For file upload, EN has onlyfiles_other: "{{count}} files"; a locale can addfiles_onefor "1 file" but EN doesn’t define it.admin.json (EN):
components.json (EN):
So for
deleteConnectionthe app does use count, so each locale needs all its plural forms for that base. FordagWarnings.errorit never uses count, so onlyerror_oneis needed; anyerror_otherorerror_zeroin a locale is never used. ForfileUpload.filesthe app uses count; something likefiles_onein PT is optional.Arabic has zero, one, two, few, many, other. For bases where EN has
{{count}}, AR needs all of those (e.g. deleteConnection_zero/one/two/few/many/other). FordagWarnings.error, EN has onlyerror_one, so at runtime only that is used; if AR haserror_zero,error_other, etc., they’re never used and the checker should list them in one "unused" bucket, not as a separate "extra" category.Portuguese usually needs only
_oneand_other. Same idea: if EN has no{{count}}for a base, only the EN keys are required; anything else in the locale (e.g.error_other,error_zero) is unused. If EN has{{count}}, PT only needs the plural forms that PT’s rules use; addingfiles_onefor "1 arquivo" is fine but not required by EN.I’m proposing the checker behave like this:
{{count}}, all plural forms that the locale’s language needs. So required = EN keys ∪ locale plural expansion only for those bases.{{count}}in EN). One list, no separate "extra."TODO: translate).--remove-extrato--remove-unusedand update docs/help.Acceptance criteria
{{count}}in EN.--remove-unusedand docs/help updated.