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,6 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { MessageDescriptor } from '@lingui/core';
import ArrowCircleLeftIcon from '@mui/icons-material/ArrowCircleLeft';
import ArrowCircleRightIcon from '@mui/icons-material/ArrowCircleRight';
import ZoomOutMapIcon from '@mui/icons-material/ZoomOutMap';
@@ -13,7 +14,8 @@ import ExpandIcon from '@mui/icons-material/Expand';
import CropOriginalIcon from '@mui/icons-material/CropOriginal';
import { TooltipProps } from '@mui/material/Tooltip';
import { Direction } from '@mui/material/styles';
import { ScrollDirection, TranslationKey, ValueToDisplayData } from '@/base/Base.types.ts';
import { msg } from '@lingui/core/macro';
import { ScrollDirection, ValueToDisplayData } from '@/base/Base.types';
import {
IReaderSettings,
IReaderSettingsGlobal,
@@ -252,11 +254,11 @@ export const READER_PROGRESS_BAR_POSITION_TO_PLACEMENT: Record<ProgressBarPositi
export const READING_DIRECTION_VALUE_TO_DISPLAY_DATA: ValueToDisplayData<ReadingDirection> = {
[ReadingDirection.LTR]: {
title: 'reader.settings.reading_direction.ltr',
title: msg`Left to right`,
icon: <ArrowCircleRightIcon />,
},
[ReadingDirection.RTL]: {
title: 'reader.settings.reading_direction.rtl',
title: msg`Right to left`,
icon: <ArrowCircleLeftIcon />,
},
};
@@ -265,19 +267,19 @@ export const READING_DIRECTION_VALUES = Object.values(ReadingDirection).filter((
export const PAGE_SCALE_VALUE_TO_DISPLAY_DATA: ValueToDisplayData<ReaderPageScaleMode> = {
[ReaderPageScaleMode.WIDTH]: {
title: 'reader.settings.page_scale.width',
title: msg`Fit width`,
icon: <ExpandIcon sx={{ transform: 'rotate(90deg)' }} />,
},
[ReaderPageScaleMode.HEIGHT]: {
title: 'reader.settings.page_scale.height',
title: msg`Fit height`,
icon: <ExpandIcon />,
},
[ReaderPageScaleMode.SCREEN]: {
title: 'reader.settings.page_scale.screen',
title: msg`Fit screen`,
icon: <ZoomOutMapIcon />,
},
[ReaderPageScaleMode.ORIGINAL]: {
title: 'reader.settings.page_scale.original',
title: msg`Original size`,
icon: <CropOriginalIcon />,
},
};
@@ -295,23 +297,23 @@ export const READER_PAGE_SCALE_MODE_TO_SCALING_ALLOWED: Record<ReaderPageScaleMo
export const READING_MODE_VALUE_TO_DISPLAY_DATA = {
[ReadingMode.SINGLE_PAGE]: {
title: 'reader.settings.reader_type.label.single_page',
title: msg`Single page`,
icon: <SinglePageIcon />,
},
[ReadingMode.DOUBLE_PAGE]: {
title: 'reader.settings.reader_type.label.double_page',
title: msg`Double page`,
icon: <DoublePageIcon />,
},
[ReadingMode.CONTINUOUS_VERTICAL]: {
title: 'reader.settings.reader_type.label.continuous_vertical',
title: msg`Continuous vertical`,
icon: <ContinuousVerticalPageIcon />,
},
[ReadingMode.CONTINUOUS_HORIZONTAL]: {
title: 'reader.settings.reader_type.label.continuous_horizontal',
title: msg`Continuous horizontal`,
icon: <ContinuousHorizontalPageIcon />,
},
[ReadingMode.WEBTOON]: {
title: 'reader.settings.reader_type.label.webtoon',
title: msg`Webtoon`,
icon: <WebtoonPageIcon />,
},
} satisfies ValueToDisplayData<ReadingMode>;
@@ -330,33 +332,33 @@ export const READER_SETTING_TABS: Record<
ReaderSettingTab,
{
id: ReaderSettingTab;
label: TranslationKey;
label: MessageDescriptor;
supportsTouchDevices: boolean;
}
> = {
[ReaderSettingTab.LAYOUT]: {
id: ReaderSettingTab.LAYOUT,
label: 'reader.settings.label.layout',
label: msg`Layout`,
supportsTouchDevices: true,
},
[ReaderSettingTab.GENERAL]: {
id: ReaderSettingTab.GENERAL,
label: 'global.label.general',
label: msg`General`,
supportsTouchDevices: true,
},
[ReaderSettingTab.FILTER]: {
id: ReaderSettingTab.FILTER,
label: 'reader.settings.custom_filter.title',
label: msg`Custom filter`,
supportsTouchDevices: true,
},
[ReaderSettingTab.BEHAVIOUR]: {
id: ReaderSettingTab.BEHAVIOUR,
label: 'reader.settings.label.behaviour',
label: msg`Behaviour`,
supportsTouchDevices: true,
},
[ReaderSettingTab.HOTKEYS]: {
id: ReaderSettingTab.HOTKEYS,
label: 'hotkeys.title_other',
label: msg`Keybinds`,
supportsTouchDevices: false,
},
};
@@ -385,27 +387,27 @@ export const CONTINUOUS_READING_MODE_TO_SCROLL_DIRECTION: Record<
export const READER_BLEND_MODE_VALUE_TO_DISPLAY_DATA = {
[ReaderBlendMode.DEFAULT]: {
title: 'reader.settings.custom_filter.rgba.blend_mode.default',
title: msg`Default`,
icon: null,
},
[ReaderBlendMode.MULTIPLY]: {
title: 'reader.settings.custom_filter.rgba.blend_mode.multiply',
title: msg`Multiply`,
icon: null,
},
[ReaderBlendMode.SCREEN]: {
title: 'reader.settings.custom_filter.rgba.blend_mode.screen',
title: msg`Screen`,
icon: null,
},
[ReaderBlendMode.OVERLAY]: {
title: 'reader.settings.custom_filter.rgba.blend_mode.overlay',
title: msg`Overlay`,
icon: null,
},
[ReaderBlendMode.DARKEN]: {
title: 'reader.settings.custom_filter.rgba.blend_mode.darken',
title: msg`Darken`,
icon: null,
},
[ReaderBlendMode.LIGHTEN]: {
title: 'reader.settings.custom_filter.rgba.blend_mode.lighten',
title: msg`Lighten`,
icon: null,
},
} satisfies ValueToDisplayData<ReaderBlendMode>;

View File

@@ -7,9 +7,9 @@
*/
import Stack from '@mui/material/Stack';
import { useTranslation } from 'react-i18next';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import { useLingui } from '@lingui/react/macro';
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { IReaderSettingsWithDefaultFlag, ReaderSettingsTypeProps } from '@/features/reader/Reader.types.ts';
import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx';
@@ -34,7 +34,7 @@ export const ReaderBehaviourSettings = ({
...args: Parameters<typeof ReaderService.updateSetting>
) => ReturnType<typeof ReaderService.updateSetting>;
} & ReaderSettingsTypeProps) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<Stack sx={{ gap: 2 }}>
@@ -47,17 +47,17 @@ export const ReaderBehaviourSettings = ({
setScrollAmount={(value, commit) => updateSetting('scrollAmount', value, commit)}
/>
<CheckboxInput
label={t('reader.settings.label.skip_dup_chapters')}
label={t`Skip duplicate chapters`}
checked={settings.shouldSkipDupChapters}
onChange={(_, checked) => updateSetting('shouldSkipDupChapters', checked)}
/>
<CheckboxInput
label={
<Box>
<Typography>{t('reader.settings.label.skip_filtered_chapters')}</Typography>
<Typography>{t`Skip filtered chapters`}</Typography>
{isDefaultable && (
<Typography variant="body2" color="textDisabled">
{t('reader.settings.label.unchangeable_in_reader')}
{t`Setting can not be changed while the reader is opened`}
</Typography>
)}
</Box>
@@ -68,7 +68,7 @@ export const ReaderBehaviourSettings = ({
/>
{isOffsetDoubleSpreadPagesEditable(settings.readingMode.value) && (
<CheckboxInput
label={t('reader.settings.label.offset_double_spread')}
label={t`Offset double spreads`}
checked={settings.shouldOffsetDoubleSpreads.value}
onChange={(_, checked) => updateSetting('shouldOffsetDoubleSpreads', checked)}
/>
@@ -76,9 +76,9 @@ export const ReaderBehaviourSettings = ({
<CheckboxInput
label={
<Box>
<Typography>{t('reader.settings.infinite_scroll.title')}</Typography>
<Typography>{t`Continuous chapter display`}</Typography>
<Typography variant="body2" color="textDisabled">
{t('reader.settings.infinite_scroll.description')}
{t`Keep previous and upcoming chapters visible while reading in continuous reading modes, allowing seamless scrolling between chapters.`}
</Typography>
</Box>
}
@@ -88,9 +88,9 @@ export const ReaderBehaviourSettings = ({
<CheckboxInput
label={
<Box>
<Typography>{t('reader.settings.preview.reading_mode.title')}</Typography>
<Typography>{t`Show reading mode`}</Typography>
<Typography variant="body2" color="textDisabled">
{t('reader.settings.preview.reading_mode.description')}
{t`Briefly show current mode when reader is opened or mode got changed`}
</Typography>
</Box>
}
@@ -100,9 +100,9 @@ export const ReaderBehaviourSettings = ({
<CheckboxInput
label={
<Box>
<Typography>{t('reader.settings.preview.tap_zones.title')}</Typography>
<Typography>{t`Show tap zones overlay`}</Typography>
<Typography variant="body2" color="textDisabled">
{t('reader.settings.preview.tap_zones.description')}
{t`Briefly show tap zone layout preview when reader is opened or layout got changed`}
</Typography>
</Box>
}
@@ -112,9 +112,9 @@ export const ReaderBehaviourSettings = ({
<CheckboxInput
label={
<Box>
<Typography>{t('reader.settings.auto_webtoon_mode.title')}</Typography>
<Typography>{t`Auto webtoon mode`}</Typography>
<Typography variant="body2" color="textDisabled">
{t('reader.settings.auto_webtoon_mode.description')}
{t`Automatically use webtoon mode for entries that are detected to likely use the long strip format`}
</Typography>
</Box>
}
@@ -122,17 +122,17 @@ export const ReaderBehaviourSettings = ({
onChange={(_, checked) => updateSetting('shouldUseAutoWebtoonMode', checked)}
/>
<CheckboxInput
label={t('reader.settings.show_transition_page')}
label={t`Show transition page`}
checked={settings.shouldShowTransitionPage}
onChange={(_, checked) => updateSetting('shouldShowTransitionPage', checked)}
/>
<CheckboxInput
label={t('reader.settings.chapter_transition.warning.missing_chapter')}
label={t`Inform about missing chapters on chapter transition`}
checked={settings.shouldInformAboutMissingChapter}
onChange={(_, checked) => updateSetting('shouldInformAboutMissingChapter', checked)}
/>
<CheckboxInput
label={t('reader.settings.chapter_transition.warning.scanlator_change')}
label={t`Inform about changing scanlator on chapter transition`}
checked={settings.shouldInformAboutScanlatorChange}
onChange={(_, checked) => updateSetting('shouldInformAboutScanlatorChange', checked)}
/>
@@ -141,7 +141,7 @@ export const ReaderBehaviourSettings = ({
setAutoScroll={(...args) => updateSetting('autoScroll', ...args)}
/>
<SliderInput
label={t('reader.settings.image_preload_amount')}
label={t`Preload images`}
value={settings.imagePreLoadAmount}
onDefault={() => onDefault?.('imagePreLoadAmount')}
slotProps={{

View File

@@ -6,18 +6,19 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { msg } from '@lingui/core/macro';
import { IReaderSettings, ReaderExitMode } from '@/features/reader/Reader.types.ts';
import { ValueToDisplayData } from '@/base/Base.types.ts';
import { ButtonSelectInput } from '@/base/components/inputs/ButtonSelectInput.tsx';
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<ReaderExitMode> = {
[ReaderExitMode.PREVIOUS]: {
title: 'global.label.previous',
title: msg`Previous`,
icon: null,
},
[ReaderExitMode.MANGA]: {
title: 'manga.title_one',
title: msg`Manga`,
icon: null,
},
};
@@ -30,11 +31,11 @@ export const ReaderSettingExitMode = ({
}: Pick<IReaderSettings, 'exitMode'> & {
setExitMode: (mode: ReaderExitMode) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<ButtonSelectInput
label={t('reader.settings.exit_mode')}
label={t`Open page on exit`}
value={exitMode}
values={READER_EXIT_MODE_VALUES}
setValue={setExitMode}

View File

@@ -6,7 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { msg } from '@lingui/core/macro';
import { IReaderSettings, ReaderScrollAmount } from '@/features/reader/Reader.types.ts';
import { ValueToDisplayData } from '@/base/Base.types.ts';
import { ButtonSelectInput } from '@/base/components/inputs/ButtonSelectInput.tsx';
@@ -15,19 +16,19 @@ import { DEFAULT_READER_SETTINGS, SCROLL_AMOUNT } from '@/features/reader/settin
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<ReaderScrollAmount> = {
[ReaderScrollAmount.TINY]: {
title: 'global.label.tiny',
title: msg`Tiny`,
icon: null,
},
[ReaderScrollAmount.SMALL]: {
title: 'global.label.small',
title: msg`Small`,
icon: null,
},
[ReaderScrollAmount.MEDIUM]: {
title: 'global.label.medium',
title: msg`Medium`,
icon: null,
},
[ReaderScrollAmount.LARGE]: {
title: 'global.label.large',
title: msg`Large`,
icon: null,
},
};
@@ -40,20 +41,20 @@ export const ReaderSettingScrollAmount = ({
}: Pick<IReaderSettings, 'scrollAmount'> & {
setScrollAmount: (amount: ReaderScrollAmount, commit: boolean) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<>
<ButtonSelectInput
label={t('reader.settings.scroll_amount')}
label={t`Scroll amount`}
value={scrollAmount}
values={READER_SCROLL_AMOUNT_VALUES}
setValue={(value) => setScrollAmount(value as number, true)}
valueToDisplayData={VALUE_TO_DISPLAY_DATA}
/>
<SliderInput
label={t('reader.settings.label.custom_scroll_amount')}
value={t('global.value', { value: scrollAmount, unit: '%' })}
label={t`Custom scroll amount`}
value={`${scrollAmount}%`}
onDefault={() => setScrollAmount(DEFAULT_READER_SETTINGS.scrollAmount, true)}
slotProps={{
slider: {

View File

@@ -8,11 +8,11 @@
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { MediaQuery } from '@/base/utils/MediaQuery.tsx';
export const DefaultSettingFootnote = ({ areDefaultSettings }: { areDefaultSettings?: boolean }) => {
const { t } = useTranslation();
const { t } = useLingui();
const isTouchDevice = MediaQuery.useIsTouchDevice();
if (!isTouchDevice || areDefaultSettings) {
@@ -21,7 +21,7 @@ export const DefaultSettingFootnote = ({ areDefaultSettings }: { areDefaultSetti
return (
<Stack sx={{ alignItems: 'end' }}>
<Typography variant="caption">{t('reader.settings.default_setting_footnote')}</Typography>
<Typography variant="caption">{t`*: Active setting`}</Typography>
</Stack>
);
};

View File

@@ -8,7 +8,7 @@
import Box from '@mui/material/Box';
import Tab from '@mui/material/Tab';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { TabsMenu } from '@/base/components/tabs/TabsMenu.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
import { MediaQuery } from '@/base/utils/MediaQuery.tsx';
@@ -43,7 +43,7 @@ const BaseReaderSettingsTabs = ({
deleteSetting: (setting: keyof IReaderSettings) => void;
setTransparent?: (transparent: boolean) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
const isTouchDevice = MediaQuery.useIsTouchDevice();
const setShowPreview = useReaderTapZoneStore((state) => state.tapZone.setShowPreview);

View File

@@ -7,7 +7,7 @@
*/
import Stack from '@mui/material/Stack';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { ReaderSettingProgressBarType } from '@/features/reader/overlay/progress-bar/settings/components/ReaderSettingProgressBarType.tsx';
import { ReaderSettingProgressBarSize } from '@/features/reader/overlay/progress-bar/settings/components/ReaderSettingProgressBarSize.tsx';
import { ReaderSettingProgressBarPosition } from '@/features/reader/overlay/progress-bar/settings/components/ReaderSettingProgressBarPosition.tsx';
@@ -27,7 +27,7 @@ export const ReaderGeneralSettings = ({
updateSetting,
onDefault,
}: Pick<IReaderSettings, 'overlayMode'> & ReaderSettingsTypeProps) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<Stack sx={{ gap: 2 }}>
@@ -58,7 +58,7 @@ export const ReaderGeneralSettings = ({
/>
{(settings.progressBarType === ProgressBarType.HIDDEN || overlayMode === ReaderOverlayMode.MOBILE) && (
<CheckboxInput
label={t('reader.settings.label.show_page_number')}
label={t`Show page number`}
checked={settings.shouldShowPageNumber}
onChange={(_, checked) => updateSetting('shouldShowPageNumber', checked)}
/>

View File

@@ -6,26 +6,27 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { msg } from '@lingui/core/macro';
import { ValueToDisplayData } from '@/base/Base.types.ts';
import { ButtonSelectInput } from '@/base/components/inputs/ButtonSelectInput.tsx';
import { IReaderSettingsWithDefaultFlag, ReaderBackgroundColor } from '@/features/reader/Reader.types.ts';
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<ReaderBackgroundColor> = {
[ReaderBackgroundColor.THEME]: {
title: 'settings.appearance.theme.title',
title: msg`Theme`,
icon: null,
},
[ReaderBackgroundColor.BLACK]: {
title: 'global.colors.black',
title: msg`Black`,
icon: null,
},
[ReaderBackgroundColor.GRAY]: {
title: 'global.colors.gray',
title: msg`Gray`,
icon: null,
},
[ReaderBackgroundColor.WHITE]: {
title: 'global.colors.white',
title: msg`White`,
icon: null,
},
};
@@ -40,11 +41,11 @@ export const ReaderSettingBackgroundColor = ({
}: Pick<IReaderSettingsWithDefaultFlag, 'backgroundColor'> & {
updateSetting: (color: ReaderBackgroundColor) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<ButtonSelectInput
label={t('reader.settings.background_color')}
label={t`Background color`}
value={backgroundColor}
values={READER_BACKGROUND_COLOR_VALUES}
setValue={updateSetting}

View File

@@ -8,7 +8,7 @@
import Stack from '@mui/material/Stack';
import { ComponentProps } from 'react';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { ReaderLayoutSettings } from '@/features/reader/settings/layout/ReaderLayoutSettings.tsx';
import { ReaderSettingProfileSettings } from '@/features/reader/settings/layout/components/ReaderSettingProfileSettings.tsx';
import {
@@ -28,7 +28,7 @@ export const ReaderDefaultLayoutSettings = ({
}) => {
const { updateSetting, isSeriesMode } = props;
const { t } = useTranslation();
const { t } = useLingui();
return (
<Stack sx={{ gap: 2, pb: Number(!isSeriesMode) * 2 }}>

View File

@@ -9,7 +9,7 @@
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import Divider from '@mui/material/Divider';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { ReaderSettingReadingMode } from '@/features/reader/settings/layout/components/ReaderSettingReadingMode.tsx';
import { ReaderSettingReadingDirection } from '@/features/reader/settings/layout/components/ReaderSettingReadingDirection.tsx';
import { ReaderSettingTapZoneLayout } from '@/features/reader/settings/layout/components/ReaderSettingTapZoneLayout.tsx';
@@ -35,14 +35,14 @@ export const ReaderLayoutSettings = ({
setShowPreview: TReaderTapZoneContext['setShowPreview'];
isSeriesMode?: boolean;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<Stack sx={{ gap: 2 }}>
<DefaultSettingFootnote areDefaultSettings={!isDefaultable} />
{isSeriesMode && (
<>
<Typography>{t('reader.settings.source_series')}</Typography>
<Typography>{t`Series settings`}</Typography>
<ReaderSettingReadingMode
readingMode={settings.readingMode}
setReadingMode={(value) => updateSetting('readingMode', value)}

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { IReaderSettings, IReaderSettingsWithDefaultFlag, ReadingMode } from '@/features/reader/Reader.types.ts';
import { SliderInput } from '@/base/components/inputs/SliderInput.tsx';
import { DEFAULT_READER_SETTINGS, PAGE_GAP } from '@/features/reader/settings/ReaderSettings.constants.tsx';
@@ -23,7 +23,7 @@ export const ReaderSettingPageGap = ({
Pick<MultiValueButtonDefaultableProps<IReaderSettings['pageGap']>, 'isDefaultable' | 'onDefault'> & {
updateSetting: (gap: number, commit: boolean) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
const isChangeable = readingMode.value !== ReadingMode.WEBTOON && isContinuousReadingMode(readingMode.value);
if (!isChangeable) {
@@ -32,8 +32,8 @@ export const ReaderSettingPageGap = ({
return (
<SliderInput
label={t('reader.settings.label.page_gap')}
value={t('global.value', { value: pageGap.value, unit: t('global.unit.px') })}
label={t`Page gap`}
value={`${pageGap.value}${t`px`}`}
onDefault={isDefaultable ? onDefault : undefined}
slotProps={{
slider: {

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { IReaderSettings, IReaderSettingsWithDefaultFlag, ReadingDirection } from '@/features/reader/Reader.types.ts';
import {
PAGE_SCALE_VALUE_TO_DISPLAY_DATA,
@@ -23,12 +23,12 @@ export const ReaderSettingPageScaleMode = ({
Pick<MultiValueButtonDefaultableProps<ReadingDirection>, 'isDefaultable' | 'onDefault'> & {
setPageScaleMode: (mode: IReaderSettings['pageScaleMode']) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<ButtonSelectInput
{...buttonSelectInputProps}
label={t('reader.settings.page_scale.title')}
label={t`Scale type`}
value={pageScaleMode.isDefault ? undefined : pageScaleMode.value}
defaultValue={pageScaleMode.isDefault ? pageScaleMode.value : undefined}
values={READER_PAGE_SCALE_MODE_VALUES}

View File

@@ -8,18 +8,19 @@
import ArrowCircleLeftIcon from '@mui/icons-material/ArrowCircleLeft';
import ArrowCircleRightIcon from '@mui/icons-material/ArrowCircleRight';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { msg } from '@lingui/core/macro';
import { IReaderSettingsWithDefaultFlag, ReadingDirection } from '@/features/reader/Reader.types.ts';
import { MultiValueButtonDefaultableProps, ValueToDisplayData } from '@/base/Base.types.ts';
import { ButtonSelectInput } from '@/base/components/inputs/ButtonSelectInput.tsx';
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<ReadingDirection> = {
[ReadingDirection.LTR]: {
title: 'reader.settings.reading_direction.ltr',
title: msg`Left to right`,
icon: <ArrowCircleRightIcon />,
},
[ReadingDirection.RTL]: {
title: 'reader.settings.reading_direction.rtl',
title: msg`Right to left`,
icon: <ArrowCircleLeftIcon />,
},
};
@@ -34,12 +35,12 @@ export const ReaderSettingReadingDirection = ({
Pick<MultiValueButtonDefaultableProps<ReadingDirection>, 'isDefaultable' | 'onDefault'> & {
setReadingDirection: (readingDirection: ReadingDirection) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<ButtonSelectInput
{...buttonSelectInputProps}
label={t('reader.settings.label.reading_direction')}
label={t`Reading direction`}
value={readingDirection.isDefault ? undefined : readingDirection.value}
defaultValue={readingDirection.isDefault ? readingDirection.value : undefined}
values={READING_DIRECTION_VALUES}

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { IReaderSettingsWithDefaultFlag, ReadingMode } from '@/features/reader/Reader.types.ts';
import {
READING_MODE_VALUE_TO_DISPLAY_DATA,
@@ -23,12 +23,12 @@ export const ReaderSettingReadingMode = ({
Pick<MultiValueButtonDefaultableProps<ReadingMode>, 'isDefaultable' | 'onDefault'> & {
setReadingMode: (mode: ReadingMode) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<ButtonSelectInput
{...buttonSelectInputProps}
label={t('reader.settings.label.reading_mode')}
label={t`Reading mode`}
value={readingMode.isDefault ? undefined : readingMode.value}
defaultValue={readingMode.isDefault ? readingMode.value : undefined}
values={READING_MODE_VALUES}

View File

@@ -6,9 +6,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import Button from '@mui/material/Button';
import Box from '@mui/material/Box';
import { useLingui } from '@lingui/react/macro';
import { IReaderSettings } from '@/features/reader/Reader.types.ts';
import { READER_PAGE_SCALE_MODE_TO_SCALING_ALLOWED } from '@/features/reader/settings/ReaderSettings.constants.tsx';
@@ -19,7 +19,7 @@ export const ReaderSettingStretchPage = ({
}: Pick<IReaderSettings, 'pageScaleMode' | 'shouldStretchPage'> & {
setShouldStretchPage: (mode: IReaderSettings['shouldStretchPage']) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
if (!READER_PAGE_SCALE_MODE_TO_SCALING_ALLOWED[pageScaleMode]) {
return null;
@@ -31,7 +31,7 @@ export const ReaderSettingStretchPage = ({
onClick={() => setShouldStretchPage(!shouldStretchPage)}
variant={shouldStretchPage ? 'contained' : 'outlined'}
>
{t('reader.settings.page_scale.stretch')}
{t`Stretch small pages`}
</Button>
</Box>
);

View File

@@ -6,7 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { msg } from '@lingui/core/macro';
import { MultiValueButtonDefaultableProps, ValueToDisplayData } from '@/base/Base.types.ts';
import { IReaderSettings, IReaderSettingsWithDefaultFlag, ReadingDirection } from '@/features/reader/Reader.types.ts';
import { TapZoneInvertMode } from '@/features/reader/tap-zones/TapZoneLayout.types.ts';
@@ -21,19 +22,19 @@ enum TapZonesInvertOption {
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<TapZonesInvertOption> = {
[TapZonesInvertOption.NONE]: {
title: 'global.label.none',
title: msg`None`,
icon: null,
},
[TapZonesInvertOption.HORIZONTAL]: {
title: 'global.label.horizontal',
title: msg`Horizontal`,
icon: null,
},
[TapZonesInvertOption.VERTICAL]: {
title: 'global.label.vertical',
title: msg`Vertical`,
icon: null,
},
[TapZonesInvertOption.BOTH]: {
title: 'global.label.both',
title: msg`Both`,
icon: null,
},
};
@@ -83,14 +84,14 @@ export const ReaderSettingTapZoneInvertMode = ({
Pick<MultiValueButtonDefaultableProps<ReadingDirection>, 'isDefaultable' | 'onDefault'> & {
setTapZoneInvertMode: (invert: IReaderSettings['tapZoneInvertMode']) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
const tapZonesInvertOption = convertTapZoneInvertModeToOption(tapZoneInvertMode.value);
return (
<ButtonSelectInput
{...buttonSelectInputProps}
label={t('reader.settings.tap_zones.invert')}
label={t`Invert tap zones`}
value={tapZoneInvertMode.isDefault ? undefined : tapZonesInvertOption}
defaultValue={tapZoneInvertMode.isDefault ? tapZonesInvertOption : undefined}
values={TAP_ZONES_INVERT_OPTION_VALUES}

View File

@@ -6,7 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { msg } from '@lingui/core/macro';
import { TapZoneLayouts } from '@/features/reader/tap-zones/TapZoneLayout.types.ts';
import { MultiValueButtonDefaultableProps, ValueToDisplayData } from '@/base/Base.types.ts';
import { IReaderSettingsWithDefaultFlag, ReadingDirection } from '@/features/reader/Reader.types.ts';
@@ -14,23 +15,23 @@ import { ButtonSelectInput } from '@/base/components/inputs/ButtonSelectInput.ts
const VALUE_TO_DISPLAY_DATA: ValueToDisplayData<TapZoneLayouts> = {
[TapZoneLayouts.EDGE]: {
title: 'reader.settings.tap_zones.edge',
title: msg`Edge`,
icon: null,
},
[TapZoneLayouts.KINDLE]: {
title: 'reader.settings.tap_zones.kindle',
title: msg`Kindle`,
icon: null,
},
[TapZoneLayouts.L_SHAPE]: {
title: 'reader.settings.tap_zones.l_shape',
title: msg`L-Shape`,
icon: null,
},
[TapZoneLayouts.RIGHT_LEFT]: {
title: 'reader.settings.tap_zones.right_left',
title: msg`Right and left`,
icon: null,
},
[TapZoneLayouts.DISABLED]: {
title: 'global.label.disabled',
title: msg`Disabled`,
icon: null,
},
};
@@ -45,12 +46,12 @@ export const ReaderSettingTapZoneLayout = ({
Pick<MultiValueButtonDefaultableProps<ReadingDirection>, 'isDefaultable' | 'onDefault'> & {
setTapZoneLayout: (layout: TapZoneLayouts) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
return (
<ButtonSelectInput
{...buttonSelectInputProps}
label={t('reader.settings.tap_zones.title')}
label={t`Tap zones`}
value={tapZoneLayout.isDefault ? undefined : tapZoneLayout.value}
defaultValue={tapZoneLayout.isDefault ? tapZoneLayout.value : undefined}
values={READER_TAP_ZONE_LAYOUT_VALUES}

View File

@@ -7,7 +7,7 @@
*/
import Stack from '@mui/material/Stack';
import { useTranslation } from 'react-i18next';
import { useLingui } from '@lingui/react/macro';
import { IReaderSettings } from '@/features/reader/Reader.types.ts';
import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx';
import { ReaderService } from '@/features/reader/services/ReaderService.ts';
@@ -29,7 +29,7 @@ export const ReaderSettingWidth = ({
updateSetting: (...args: Parameters<typeof ReaderService.updateSetting>) => void;
setTransparent?: (transparent: boolean) => void;
}) => {
const { t } = useTranslation();
const { t } = useLingui();
if (!isReaderWidthEditable(pageScaleMode)) {
return null;
@@ -39,7 +39,7 @@ export const ReaderSettingWidth = ({
<Stack>
<Stack sx={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<CheckboxInput
label={t('reader.settings.label.limit_reader_width')}
label={t`Limit reader width`}
checked={readerWidth.enabled}
onChange={(_, checked) => updateSetting('readerWidth', { ...readerWidth, enabled: checked }, true)}
/>
@@ -47,8 +47,8 @@ export const ReaderSettingWidth = ({
</Stack>
{readerWidth.enabled && (
<SliderInput
label={t('reader.settings.label.reader_width')}
value={t('global.value', { value: readerWidth.value, unit: '%' })}
label={t`Reader width`}
value={`${readerWidth.value}%`}
slotProps={{
slider: {
defaultValue: DEFAULT_READER_SETTINGS.readerWidth.value,

View File

@@ -6,8 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { useTranslation } from 'react-i18next';
import { useState } from 'react';
import { useLingui } from '@lingui/react/macro';
import { useDefaultReaderSettingsWithDefaultFlag } from '@/features/reader/settings/ReaderSettingsMetadata.ts';
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
import { EmptyViewAbsoluteCentered } from '@/base/components/feedback/EmptyViewAbsoluteCentered.tsx';
@@ -19,9 +19,9 @@ import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts';
export const GlobalReaderSettings = () => {
const { t } = useTranslation();
const { t } = useLingui();
useAppTitle(t('reader.settings.title.reader'));
useAppTitle(t`Reader`);
const [activeTab, setActiveTab] = useState(0);
@@ -46,7 +46,7 @@ export const GlobalReaderSettings = () => {
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('DefaultReaderSettings::refetch'))}
/>