From add5c128ceada5a54ccb1be618e2e4d2628bfae1 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Sun, 21 Apr 2024 14:23:34 +0200 Subject: [PATCH] fix: Localisation-matching algorithm missing some edgecase (#4692) --- src/i18n.js | 19 +++++++++++--- test/cypress/unit/i18n.spec.js | 48 ++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/i18n.js b/src/i18n.js index ad3894d4..b7c32496 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -63,9 +63,22 @@ const rtlLangs = [ "fa", "ar-SY", "ur" ]; * @returns {string} the locale that should be displayed */ export function currentLocale() { - const potentialLocales = [ localStorage.locale, navigator.language, navigator.language.substring(0, 2), ...navigator.languages ]; - const availableLocales = potentialLocales.filter(l => languageList[l]); - return availableLocales[0] || "en"; + for (const locale of [ localStorage.locale, navigator.language, ...navigator.languages ]) { + // localstorage might not have a value or there might not be a language in `navigator.language` + if (!locale) { + continue; + } + if (locale in messages) { + return locale; + } + // some locales are further specified such as "en-US". + // If we only have a generic locale for this, we can use it too + const genericLocale = locale.split("-")[0]; + if (genericLocale in messages) { + return genericLocale; + } + } + return "en"; } export const localeDirection = () => { diff --git a/test/cypress/unit/i18n.spec.js b/test/cypress/unit/i18n.spec.js index c53f341f..c8352a76 100644 --- a/test/cypress/unit/i18n.spec.js +++ b/test/cypress/unit/i18n.spec.js @@ -3,46 +3,62 @@ import { currentLocale } from "../../../src/i18n"; describe("Test i18n.js", () => { it("currentLocale()", () => { - const setLanguage = (language) => { - Object.defineProperty(window.navigator, 'language', { - value: language, + const setLanguages = (languages) => { + Object.defineProperty(navigator, 'language', { + value: languages[0], writable: true }); - Object.defineProperty(window.navigator, 'languages', { - value: [language], + Object.defineProperty(navigator, 'languages', { + value: languages, writable: true }); } - setLanguage('en-EN'); + setLanguages(['en-EN']); expect(currentLocale()).equal("en"); - setLanguage('zh-HK'); + setLanguages(['zh-HK']); expect(currentLocale()).equal("zh-HK"); // Note that in Safari on iOS prior to 10.2, the country code returned is lowercase: "en-us", "fr-fr" etc. // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language - setLanguage('zh-hk'); + setLanguages(['zh-hk']); expect(currentLocale()).equal("en"); - setLanguage('en-US'); + setLanguages(['en-US']); expect(currentLocale()).equal("en"); - setLanguage('ja-ZZ'); + setLanguages(['ja-ZZ']); expect(currentLocale()).equal("ja"); - setLanguage('zz-ZZ'); + setLanguages(['zz-ZZ']); expect(currentLocale()).equal("en"); - setLanguage('zz-ZZ'); + setLanguages(['zz-ZZ']); expect(currentLocale()).equal("en"); - setLanguage('en'); - localStorage.locale = "en"; + setLanguages(['en-US', 'en', 'pl', 'ja']); expect(currentLocale()).equal("en"); - localStorage.locale = "zh-HK"; - expect(currentLocale()).equal("zh-HK"); + setLanguages(['en-US', 'pl', 'ja']); + expect(currentLocale()).equal("en"); + + setLanguages(['abc', 'en-US', 'pl', 'ja']); + expect(currentLocale()).equal("en"); + + setLanguages(['fil-PH', 'pl']); + expect(currentLocale()).equal("pl"); + + setLanguages(['shi-Latn-MA', 'pl']); + expect(currentLocale()).equal("pl"); + + setLanguages(['pl']); + localStorage.locale = "ja-ZZ"; + expect(currentLocale()).equal("ja"); + + setLanguages(['pl']); + localStorage.locale = "invalid-lang"; + expect(currentLocale()).equal("pl"); }); });