mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-09 06:03:01 -05:00
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:
@@ -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');
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
6
upcoming-release-notes/6812.md
Normal file
6
upcoming-release-notes/6812.md
Normal 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.
|
||||
Reference in New Issue
Block a user