Skip to content

Commit 812ca92

Browse files
committed
fix(localizeText): accept { en: "" } as a valid translation (plan 61 S-E)
localizeText({ en: "" }) previously threw "textItems must have an english translation" because `!textItem.en` is falsy for an empty string. An empty string IS a valid translation (the author chose "no text" for that locale); only a genuinely missing `en` should throw. Switch the guard from `!textItem.en` to `textItem.en == null` so that: - null / undefined still throw (unchanged contract) - empty strings return as-is - empty strings in non-`en` locales fall through to the next preference via `!= null` check (was falsy check, which dropped empty strings) New regression test [LOLY] pins the behaviour. The textItem with consent: { en: "" } shape that the Chat preset writes was poisoning peekInvite in hds-webapp; the safeLocalize wrapper there can now be simplified.
1 parent 269523d commit 812ca92

2 files changed

Lines changed: 20 additions & 2 deletions

File tree

tests/localizeText.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,17 @@ describe('[LOCX] Localization', () => {
122122
assert.equal(e.message, 'textItems must have an english translation');
123123
}
124124
});
125+
126+
it('[LOLY] empty string `en` is a valid translation (author chose "no text")', () => {
127+
// Regression for S-2026-05-26-E: previously `!textItem.en` swallowed
128+
// empty strings and threw "textItems must have an english translation",
129+
// breaking invite peeks against Chat presets that wrote `consent: { en: "" }`.
130+
assert.equal(localizeText({ en: '' }), '');
131+
// Less-preferred locale set to `""` should also fall through to en.
132+
setPreferredLocales(['fr']);
133+
assert.equal(localizeText({ en: 'Hello', fr: '' }), '');
134+
assert.equal(localizeText({ en: 'Hello', fr: null }), 'Hello');
135+
assert.equal(localizeText({ en: 'Hello', fr: undefined }), 'Hello');
136+
});
125137
});
126138
});

ts/localizeText.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,18 @@ export function resetPreferredLocales (): void {
3737

3838
/**
3939
* return the translation of this item considering the setting of preffered language
40+
*
41+
* Empty strings `""` are valid translations (the author chose "no text"); the
42+
* function returns them as-is and falls through to less-preferred locales only
43+
* when a translation is genuinely `null`/`undefined`. Only a missing `en` key
44+
* throws.
4045
*/
4146
export function localizeText (textItem: localizableText | null): string | null {
4247
if (textItem == null) return null;
43-
if (!textItem.en) throw new HDSLibError('textItems must have an english translation', { textItem });
48+
if (textItem.en == null) throw new HDSLibError('textItems must have an english translation', { textItem });
4449
for (const l of preferredLocales) {
45-
if (textItem[l as keyof localizableText]) return textItem[l as keyof localizableText];
50+
const v = textItem[l as keyof localizableText];
51+
if (v != null) return v;
4652
}
4753
return textItem.en;
4854
}

0 commit comments

Comments
 (0)