i18n: parity checks itself, over the locales actually on disk
master was out of parity and every test was green. sv-SE named commandHq.referencePath and referencePathHint; en-GB named workingDirectory and cwdHint. Two reasons neither was caught. The three parity tests LISTED their locales literally, so adding a sixth added a file none of them looked at. A guard that has to be maintained to keep guarding is the thing it exists to prevent — the same shape as the bug that made three locales ship dead last night. They now read the directory. And findMissingKeys is one-directional: it asks whether every English key is present, so a rename reports half of itself. The new key is missing and caught; the stale one the translation still carries is invisible. findExtraKeys is the other half, and both are asserted. Realigns sv-SE onto the committed key names. It was translated from a working tree where that rename existed and was not yet committed — the commander directory work, still unreviewed — so on master it named keys English did not have. The rename will land across all six locales together when that work does. Also asserts there IS at least one locale besides en-GB, because otherwise every assertion passes over an empty set and reports nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
@@ -2,7 +2,7 @@ export { I18nProvider, I18nContext } from './I18nProvider';
|
||||
export { useTranslation } from './useTranslation';
|
||||
export { useFormat } from './useFormat';
|
||||
export { resolveKey, interpolate, isPluralForms, localeDirection } from './resolve';
|
||||
export { findMissingKeys } from './parity';
|
||||
export { findMissingKeys, findExtraKeys } from './parity';
|
||||
// Deliberately NOT re-exporting translateStandalone — see standalone.ts on why it is awkward to reach.
|
||||
export { activeLocale } from './standalone';
|
||||
export type { MissingKey } from './parity';
|
||||
|
||||
@@ -25,3 +25,24 @@ export const findMissingKeys = (en: Catalog, locales: Record<string, Catalog>):
|
||||
return enKeys.filter((key) => !ownKeys.has(key)).map((key) => ({ locale, key }));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Keys a locale has that `en-GB` does NOT — the other direction, and it is not symmetry for its own sake.
|
||||
*
|
||||
* A locale written against a source that has since changed keeps the old names, and `findMissingKeys`
|
||||
* cannot see that: it only asks whether every English key is present. Rename a key and the translated
|
||||
* catalogue holds both the new one (missing, caught) and the stale one (extra, invisible), so half the
|
||||
* problem is reported and the file quietly grows dead entries.
|
||||
*
|
||||
* It happened the day sv-SE landed. It was translated from a working tree where two keys had been renamed
|
||||
* and that rename was not yet committed, so on `master` the Swedish catalogue named two keys English did
|
||||
* not have — and every parity test passed, because none of them looked in this direction.
|
||||
*/
|
||||
export const findExtraKeys = (en: Catalog, locales: Record<string, Catalog>): MissingKey[] => {
|
||||
const enKeys = new Set(flattenKeys(en));
|
||||
return Object.entries(locales).flatMap(([locale, catalog]) =>
|
||||
flattenKeys(catalog)
|
||||
.filter((key) => !enKeys.has(key))
|
||||
.map((key) => ({ locale, key })),
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user