diff --git a/ts/test-node/util/resolveCanonicalLocales_test.ts b/ts/test-node/util/resolveCanonicalLocales_test.ts new file mode 100644 index 00000000000..273a46ce863 --- /dev/null +++ b/ts/test-node/util/resolveCanonicalLocales_test.ts @@ -0,0 +1,22 @@ +// Copyright 2024 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +import assert from 'node:assert/strict'; +import { resolveCanonicalLocales } from '../../util/resolveCanonicalLocales'; + +describe('resolveCanonicalLocales', () => { + it('returns an array of canonical locales', () => { + assert.deepEqual( + resolveCanonicalLocales(['EN', 'EN-US', 'EN-GB', 'FR', 'FR-FR']), + ['en', 'en-US', 'en-GB', 'fr', 'fr-FR'] + ); + }); + + it('removes invalid locales', () => { + assert.deepEqual(resolveCanonicalLocales(['!@#$', 'POSIX', 'en']), ['en']); + }); + + it('defaults to en if no valid locales are provided', () => { + assert.deepEqual(resolveCanonicalLocales(['!@#$']), ['en']); + }); +}); diff --git a/ts/util/resolveCanonicalLocales.ts b/ts/util/resolveCanonicalLocales.ts index 3517f582004..f52d999467b 100644 --- a/ts/util/resolveCanonicalLocales.ts +++ b/ts/util/resolveCanonicalLocales.ts @@ -2,13 +2,18 @@ // SPDX-License-Identifier: AGPL-3.0-only export function resolveCanonicalLocales(locales: Array): Array { - return Intl.getCanonicalLocales( - locales.flatMap(locale => { - try { - return Intl.getCanonicalLocales(locale); - } catch { - return 'en'; - } - }) - ); + const validLocales = locales.filter(locale => { + try { + // Test if the locale is valid + new Intl.Locale(locale).maximize(); + return true; + } catch { + return false; + } + }); + const canonical = Intl.getCanonicalLocales(validLocales); + if (canonical.length === 0) { + return ['en']; + } + return canonical; }