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

@@ -9,12 +9,12 @@
import { useEffect, useState } from 'react';
import IconButton from '@mui/material/IconButton';
import RefreshIcon from '@mui/icons-material/Refresh';
import { useTranslation } from 'react-i18next';
import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import ClearIcon from '@mui/icons-material/Clear';
import Stack from '@mui/material/Stack';
import { useLingui } from '@lingui/react/macro';
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { makeToast } from '@/base/utils/Toast.ts';
@@ -22,8 +22,8 @@ import { Progress } from '@/base/components/feedback/Progress.tsx';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { dateTimeFormatter } from '@/base/utils/DateHelper.ts';
import { MediaQuery } from '@/base/utils/MediaQuery.tsx';
import { CategoryIdInfo } from '@/features/category/Category.types.ts';
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
let lastRunningState = false;
@@ -35,17 +35,20 @@ export function UpdateChecker({
categoryId?: CategoryIdInfo['id'];
handleFinishedUpdate?: () => void;
}) {
const { t } = useTranslation();
const { t } = useLingui();
const isTouchDevice = MediaQuery.useIsTouchDevice();
const [isHovered, setIsHovered] = useState(false);
const { data: lastUpdateTimestampData, refetch: reFetchLastTimestamp } =
requestManager.useGetLastGlobalUpdateTimestamp();
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
const { data: updaterData } = requestManager.useGetGlobalUpdateSummary();
const status = updaterData?.libraryUpdateStatus;
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
const date = lastUpdateTimestamp ? dateTimeFormatter.format(+lastUpdateTimestamp) : '-';
const isRunning = !!status?.jobsInfo.isRunning;
const progress = status ? (status.jobsInfo.finishedJobs / status.jobsInfo.totalJobs) * 100 : 0;
@@ -72,7 +75,7 @@ export function UpdateChecker({
reFetchLastTimestamp().catch(defaultPromiseErrorHandler('UpdateChecker::reFetchLastTimestamp'));
} catch (e) {
lastRunningState = false;
makeToast(t('global.error.label.update_failed'), 'error', getErrorMessage(e));
makeToast(t`Could not check for updates`, 'error', getErrorMessage(e));
}
};
@@ -80,7 +83,7 @@ export function UpdateChecker({
try {
await requestManager.resetGlobalUpdate();
} catch (e) {
makeToast(t('library.error.label.stop_global_update'), 'error', getErrorMessage(e));
makeToast(t`Could not stop global update`, 'error', getErrorMessage(e));
}
};
@@ -96,15 +99,7 @@ export function UpdateChecker({
<PopupState variant="popover" popupId="library-update-checker-menu">
{(popupState) => (
<>
<CustomTooltip
title={
isRunning
? t('library.action.label.stop_update')
: t('library.settings.global_update.label.last_update_tooltip', {
date: lastUpdateTimestamp ? dateTimeFormatter.format(+lastUpdateTimestamp) : '-',
})
}
>
<CustomTooltip title={isRunning ? t`Stop global update` : t`Global update (last update: ${date})`}>
<IconButton
sx={{ position: 'relative' }}
{...(categoryId !== undefined && !isRunning
@@ -137,7 +132,7 @@ export function UpdateChecker({
onClick();
}}
>
{t('library.action.label.update_library')}
{t`Update library`}
</MenuItem>
<MenuItem
onClick={() => {
@@ -145,7 +140,7 @@ export function UpdateChecker({
onClick(categoryId);
}}
>
{t('library.action.label.update_category')}
{t`Update category`}
</MenuItem>
</Menu>
</>

View File

@@ -8,7 +8,7 @@
import Typography from '@mui/material/Typography';
import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
import { EmptyViewAbsoluteCentered } from '@/base/components/feedback/EmptyViewAbsoluteCentered.tsx';
@@ -27,7 +27,7 @@ import { useAppTitleAndAction } from '@/features/navigation-bar/hooks/useAppTitl
import { GROUPED_VIRTUOSO_Z_INDEX } from '@/lib/virtuoso/Virtuoso.constants.ts';
export const Updates: React.FC = () => {
const { t } = useTranslation();
const { t } = useLingui();
const { appBarHeight } = useNavBarContext();
const {
@@ -71,8 +71,9 @@ export const Updates: React.FC = () => {
fetchPolicy: 'cache-only',
});
const lastUpdateTimestamp = lastUpdateTimestampData?.lastUpdateTimestamp.timestamp;
const date = lastUpdateTimestamp ? dateTimeFormatter.format(+lastUpdateTimestamp) : '-';
useAppTitleAndAction(t('updates.title'), <UpdateChecker />);
useAppTitleAndAction(t`Updates`, <UpdateChecker />);
const loadMore = useCallback(() => {
if (!hasNextPage) {
@@ -85,7 +86,7 @@ export const Updates: React.FC = () => {
if (error) {
return (
<EmptyViewAbsoluteCentered
message={t('global.error.label.failed_to_load_data')}
message={t`Unable to load data`}
messageExtra={getErrorMessage(error)}
retry={() => refetch().catch(defaultPromiseErrorHandler('Updates::refetch'))}
/>
@@ -93,7 +94,7 @@ export const Updates: React.FC = () => {
}
if (!isLoading && updateEntries.length === 0) {
return <EmptyViewAbsoluteCentered message={t('updates.error.label.no_updates_available')} />;
return <EmptyViewAbsoluteCentered message={t`You don't have any updates yet.`} />;
}
return (
@@ -109,9 +110,7 @@ export const Updates: React.FC = () => {
paddingTop: (theme) => ({ [theme.breakpoints.up('sm')]: { paddingTop: '6px' } }),
}}
>
{t('library.settings.global_update.label.last_update', {
date: lastUpdateTimestamp ? dateTimeFormatter.format(+lastUpdateTimestamp) : '-',
})}
{t`Last update: ${date}`}
</Typography>
<StyledGroupedVirtuoso
persistKey="updates"