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:
@@ -6,12 +6,12 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import ListItemAvatar from '@mui/material/ListItemAvatar';
|
||||
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { makeToast } from '@/base/utils/Toast.ts';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { Trackers } from '@/features/tracker/services/Trackers.ts';
|
||||
@@ -21,7 +21,7 @@ import { AvatarSpinner } from '@/base/components/AvatarSpinner.tsx';
|
||||
import { CredentialsLogin } from '@/base/components/modals/LoginDialog.tsx';
|
||||
|
||||
export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
const isOAuthLogin = !tracker.isLoggedIn && !!tracker.authUrl;
|
||||
|
||||
@@ -29,7 +29,7 @@ export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) =>
|
||||
try {
|
||||
await requestManager.logoutFromTracker(tracker.id).response;
|
||||
} catch (e) {
|
||||
makeToast(t('tracking.action.logout.label.failure', { name: tracker.name }), 'error', getErrorMessage(e));
|
||||
makeToast(t`Could not log out from ${tracker.name}`, 'error', getErrorMessage(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) =>
|
||||
try {
|
||||
await requestManager.loginTrackerCredentials(tracker.id, username, password).response;
|
||||
} catch (e) {
|
||||
makeToast(t('tracking.action.login.label.failure', { name: tracker.name }), 'error', getErrorMessage(e));
|
||||
makeToast(t`Could not log in to ${tracker.name}`, 'error', getErrorMessage(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -68,12 +68,7 @@ export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) =>
|
||||
|
||||
const controlled = CredentialsLogin.showControlled(
|
||||
{
|
||||
title: t(
|
||||
Trackers.isLoggedIn(tracker)
|
||||
? 'tracking.settings.dialog.title.log_out'
|
||||
: 'tracking.settings.dialog.title.log_in',
|
||||
{ name: tracker.name },
|
||||
),
|
||||
title: Trackers.isLoggedIn(tracker) ? t`Log out from ${tracker.name}` : t`Log in to ${tracker.name}`,
|
||||
isLoading: false,
|
||||
isLoggedIn: Trackers.isLoggedIn(tracker),
|
||||
username: initialUsername,
|
||||
@@ -90,11 +85,7 @@ export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) =>
|
||||
|
||||
controlled.submit();
|
||||
} catch (e) {
|
||||
makeToast(
|
||||
t('tracking.action.logout.label.failure', { name: tracker.name }),
|
||||
'error',
|
||||
getErrorMessage(e),
|
||||
);
|
||||
makeToast(t`Could not log out from ${tracker.name}`, 'error', getErrorMessage(e));
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -105,11 +96,7 @@ export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) =>
|
||||
|
||||
controlled.submit();
|
||||
} catch (e) {
|
||||
makeToast(
|
||||
t('tracking.action.login.label.failure', { name: tracker.name }),
|
||||
'error',
|
||||
getErrorMessage(e),
|
||||
);
|
||||
makeToast(t`Could not log in to ${tracker.name}`, 'error', getErrorMessage(e));
|
||||
|
||||
const RETRY_KEY = '__retry__';
|
||||
const retry = await Promise.race([controlled.promise, Promise.resolve(RETRY_KEY)]);
|
||||
@@ -145,7 +132,7 @@ export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) =>
|
||||
<ListItemText primary={tracker.name} />
|
||||
{Trackers.isLoggedIn(tracker) && (
|
||||
<ListItemSecondaryAction>
|
||||
<Chip label={t('global.label.logged_in')} color="success" />
|
||||
<Chip label={t`Logged in`} color="success" />
|
||||
</ListItemSecondaryAction>
|
||||
)}
|
||||
</ListItemButton>
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import Card from '@mui/material/Card';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Box from '@mui/material/Box';
|
||||
import Button from '@mui/material/Button';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
@@ -28,6 +27,7 @@ import PopupState, { bindDialog, bindMenu, bindTrigger } from 'material-ui-popup
|
||||
import { useMemo, useState } from 'react';
|
||||
import Badge from '@mui/material/Badge';
|
||||
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { Trackers } from '@/features/tracker/services/Trackers.ts';
|
||||
@@ -63,7 +63,7 @@ const TrackerActiveRemoveBind = ({
|
||||
onClick: () => void;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
const [removeRemoteTracking, setRemoveRemoteTracking] = useState(false);
|
||||
|
||||
@@ -71,8 +71,8 @@ const TrackerActiveRemoveBind = ({
|
||||
onClose();
|
||||
requestManager
|
||||
.unbindTracker(trackerRecordId, removeRemoteTracking)
|
||||
.response.then(() => makeToast(t('manga.action.track.remove.label.success'), 'success'))
|
||||
.catch((e) => makeToast(t('manga.action.track.remove.label.error'), 'error', getErrorMessage(e)));
|
||||
.response.then(() => makeToast(t`Untracked manga`, 'success'))
|
||||
.catch((e) => makeToast(t`Could not untrack manga`, 'error', getErrorMessage(e)));
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -86,7 +86,7 @@ const TrackerActiveRemoveBind = ({
|
||||
popupState.open();
|
||||
}}
|
||||
>
|
||||
{t('global.button.remove')}
|
||||
{t`Remove`}
|
||||
</MenuItem>
|
||||
<Dialog
|
||||
{...bindDialog(popupState)}
|
||||
@@ -95,18 +95,14 @@ const TrackerActiveRemoveBind = ({
|
||||
popupState.close();
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
{t('manga.action.track.remove.dialog.label.title', { tracker: tracker.name })}
|
||||
</DialogTitle>
|
||||
<DialogTitle>{t`Remove ${tracker.name} tracking?`}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<Typography>{t('manga.action.track.remove.dialog.label.description')}</Typography>
|
||||
<Typography>{t`This will remove the tracking locally.`}</Typography>
|
||||
{tracker.supportsTrackDeletion && (
|
||||
<FormGroup>
|
||||
<CheckboxInput
|
||||
disabled={false}
|
||||
label={t('manga.action.track.remove.dialog.label.delete_remote_track', {
|
||||
tracker: tracker.name,
|
||||
})}
|
||||
label={t`Also remove from ${tracker.name}`}
|
||||
checked={removeRemoteTracking}
|
||||
onChange={(_, checked) => setRemoveRemoteTracking(checked)}
|
||||
/>
|
||||
@@ -121,7 +117,7 @@ const TrackerActiveRemoveBind = ({
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
{t('global.button.cancel')}
|
||||
{t`Cancel`}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
@@ -130,7 +126,7 @@ const TrackerActiveRemoveBind = ({
|
||||
removeBind();
|
||||
}}
|
||||
>
|
||||
{t('global.button.ok')}
|
||||
{t`Ok`}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
@@ -151,7 +147,7 @@ const TrackerUpdatePrivateStatus = ({
|
||||
closeMenu: () => void;
|
||||
supportsPrivateTracking: TTrackerActive['supportsPrivateTracking'];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
if (!supportsPrivateTracking) {
|
||||
return null;
|
||||
@@ -162,13 +158,11 @@ const TrackerUpdatePrivateStatus = ({
|
||||
onClick={() => {
|
||||
requestManager
|
||||
.updateTrackerBind(trackRecordId, { private: !isPrivate })
|
||||
.response.catch((e) =>
|
||||
makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)),
|
||||
);
|
||||
.response.catch((e) => makeToast(t`Failed to save changes`, 'error', getErrorMessage(e)));
|
||||
closeMenu();
|
||||
}}
|
||||
>
|
||||
{t(isPrivate ? 'tracking.action.button.track_publicly' : 'tracking.action.button.track_privately')}
|
||||
{isPrivate ? t`Track publicly` : t`Track privately`}
|
||||
</MenuItem>
|
||||
);
|
||||
};
|
||||
@@ -183,7 +177,7 @@ const TrackerActiveHeader = ({
|
||||
tracker: TTrackerActive;
|
||||
openSearch: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
return (
|
||||
<Stack
|
||||
@@ -218,7 +212,6 @@ const TrackerActiveHeader = ({
|
||||
/>
|
||||
</TrackerActiveLink>
|
||||
</Badge>
|
||||
|
||||
<ListItemButton sx={{ flexGrow: 1 }} onClick={openSearch}>
|
||||
<CustomTooltip title={trackRecord.title}>
|
||||
<TypographyMaxLines flexGrow={1} lines={1}>
|
||||
@@ -243,9 +236,7 @@ const TrackerActiveHeader = ({
|
||||
key={`tracker-active-menu-item-browser-${tracker.id}`}
|
||||
url={trackRecord.remoteUrl}
|
||||
>
|
||||
<MenuItem onClick={() => onClose()}>
|
||||
{t('global.label.open_in_browser')}
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => onClose()}>{t`Open in browser`}</MenuItem>
|
||||
</TrackerActiveLink>,
|
||||
<TrackerActiveRemoveBind
|
||||
key={`tracker-active-menu-item-remove-${tracker.id}`}
|
||||
@@ -287,7 +278,7 @@ export const TrackerActiveCard = ({
|
||||
tracker: TTrackerBind;
|
||||
onClick: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
const isScoreUnset = isUnsetScore(trackRecord.displayScore);
|
||||
const currentScore = isScoreUnset ? tracker.scores[0] : trackRecord.displayScore;
|
||||
@@ -306,9 +297,7 @@ export const TrackerActiveCard = ({
|
||||
const updateTrackerBind = (patch: Parameters<typeof requestManager.updateTrackerBind>[1]) => {
|
||||
requestManager
|
||||
.updateTrackerBind(trackRecord.id, patch)
|
||||
.response.catch((e) =>
|
||||
makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)),
|
||||
);
|
||||
.response.catch((e) => makeToast(t`Failed to save changes`, 'error', getErrorMessage(e)));
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -320,7 +309,7 @@ export const TrackerActiveCard = ({
|
||||
<Box sx={{ padding: 1 }}>
|
||||
<TrackerActiveCardInfoRow>
|
||||
<ListPreference
|
||||
ListPreferenceTitle={t('manga.label.status')}
|
||||
ListPreferenceTitle={t`Status`}
|
||||
entries={tracker.statuses.map((status) => status.name)}
|
||||
key="status"
|
||||
type="ListPreference"
|
||||
@@ -331,8 +320,8 @@ export const TrackerActiveCard = ({
|
||||
/>
|
||||
<Divider orientation="vertical" flexItem />
|
||||
<NumberSetting
|
||||
settingTitle={t('chapter.title_other')}
|
||||
dialogTitle={t('chapter.title_other')}
|
||||
settingTitle={t`Chapter`}
|
||||
dialogTitle={t`Chapter`}
|
||||
settingValue={`${trackRecord.lastChapterRead}/${trackRecord.totalChapters}`}
|
||||
value={trackRecord.lastChapterRead}
|
||||
minValue={0}
|
||||
@@ -342,7 +331,7 @@ export const TrackerActiveCard = ({
|
||||
/>
|
||||
<Divider orientation="vertical" flexItem />
|
||||
<SelectSetting<string>
|
||||
settingName={t('tracking.track_record.label.score')}
|
||||
settingName={t`Score`}
|
||||
value={currentScore}
|
||||
values={selectSettingValues}
|
||||
handleChange={(score) => updateTrackerBind({ scoreString: score })}
|
||||
@@ -351,7 +340,7 @@ export const TrackerActiveCard = ({
|
||||
<Divider />
|
||||
<TrackerActiveCardInfoRow>
|
||||
<DateSetting
|
||||
settingName={t('tracking.track_record.label.start_date')}
|
||||
settingName={t`Start date`}
|
||||
value={Trackers.getDateString(trackRecord.startDate)}
|
||||
remove
|
||||
handleChange={(startDate) =>
|
||||
@@ -360,7 +349,7 @@ export const TrackerActiveCard = ({
|
||||
/>
|
||||
<Divider orientation="vertical" flexItem />
|
||||
<DateSetting
|
||||
settingName={t('tracking.track_record.label.finish_date')}
|
||||
settingName={t`Finish date`}
|
||||
value={Trackers.getDateString(trackRecord.finishDate)}
|
||||
remove
|
||||
handleChange={(finishDate) =>
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import Card from '@mui/material/Card';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
import Button from '@mui/material/Button';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Box from '@mui/material/Box';
|
||||
import CardActionArea from '@mui/material/CardActionArea';
|
||||
import CardMedia from '@mui/material/CardMedia';
|
||||
@@ -19,6 +18,7 @@ import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { useLayoutEffect, useRef, useState } from 'react';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
||||
import { SpinnerImage } from '@/base/components/SpinnerImage.tsx';
|
||||
import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx';
|
||||
@@ -52,7 +52,7 @@ const TrackerMangaCardTitle = ({ title, selected }: { title: string; selected: b
|
||||
|
||||
const SUMMARY_COLLAPSED_SIZE = 50;
|
||||
const TrackerMangaCardSummary = ({ summary }: { summary: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
const summaryRef = useRef<HTMLParagraphElement>(null);
|
||||
|
||||
@@ -85,7 +85,7 @@ const TrackerMangaCardSummary = ({ summary }: { summary: string }) => {
|
||||
setIsSummaryExpanded(!isSummaryExpanded);
|
||||
}}
|
||||
>
|
||||
{t(isSummaryExpanded ? 'global.button.show_less' : 'global.button.show_more')}
|
||||
{isSummaryExpanded ? t`Show less` : t`Show more`}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
@@ -115,7 +115,7 @@ export const TrackerMangaCard = ({
|
||||
selected: boolean;
|
||||
onSelect: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
const isMobileWidth = MediaQuery.useIsMobileWidth();
|
||||
|
||||
return (
|
||||
@@ -175,25 +175,19 @@ export const TrackerMangaCard = ({
|
||||
</TrackerMangaCardLink>
|
||||
{manga.publishingType && (
|
||||
<Metadata
|
||||
title={t('global.label.type')}
|
||||
title={t`Type`}
|
||||
value={t(PUBLISHING_TYPE_TO_TRANSLATION[Trackers.getPublishingType(manga)])}
|
||||
/>
|
||||
)}
|
||||
{manga.startDate && (
|
||||
<Metadata title={t('global.label.started')} value={manga.startDate} />
|
||||
)}
|
||||
{manga.startDate && <Metadata title={t`Started`} value={manga.startDate} />}
|
||||
{manga.publishingStatus && (
|
||||
<Metadata
|
||||
title={t('manga.label.status')}
|
||||
title={t`Status`}
|
||||
value={t(PUBLISHING_STATUS_TO_TRANSLATION[Trackers.getPublishingStatus(manga)])}
|
||||
/>
|
||||
)}
|
||||
{manga.score > 0 && (
|
||||
<Metadata title={t('tracking.track_record.label.score')} value={manga.score} />
|
||||
)}
|
||||
{manga.totalChapters > 0 && (
|
||||
<Metadata title={t('chapter.title_other')} value={manga.totalChapters} />
|
||||
)}
|
||||
{manga.score > 0 && <Metadata title={t`Score`} value={manga.score} />}
|
||||
{manga.totalChapters > 0 && <Metadata title={t`Chapter`} value={manga.totalChapters} />}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<TrackerMangaCardSummary summary={manga.summary} />
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
import Card from '@mui/material/Card';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
import Button from '@mui/material/Button';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { CARD_STYLING } from '@/features/tracker/Tracker.constants.ts';
|
||||
|
||||
import { TTrackerBase } from '@/features/tracker/Tracker.types.ts';
|
||||
|
||||
import { AvatarSpinner } from '@/base/components/AvatarSpinner.tsx';
|
||||
|
||||
export const TrackerUntrackedCard = ({
|
||||
@@ -24,7 +24,7 @@ export const TrackerUntrackedCard = ({
|
||||
tracker: Pick<TTrackerBase, 'name' | 'icon'>;
|
||||
onClick: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useLingui();
|
||||
|
||||
return (
|
||||
<Card sx={CARD_STYLING}>
|
||||
@@ -49,7 +49,7 @@ export const TrackerUntrackedCard = ({
|
||||
}}
|
||||
/>
|
||||
<Button sx={{ flexGrow: '1' }} onClick={onClick}>
|
||||
{t('tracking.action.button.add_tracking')}
|
||||
{t`Add tracking`}
|
||||
</Button>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
|
||||
Reference in New Issue
Block a user