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

@@ -8,8 +8,8 @@
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { useTranslation } from 'react-i18next';
import { INSTALLED_STATE_TO_TRANSLATION_KEY_MAP } from '@/features/extension/Extensions.constants.ts';
import { useLingui } from '@lingui/react/macro';
import { INSTALLED_STATE_TO_TRANSLATION_MAP } from '@/features/extension/Extensions.constants.ts';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { getInstalledState, updateExtension } from '@/features/extension/Extensions.utils.ts';
import { useBackButton } from '@/base/hooks/useBackButton.ts';
@@ -17,7 +17,7 @@ import { ExtensionAction, InstalledState, TExtension } from '@/features/extensio
export const ActionButton = ({ pkgName, isInstalled, isObsolete, hasUpdate }: TExtension) => {
const handleBack = useBackButton();
const { t } = useTranslation();
const { t } = useLingui();
const installedState = getInstalledState(isInstalled, isObsolete, hasUpdate);
@@ -44,7 +44,7 @@ export const ActionButton = ({ pkgName, isInstalled, isObsolete, hasUpdate }: TE
}
}}
>
{t(INSTALLED_STATE_TO_TRANSLATION_KEY_MAP[installedState])}
{t(INSTALLED_STATE_TO_TRANSLATION_MAP[installedState])}
</Button>
</Box>
);

View File

@@ -7,25 +7,19 @@
*/
import Stack from '@mui/material/Stack';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { TExtension } from '@/features/extension/Extensions.types.ts';
import { ExtensionMetadata } from '@/features/extension/info/components/ExtensionMetadata.tsx';
import { languageCodeToName } from '@/base/utils/Languages.ts';
export const Meta = ({ versionName, lang, isNsfw }: TExtension) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<Stack sx={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
<ExtensionMetadata title={t('global.label.version')} value={versionName} />
<ExtensionMetadata title={t('global.language.label.language')} value={languageCodeToName(lang)} />
{isNsfw && (
<ExtensionMetadata
title={t('extension.label.age_rating')}
value="18+"
valueProps={{ color: 'error' }}
/>
)}
<ExtensionMetadata title={t`Version`} value={versionName} />
<ExtensionMetadata title={t`Language`} value={languageCodeToName(lang)} />
{isNsfw && <ExtensionMetadata title={t`Age rating`} value="18+" valueProps={{ color: 'error' }} />}
</Stack>
);
};

View File

@@ -7,13 +7,13 @@
*/
import Typography from '@mui/material/Typography';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import Card from '@mui/material/Card';
import IconButton from '@mui/material/IconButton';
import SettingsIcon from '@mui/icons-material/Settings';
import Switch from '@mui/material/Switch';
import CardActionArea from '@mui/material/CardActionArea';
import { useLingui } from '@lingui/react/macro';
import { MUIUtil } from '@/lib/mui/MUI.util.ts';
import { AppRoutes } from '@/base/AppRoute.constants.ts';
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
@@ -29,11 +29,11 @@ import { SourceConfigurableInfo, SourceIdInfo, SourceLanguageInfo } from '@/feat
export const SourceCard = (source: SourceIdInfo & SourceLanguageInfo & SourceConfigurableInfo) => {
const { id, isConfigurable } = source;
const { t } = useTranslation();
const { t } = useLingui();
const { isEnabled } = useGetSourceMetadata(source);
const updateSetting = createUpdateSourceMetadata(source, (e) =>
makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)),
makeToast(t`Failed to save changes`, 'error', getErrorMessage(e)),
);
return (
@@ -45,7 +45,7 @@ export const SourceCard = (source: SourceIdInfo & SourceLanguageInfo & SourceCon
{translateExtensionLanguage(Sources.getLanguage(source))}
</Typography>
{isConfigurable && (
<CustomTooltip title={t('settings.title')}>
<CustomTooltip title={t`Settings`}>
<IconButton
component={Link}
to={AppRoutes.sources.childRoutes.configure.path(id)}

View File

@@ -8,9 +8,9 @@
import Box from '@mui/material/Box';
import Stack from '@mui/material/Stack';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';
import { useMemo } from 'react';
import { useLingui } from '@lingui/react/macro';
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { EmptyViewAbsoluteCentered } from '@/base/components/feedback/EmptyViewAbsoluteCentered.tsx';
@@ -26,10 +26,10 @@ import { ActionButton } from '@/features/extension/info/components/ActionButton.
import { SourceCard } from '@/features/extension/info/components/SourceCard.tsx';
export const ExtensionInfo = () => {
const { t } = useTranslation();
const { t } = useLingui();
const { pkgName } = useParams<{ pkgName: string }>();
useAppTitle(t('source.extension_info.title'));
useAppTitle(t`Extension info`);
const extensionResponse = requestManager.useGetExtension(pkgName);
const sourcesResponse = requestManager.useGetSourceList();
@@ -55,7 +55,7 @@ export const ExtensionInfo = () => {
if (error) {
return (
<EmptyViewAbsoluteCentered
message={t('global.error.label.failed_to_load_data')}
message={t`Unable to load data`}
messageExtra={getErrorMessage(extensionResponse.error)}
retry={() => {
if (extensionResponse.error) {