fix(i18n): respect browser preferred languages when supported (#6812)

* fix(i18n): respect browser preferred languages when supported

Instead of relying on the first browser language, the application now
iterates through navigator.languages and selects the first supported
locale, with a fallback to English.

* chore: add the release notes related file

* fix(i18n): check region locales support before falling back to base locale

* fix(i18n): make the unit test aligned with the region locales checking
This commit is contained in:
Adam
2026-02-04 21:04:28 +01:00
committed by GitHub
parent 7732fac8b6
commit d8afc6b2be
3 changed files with 49 additions and 32 deletions

View File

@@ -71,7 +71,7 @@ describe('setI18NextLanguage', () => {
setI18NextLanguage('uk-ZZ');
expect(console.info).toHaveBeenCalledWith(
'Unknown locale uk-ZZ, falling back to uk',
'Unknown locale uk-ZZ, falling back to uk-zz',
);
expect(i18n.changeLanguage).toHaveBeenCalledWith('uk');
});

View File

@@ -40,44 +40,55 @@ i18n
},
});
const resolveLanguage = (language: string) => {
// English is always available since we use natural-language keys.
if (language === 'en') return 'en';
if (isLanguageAvailable(language)) return language;
const lowercaseLanguage = language.toLowerCase();
if (lowercaseLanguage !== language) {
console.info(
`Unknown locale ${language}, falling back to ${lowercaseLanguage}`,
);
return resolveLanguage(lowercaseLanguage);
}
if (language.includes('-')) {
const fallback = language.split('-')[0];
console.info(`Unknown locale ${language}, falling back to ${fallback}`);
return resolveLanguage(fallback);
}
return undefined;
};
export const setI18NextLanguage = (language: string) => {
if (!language) {
// System default
setI18NextLanguage(navigator.language || 'en');
return;
const defaultLanguages = Array.isArray(navigator.languages)
? navigator.languages
: [navigator.language || 'en'];
const languagesToTry = language ? [language] : defaultLanguages;
let resolved: string | undefined;
for (const lang of languagesToTry) {
resolved = resolveLanguage(lang);
if (resolved) break;
}
if (!isLanguageAvailable(language)) {
if (language === 'en') {
// English is always available since we use natural-language keys.
return;
}
if (language.includes('-')) {
const fallback = language.split('-')[0];
console.info(`Unknown locale ${language}, falling back to ${fallback}`);
setI18NextLanguage(fallback);
return;
}
const lowercaseLanguage = language.toLowerCase();
if (lowercaseLanguage !== language) {
console.info(
`Unknown locale ${language}, falling back to ${lowercaseLanguage}`,
);
setI18NextLanguage(lowercaseLanguage);
return;
}
if (!resolved) {
// Fall back to English
console.info(`Unknown locale ${language}, falling back to en`);
setI18NextLanguage('en');
return;
console.info(
language
? `Unknown locale ${language}, falling back to en`
: `Unknown locales [${languagesToTry.join(', ')}] falling back to en`,
);
resolved = 'en';
}
if (language === i18n.language) {
if (resolved === i18n.language) {
return; // language is already set
}
i18n.changeLanguage(language || 'en');
i18n.changeLanguage(resolved);
};

View File

@@ -0,0 +1,6 @@
---
category: Bugfixes
authors: [elevennprime]
---
The app now checks your preferred browser languages in order and uses the first one we support, otherwise English.