Migrate to lingui

Switch to "lingui" for better DX.
Tried to persist existing languages as much as possible.

Removed "vite-plugin-node-polyfills" because it's incompatible with "lingui"
This commit is contained in:
schroda
2026-01-10 19:45:02 +01:00
parent c1ac58f4d6
commit 65a9a905be
287 changed files with 120766 additions and 37748 deletions

View File

@@ -6,66 +6,47 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { use } from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import HttpBackend from 'i18next-http-backend';
import { SubpathUtil } from '@/lib/utils/SubpathUtil.ts';
import { i18n } from '@lingui/core';
import { DEFAULT_LANGUAGE, getISOLanguage, getPreferredISOLanguageCodes } from '@/lib/ISOLanguageUtil.ts';
import { AppStorage } from '@/lib/storage/AppStorage.ts';
import localesConfig from '@/i18n/locales.json';
/**
* Keys have to match {@link IsoLanguages} codes, they're used for showing the language name in the dropdown in the {@link Settings}.<br/>
* In case there is no language code for the key in {@link IsoLanguages}, the corresponding language has to be added
*
* **IMPORTANT:**
*
* This is generated by the `i18n:gen-resources` script
*/
export const i18nResources = [
'de',
'en',
'es',
'fa',
'fr',
'it',
'ja',
'ko',
'pl',
'pt-BR',
'pt',
'ru',
'ta',
'tr',
'vi',
'zh_Hans',
'zh_Hant',
] as const;
export const i18nResources = localesConfig.locales;
export type I18nResourceCode = (typeof i18nResources)[number];
export const i18n = use(initReactI18next)
.use(HttpBackend)
.use(LanguageDetector)
.init({
supportedLngs: i18nResources,
fallbackLng: 'en',
const DEFAULT_LOCALE = localesConfig.defaultLocale;
backend: {
loadPath: `${SubpathUtil.getSubpath()}/locales/{{lng}}.json`,
allowMultiLoading: true,
},
const SELECTED_LANGUAGE_CODE_KEY = 'i18n:selected-language';
interpolation: {
escapeValue: false,
format: (value, format) => {
switch (format) {
case 'lowercase':
return value.toLocaleLowerCase();
default:
return value;
}
},
},
export async function loadCatalog(locale: string): Promise<void> {
const localeToLoad = i18nResources.includes(locale as (typeof i18nResources)[number]) ? locale : DEFAULT_LOCALE;
returnNull: false,
debug: process.env.NODE_ENV !== 'production',
});
const { messages } = await import(`./locales/${localeToLoad}.po`);
i18n.loadAndActivate({ locale: localeToLoad, messages });
AppStorage.local.setItem(SELECTED_LANGUAGE_CODE_KEY, localeToLoad);
}
function detectLocale(): string {
const storedLanguage = AppStorage.local.getItem(SELECTED_LANGUAGE_CODE_KEY);
const preferredLanguages = getPreferredISOLanguageCodes();
const languageCodes = [storedLanguage, ...preferredLanguages];
const normalizedLanguageCodes = languageCodes
.filter((code) => code !== null)
.filter((code) => getISOLanguage(code))
.filter((code) => i18nResources.includes(code as (typeof i18nResources)[number]));
return normalizedLanguageCodes[0] ?? DEFAULT_LANGUAGE;
}
export async function initializeLocalization(): Promise<void> {
try {
await loadCatalog(detectLocale());
} catch (e) {
await loadCatalog(DEFAULT_LOCALE);
}
}
export { i18n };

23
src/i18n/locales.json Normal file
View File

@@ -0,0 +1,23 @@
{
"comment": "!!!IMPORTANT!!!: 'locales' is auto generated by tools/scripts/weblate/generatei18nResources.ts. Do not edit manually.",
"locales": [
"de",
"en",
"es",
"fa",
"fr",
"it",
"ja",
"ko",
"pl",
"pt-BR",
"pt",
"ru",
"ta",
"tr",
"vi",
"zh_Hans",
"zh_Hant"
],
"defaultLocale": "en"
}

4603
src/i18n/locales/ar.po Normal file

File diff suppressed because it is too large Load Diff

4588
src/i18n/locales/bn.po Normal file

File diff suppressed because it is too large Load Diff

4588
src/i18n/locales/ca.po Normal file

File diff suppressed because it is too large Load Diff

4588
src/i18n/locales/da.po Normal file

File diff suppressed because it is too large Load Diff

3691
src/i18n/locales/de.po Normal file

File diff suppressed because it is too large Load Diff

3698
src/i18n/locales/en.po Normal file

File diff suppressed because it is too large Load Diff

3688
src/i18n/locales/es.po Normal file

File diff suppressed because it is too large Load Diff

3691
src/i18n/locales/fa.po Normal file

File diff suppressed because it is too large Load Diff

4592
src/i18n/locales/fil.po Normal file

File diff suppressed because it is too large Load Diff

3688
src/i18n/locales/fr.po Normal file

File diff suppressed because it is too large Load Diff

4597
src/i18n/locales/id.po Normal file

File diff suppressed because it is too large Load Diff

3688
src/i18n/locales/it.po Normal file

File diff suppressed because it is too large Load Diff

3688
src/i18n/locales/ja.po Normal file

File diff suppressed because it is too large Load Diff

3691
src/i18n/locales/ko.po Normal file

File diff suppressed because it is too large Load Diff

4588
src/i18n/locales/nb-NO.po Normal file

File diff suppressed because it is too large Load Diff

4593
src/i18n/locales/nl.po Normal file

File diff suppressed because it is too large Load Diff

3688
src/i18n/locales/pl.po Normal file

File diff suppressed because it is too large Load Diff

3677
src/i18n/locales/pt-BR.po Normal file

File diff suppressed because it is too large Load Diff

3685
src/i18n/locales/pt.po Normal file

File diff suppressed because it is too large Load Diff

4588
src/i18n/locales/ro.po Normal file

File diff suppressed because it is too large Load Diff

3691
src/i18n/locales/ru.po Normal file

File diff suppressed because it is too large Load Diff

4588
src/i18n/locales/sv.po Normal file

File diff suppressed because it is too large Load Diff

3688
src/i18n/locales/ta.po Normal file

File diff suppressed because it is too large Load Diff

4588
src/i18n/locales/th.po Normal file

File diff suppressed because it is too large Load Diff

3681
src/i18n/locales/tr.po Normal file

File diff suppressed because it is too large Load Diff

4603
src/i18n/locales/uk.po Normal file

File diff suppressed because it is too large Load Diff

3691
src/i18n/locales/vi.po Normal file

File diff suppressed because it is too large Load Diff

3691
src/i18n/locales/zh_Hans.po Normal file

File diff suppressed because it is too large Load Diff

3685
src/i18n/locales/zh_Hant.po Normal file

File diff suppressed because it is too large Load Diff