mirror of
https://github.com/jeffvli/feishin.git
synced 2026-07-09 20:19:58 +02:00
Use proper casing for i18n locales (#1998)
This commit is contained in:
@@ -35,7 +35,7 @@ export const useMainPlayerListener = () => {
|
||||
toast.error({
|
||||
id: 'mpv-error',
|
||||
message,
|
||||
title: t('error.playbackError', { postProcess: 'sentenceCase' }) as string,
|
||||
title: t('error.playbackError') as string,
|
||||
});
|
||||
mediaPause();
|
||||
mpvPlayer!.pause();
|
||||
|
||||
@@ -470,7 +470,7 @@ export function WebPlayer() {
|
||||
const handleOnErrorPause = useCallback(() => {
|
||||
mediaPause();
|
||||
toast.error({
|
||||
message: t('error.playbackPausedDueToError', { postProcess: 'sentenceCase' }),
|
||||
message: t('error.playbackPausedDueToError'),
|
||||
});
|
||||
}, [mediaPause, t]);
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ const RadioStopButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
icon={<Icon fill="default" icon="mediaStop" size={buttonSize - 2} />}
|
||||
onClick={stop}
|
||||
tooltip={{
|
||||
label: t('player.stop', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.stop'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="tertiary"
|
||||
@@ -114,7 +114,7 @@ const StopButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
icon={<Icon fill="default" icon="mediaStop" size={buttonSize - 2} />}
|
||||
onClick={() => mediaStop()}
|
||||
tooltip={{
|
||||
label: t('player.stop', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.stop'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="tertiary"
|
||||
@@ -145,9 +145,8 @@ const ShuffleButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
shuffle === PlayerShuffle.NONE
|
||||
? t('player.shuffle', {
|
||||
context: 'off',
|
||||
postProcess: 'sentenceCase',
|
||||
})
|
||||
: t('player.shuffle', { postProcess: 'sentenceCase' }),
|
||||
: t('player.shuffle'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="tertiary"
|
||||
@@ -166,7 +165,7 @@ const PreviousButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
icon={<Icon fill="default" icon="mediaPrevious" size={buttonSize} />}
|
||||
onClick={mediaPrevious}
|
||||
tooltip={{
|
||||
label: t('player.previous', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.previous'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="secondary"
|
||||
@@ -187,7 +186,6 @@ const SkipBackwardButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
tooltip={{
|
||||
label: t('player.skip', {
|
||||
context: 'back',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
openDelay: 0,
|
||||
}}
|
||||
@@ -224,7 +222,6 @@ const SkipForwardButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
tooltip={{
|
||||
label: t('player.skip', {
|
||||
context: 'forward',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
openDelay: 0,
|
||||
}}
|
||||
@@ -244,7 +241,7 @@ const NextButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
icon={<Icon fill="default" icon="mediaNext" size={buttonSize} />}
|
||||
onClick={mediaNext}
|
||||
tooltip={{
|
||||
label: t('player.next', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.next'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="secondary"
|
||||
@@ -279,16 +276,13 @@ const RepeatButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
repeat === PlayerRepeat.NONE
|
||||
? t('player.repeat', {
|
||||
context: 'off',
|
||||
postProcess: 'sentenceCase',
|
||||
})
|
||||
: repeat === PlayerRepeat.ALL
|
||||
? t('player.repeat', {
|
||||
context: 'all',
|
||||
postProcess: 'sentenceCase',
|
||||
})
|
||||
: t('player.repeat', {
|
||||
context: 'one',
|
||||
postProcess: 'sentenceCase',
|
||||
})
|
||||
}`,
|
||||
openDelay: 0,
|
||||
@@ -308,7 +302,7 @@ const ShuffleAllButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
icon={<Icon fill="default" icon="mediaRandom" size={buttonSize} />}
|
||||
onClick={() => openShuffleAllModal()}
|
||||
tooltip={{
|
||||
label: t('form.shuffleAll.title', { postProcess: 'sentenceCase' }),
|
||||
label: t('form.shuffleAll.title'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="tertiary"
|
||||
|
||||
@@ -58,7 +58,7 @@ export const FullScreenPlayerQueue = () => {
|
||||
if (webAudio) {
|
||||
items.push({
|
||||
active: activeTab === 'visualizer',
|
||||
label: t('page.fullscreenPlayer.visualizer', { postProcess: 'titleCase' }),
|
||||
label: t('page.fullscreenPlayer.visualizer'),
|
||||
onClick: () => setStore({ activeTab: 'visualizer' }),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ const Controls = () => {
|
||||
icon="arrowDownS"
|
||||
iconProps={{ size: 'lg' }}
|
||||
onClick={handleToggleFullScreenPlayer}
|
||||
tooltip={{ label: t('common.minimize', { postProcess: 'titleCase' }) }}
|
||||
tooltip={{ label: t('common.minimize') }}
|
||||
variant="subtle"
|
||||
/>
|
||||
<Popover position="bottom-start">
|
||||
@@ -296,16 +296,14 @@ const Controls = () => {
|
||||
<ActionIcon
|
||||
icon="settings2"
|
||||
iconProps={{ size: 'lg' }}
|
||||
tooltip={{ label: t('common.configure', { postProcess: 'titleCase' }) }}
|
||||
tooltip={{ label: t('common.configure') }}
|
||||
variant="subtle"
|
||||
/>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.dynamicBackground', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.dynamicBackground')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -321,9 +319,7 @@ const Controls = () => {
|
||||
{dynamicBackground && (
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.dynamicIsImage', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.dynamicIsImage')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -340,9 +336,7 @@ const Controls = () => {
|
||||
{dynamicBackground && dynamicIsImage && (
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.dynamicImageBlur', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.dynamicImageBlur')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Slider
|
||||
@@ -359,11 +353,7 @@ const Controls = () => {
|
||||
)}
|
||||
{dynamicBackground && (
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.opacity', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Option.Label>
|
||||
<Option.Label>{t('page.fullscreenPlayer.config.opacity')}</Option.Label>
|
||||
<Option.Control>
|
||||
<Slider
|
||||
defaultValue={opacity}
|
||||
@@ -378,9 +368,7 @@ const Controls = () => {
|
||||
)}
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.useImageAspectRatio', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.useImageAspectRatio')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -396,9 +384,7 @@ const Controls = () => {
|
||||
<Divider my="sm" />
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.followCurrentLyric', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.followCurrentLyric')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -411,9 +397,7 @@ const Controls = () => {
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.showLyricProvider', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.showLyricProvider')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -426,9 +410,7 @@ const Controls = () => {
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.showLyricMatch', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.showLyricMatch')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -440,19 +422,13 @@ const Controls = () => {
|
||||
</Option.Control>
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.lyricSize', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Option.Label>
|
||||
<Option.Label>{t('page.fullscreenPlayer.config.lyricSize')}</Option.Label>
|
||||
<Option.Control>
|
||||
<Group w="100%" wrap="nowrap">
|
||||
<Slider
|
||||
defaultValue={lyricConfig.fontSize}
|
||||
label={(e) =>
|
||||
`${t('page.fullscreenPlayer.config.synchronized', {
|
||||
postProcess: 'titleCase',
|
||||
})}: ${e}px`
|
||||
`${t('page.fullscreenPlayer.config.synchronized')}: ${e}px`
|
||||
}
|
||||
max={72}
|
||||
min={8}
|
||||
@@ -462,9 +438,7 @@ const Controls = () => {
|
||||
<Slider
|
||||
defaultValue={lyricConfig.fontSize}
|
||||
label={(e) =>
|
||||
`${t('page.fullscreenPlayer.config.unsynchronized', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}: ${e}px`
|
||||
`${t('page.fullscreenPlayer.config.unsynchronized')}: ${e}px`
|
||||
}
|
||||
max={72}
|
||||
min={8}
|
||||
@@ -477,11 +451,7 @@ const Controls = () => {
|
||||
</Option.Control>
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.lyricGap', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Option.Label>
|
||||
<Option.Label>{t('page.fullscreenPlayer.config.lyricGap')}</Option.Label>
|
||||
<Option.Control>
|
||||
<Group w="100%" wrap="nowrap">
|
||||
<Slider
|
||||
@@ -507,29 +477,21 @@ const Controls = () => {
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.lyricAlignment', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.lyricAlignment')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<SegmentedControl
|
||||
data={[
|
||||
{
|
||||
label: t('common.left', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('common.left'),
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: t('common.center', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('common.center'),
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: t('common.right', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('common.right'),
|
||||
value: 'right',
|
||||
},
|
||||
]}
|
||||
@@ -539,11 +501,7 @@ const Controls = () => {
|
||||
</Option.Control>
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.lyricOffset', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Option.Label>
|
||||
<Option.Label>{t('page.fullscreenPlayer.config.lyricOffset')}</Option.Label>
|
||||
<Option.Control>
|
||||
<NumberInput
|
||||
defaultValue={lyricConfig.delayMs}
|
||||
|
||||
@@ -130,12 +130,7 @@ export const LeftControls = () => {
|
||||
role="button"
|
||||
transition={{ duration: 0.2, ease: 'easeIn' }}
|
||||
>
|
||||
<Tooltip
|
||||
label={t('player.toggleFullscreenPlayer', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
openDelay={0}
|
||||
>
|
||||
<Tooltip label={t('player.toggleFullscreenPlayer')} openDelay={0}>
|
||||
{isRadioMode && hasRadioStationImage ? (
|
||||
<ItemImage
|
||||
className={clsx(
|
||||
@@ -192,9 +187,7 @@ export const LeftControls = () => {
|
||||
top: 2,
|
||||
}}
|
||||
tooltip={{
|
||||
label: t('common.expand', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('common.expand'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -33,7 +33,7 @@ export const MobileFullscreenPlayerControls = memo(
|
||||
icon={<Icon fill="default" icon="mediaPrevious" size="xl" />}
|
||||
onClick={mediaPrevious}
|
||||
tooltip={{
|
||||
label: t('player.previous', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.previous'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="secondary"
|
||||
@@ -44,7 +44,6 @@ export const MobileFullscreenPlayerControls = memo(
|
||||
tooltip={{
|
||||
label: t('player.skip', {
|
||||
context: 'back',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
openDelay: 0,
|
||||
}}
|
||||
@@ -65,7 +64,6 @@ export const MobileFullscreenPlayerControls = memo(
|
||||
tooltip={{
|
||||
label: t('player.skip', {
|
||||
context: 'forward',
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
openDelay: 0,
|
||||
}}
|
||||
@@ -75,7 +73,7 @@ export const MobileFullscreenPlayerControls = memo(
|
||||
icon={<Icon fill="default" icon="mediaNext" size="xl" />}
|
||||
onClick={mediaNext}
|
||||
tooltip={{
|
||||
label: t('player.next', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.next'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="secondary"
|
||||
|
||||
@@ -84,7 +84,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
icon="arrowDownS"
|
||||
iconProps={{ size: 'lg' }}
|
||||
onClick={onClose}
|
||||
tooltip={{ label: t('common.minimize', { postProcess: 'titleCase' }) }}
|
||||
tooltip={{ label: t('common.minimize') }}
|
||||
variant={isPageHovered ? 'default' : 'subtle'}
|
||||
/>
|
||||
<Popover position="bottom-end">
|
||||
@@ -92,16 +92,14 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
<ActionIcon
|
||||
icon="settings2"
|
||||
iconProps={{ size: 'lg' }}
|
||||
tooltip={{ label: t('common.configure', { postProcess: 'titleCase' }) }}
|
||||
tooltip={{ label: t('common.configure') }}
|
||||
variant={isPageHovered ? 'default' : 'subtle'}
|
||||
/>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.dynamicBackground', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.dynamicBackground')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -117,9 +115,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
{dynamicBackground && (
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.dynamicIsImage', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.dynamicIsImage')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -136,9 +132,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
{dynamicBackground && dynamicIsImage && (
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.dynamicImageBlur', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.dynamicImageBlur')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Slider
|
||||
@@ -158,9 +152,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
{dynamicBackground && (
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.opacity', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.opacity')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Slider
|
||||
@@ -176,9 +168,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
)}
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.useImageAspectRatio', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.useImageAspectRatio')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -194,9 +184,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
<Divider my="sm" />
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.followCurrentLyric', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.followCurrentLyric')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -209,9 +197,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.showLyricProvider', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.showLyricProvider')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -227,9 +213,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.showLyricMatch', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.showLyricMatch')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Switch
|
||||
@@ -242,18 +226,14 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.lyricSize', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.lyricSize')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Group w="100%" wrap="nowrap">
|
||||
<Slider
|
||||
defaultValue={lyricConfig.fontSize}
|
||||
label={(e) =>
|
||||
`${t('page.fullscreenPlayer.config.synchronized', {
|
||||
postProcess: 'titleCase',
|
||||
})}: ${e}px`
|
||||
`${t('page.fullscreenPlayer.config.synchronized')}: ${e}px`
|
||||
}
|
||||
max={72}
|
||||
min={8}
|
||||
@@ -265,9 +245,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
<Slider
|
||||
defaultValue={lyricConfig.fontSizeUnsync}
|
||||
label={(e) =>
|
||||
`${t('page.fullscreenPlayer.config.unsynchronized', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}: ${e}px`
|
||||
`${t('page.fullscreenPlayer.config.unsynchronized')}: ${e}px`
|
||||
}
|
||||
max={72}
|
||||
min={8}
|
||||
@@ -281,9 +259,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.lyricGap', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.lyricGap')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<Group w="100%" wrap="nowrap">
|
||||
@@ -310,29 +286,21 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.lyricAlignment', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.lyricAlignment')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<SegmentedControl
|
||||
data={[
|
||||
{
|
||||
label: t('common.left', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('common.left'),
|
||||
value: 'left',
|
||||
},
|
||||
{
|
||||
label: t('common.center', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('common.center'),
|
||||
value: 'center',
|
||||
},
|
||||
{
|
||||
label: t('common.right', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('common.right'),
|
||||
value: 'right',
|
||||
},
|
||||
]}
|
||||
@@ -343,9 +311,7 @@ export const MobileFullscreenPlayerHeader = memo(
|
||||
</Option>
|
||||
<Option>
|
||||
<Option.Label>
|
||||
{t('page.fullscreenPlayer.config.lyricOffset', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('page.fullscreenPlayer.config.lyricOffset')}
|
||||
</Option.Label>
|
||||
<Option.Control>
|
||||
<NumberInput
|
||||
|
||||
@@ -545,7 +545,7 @@ export const MobileFullscreenPlayer = () => {
|
||||
variant={isPageHovered ? 'default' : 'subtle'}
|
||||
/>
|
||||
<Text fw={600} size="lg">
|
||||
{t('page.fullscreenPlayer.lyrics', { postProcess: 'sentenceCase' })}
|
||||
{t('page.fullscreenPlayer.lyrics')}
|
||||
</Text>
|
||||
<ActionIcon
|
||||
icon="x"
|
||||
|
||||
@@ -82,9 +82,7 @@ export const MobilePlayerbar = () => {
|
||||
transition={{ duration: 0.2, ease: 'easeIn' }}
|
||||
>
|
||||
<Tooltip
|
||||
label={t('player.toggleFullscreenPlayer', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
label={t('player.toggleFullscreenPlayer')}
|
||||
openDelay={0}
|
||||
>
|
||||
<ItemImage
|
||||
@@ -208,7 +206,7 @@ export const MobilePlayerbar = () => {
|
||||
mediaPrevious();
|
||||
}}
|
||||
tooltip={{
|
||||
label: t('player.previous', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.previous'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="tertiary"
|
||||
@@ -228,7 +226,7 @@ export const MobilePlayerbar = () => {
|
||||
mediaNext();
|
||||
}}
|
||||
tooltip={{
|
||||
label: t('player.next', { postProcess: 'sentenceCase' }),
|
||||
label: t('player.next'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="tertiary"
|
||||
|
||||
@@ -80,9 +80,7 @@ export const MainPlayButton = forwardRef<HTMLButtonElement, PlayButtonProps>(
|
||||
}}
|
||||
ref={ref}
|
||||
tooltip={{
|
||||
label: isPaused
|
||||
? (t('player.play', { postProcess: 'sentenceCase' }) as string)
|
||||
: (t('player.pause', { postProcess: 'sentenceCase' }) as string),
|
||||
label: isPaused ? (t('player.play') as string) : (t('player.pause') as string),
|
||||
openDelay: 0,
|
||||
}}
|
||||
{...props}
|
||||
|
||||
@@ -54,12 +54,12 @@ export const PlayerConfig = () => {
|
||||
{
|
||||
component: <AudioPlayerTypeConfig />,
|
||||
id: 'audioPlayerType',
|
||||
label: t('setting.audioPlayer', { postProcess: 'titleCase' }),
|
||||
label: t('setting.audioPlayer'),
|
||||
},
|
||||
{
|
||||
component: <AudioDeviceConfig />,
|
||||
id: 'audioDevice',
|
||||
label: t('setting.audioDevice', { postProcess: 'titleCase' }),
|
||||
label: t('setting.audioDevice'),
|
||||
},
|
||||
{
|
||||
component: null,
|
||||
@@ -70,23 +70,17 @@ export const PlayerConfig = () => {
|
||||
{
|
||||
component: <TransitionTypeConfig />,
|
||||
id: 'transitionType',
|
||||
label: t('setting.playbackStyle', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('setting.playbackStyle'),
|
||||
},
|
||||
{
|
||||
component: <CrossfadeStyleConfig />,
|
||||
id: 'crossfadeStyle',
|
||||
label: t('setting.crossfadeStyle', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('setting.crossfadeStyle'),
|
||||
},
|
||||
{
|
||||
component: <CrossfadeDurationConfig />,
|
||||
id: 'crossfadeDuration',
|
||||
label: t('setting.crossfadeDuration', {
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
label: t('setting.crossfadeDuration'),
|
||||
},
|
||||
{
|
||||
component: null,
|
||||
@@ -97,7 +91,7 @@ export const PlayerConfig = () => {
|
||||
{
|
||||
component: <PlaybackSpeedSlider />,
|
||||
id: 'playbackSpeed',
|
||||
label: t('player.playbackSpeed', { postProcess: 'titleCase' }),
|
||||
label: t('player.playbackSpeed'),
|
||||
},
|
||||
{
|
||||
component: (
|
||||
@@ -107,7 +101,7 @@ export const PlayerConfig = () => {
|
||||
/>
|
||||
),
|
||||
id: 'preservePitch',
|
||||
label: t('setting.preservePitch', { postProcess: 'titleCase' }),
|
||||
label: t('setting.preservePitch'),
|
||||
},
|
||||
{
|
||||
component: null,
|
||||
@@ -129,7 +123,7 @@ export const PlayerConfig = () => {
|
||||
/>
|
||||
),
|
||||
id: 'showLyricsInSidebar',
|
||||
label: t('setting.showLyricsInSidebar', { postProcess: 'titleCase' }),
|
||||
label: t('setting.showLyricsInSidebar'),
|
||||
},
|
||||
{
|
||||
component: (
|
||||
@@ -145,7 +139,7 @@ export const PlayerConfig = () => {
|
||||
/>
|
||||
),
|
||||
id: 'showVisualizerInSidebar',
|
||||
label: t('setting.showVisualizerInSidebar', { postProcess: 'titleCase' }),
|
||||
label: t('setting.showVisualizerInSidebar'),
|
||||
},
|
||||
{
|
||||
component: (
|
||||
@@ -161,7 +155,7 @@ export const PlayerConfig = () => {
|
||||
/>
|
||||
),
|
||||
id: 'combinedLyricsAndVisualizer',
|
||||
label: t('setting.combinedLyricsAndVisualizer', { postProcess: 'titleCase' }),
|
||||
label: t('setting.combinedLyricsAndVisualizer'),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -187,7 +181,7 @@ export const PlayerConfig = () => {
|
||||
size="sm"
|
||||
stopsPropagation
|
||||
tooltip={{
|
||||
label: t('common.setting', { count: 2, postProcess: 'titleCase' }),
|
||||
label: t('common.setting', { count: 2 }),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="subtle"
|
||||
@@ -279,14 +273,12 @@ const TransitionTypeConfig = () => {
|
||||
{
|
||||
label: t('setting.playbackStyle', {
|
||||
context: 'optionNormal',
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
value: PlayerStyle.GAPLESS,
|
||||
},
|
||||
{
|
||||
label: t('setting.playbackStyle', {
|
||||
context: 'optionCrossFade',
|
||||
postProcess: 'titleCase',
|
||||
}),
|
||||
value: PlayerStyle.CROSSFADE,
|
||||
},
|
||||
|
||||
@@ -159,7 +159,7 @@ const QueueButton = () => {
|
||||
onClick={handleClick}
|
||||
size="sm"
|
||||
tooltip={{
|
||||
label: t('player.viewQueue', { postProcess: 'titleCase' }),
|
||||
label: t('player.viewQueue'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="subtle"
|
||||
@@ -205,7 +205,7 @@ const LyricsButton = () => {
|
||||
role="button"
|
||||
size="sm"
|
||||
tooltip={{
|
||||
label: t('player.lyrics', { postProcess: 'titleCase' }),
|
||||
label: t('player.lyrics'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="subtle"
|
||||
@@ -288,9 +288,7 @@ const FavoriteButton = () => {
|
||||
}}
|
||||
size="sm"
|
||||
tooltip={{
|
||||
label: currentSong?.userFavorite
|
||||
? t('player.unfavorite', { postProcess: 'titleCase' })
|
||||
: t('player.favorite', { postProcess: 'titleCase' }),
|
||||
label: currentSong?.userFavorite ? t('player.unfavorite') : t('player.favorite'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="subtle"
|
||||
@@ -445,7 +443,7 @@ const VolumeButton = () => {
|
||||
onWheel={handleVolumeWheel}
|
||||
size="sm"
|
||||
tooltip={{
|
||||
label: muted ? t('player.muted', { postProcess: 'titleCase' }) : volume,
|
||||
label: muted ? t('player.muted') : volume,
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="subtle"
|
||||
|
||||
@@ -104,7 +104,7 @@ export const ShuffleAllContextModal = () => {
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<NumberInput
|
||||
label={t('form.shuffleAll.input_limit', { postProcess: 'sentenceCase' })}
|
||||
label={t('form.shuffleAll.input_limit')}
|
||||
max={500}
|
||||
min={1}
|
||||
onChange={(e) => setStore({ limit: e ? Number(e) : 500 })}
|
||||
@@ -113,7 +113,7 @@ export const ShuffleAllContextModal = () => {
|
||||
/>
|
||||
<Group grow>
|
||||
<NumberInput
|
||||
label={t('form.shuffleAll.input_minYear', { postProcess: 'sentenceCase' })}
|
||||
label={t('form.shuffleAll.input_minYear')}
|
||||
max={2050}
|
||||
min={1850}
|
||||
onChange={(e) => setStore({ minYear: e ? Number(e) : 0 })}
|
||||
@@ -127,7 +127,7 @@ export const ShuffleAllContextModal = () => {
|
||||
value={minYear}
|
||||
/>
|
||||
<NumberInput
|
||||
label={t('form.shuffleAll.input_maxYear', { postProcess: 'sentenceCase' })}
|
||||
label={t('form.shuffleAll.input_maxYear')}
|
||||
max={2050}
|
||||
min={1850}
|
||||
onChange={(e) => setStore({ maxYear: e ? Number(e) : 0 })}
|
||||
@@ -148,7 +148,7 @@ export const ShuffleAllContextModal = () => {
|
||||
<Select
|
||||
clearable
|
||||
data={PLAYED_DATA}
|
||||
label={t('form.shuffleAll.input_played', { postProcess: 'sentenceCase' })}
|
||||
label={t('form.shuffleAll.input_played')}
|
||||
onChange={(e) => {
|
||||
setStore({ played: e as Played });
|
||||
}}
|
||||
@@ -191,7 +191,7 @@ export const openShuffleAllModal = async () => {
|
||||
innerProps: {},
|
||||
modal: 'shuffleAll',
|
||||
size: 'sm',
|
||||
title: i18n.t('player.playRandom', { postProcess: 'sentenceCase' }) as string,
|
||||
title: i18n.t('player.playRandom') as string,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -221,7 +221,7 @@ const GenreSelect = () => {
|
||||
<Select
|
||||
clearable
|
||||
data={genreData}
|
||||
label={t('form.shuffleAll.input_genre', { postProcess: 'sentenceCase' })}
|
||||
label={t('form.shuffleAll.input_genre')}
|
||||
onChange={(e) => setStore({ genre: e || '' })}
|
||||
searchable
|
||||
value={genre}
|
||||
|
||||
@@ -176,17 +176,15 @@ export const SleepTimerButton = () => {
|
||||
|
||||
const getPresetLabel = (option: (typeof PRESET_OPTIONS)[number]) => {
|
||||
if (option.mode === 'endOfSong') {
|
||||
return t('player.sleepTimer_endOfSong', { postProcess: 'sentenceCase' });
|
||||
return t('player.sleepTimer_endOfSong');
|
||||
}
|
||||
if (option.minutes >= 60) {
|
||||
return t('player.sleepTimer_hours', {
|
||||
count: option.minutes / 60,
|
||||
postProcess: 'sentenceCase',
|
||||
});
|
||||
}
|
||||
return t('player.sleepTimer_minutes', {
|
||||
count: option.minutes,
|
||||
postProcess: 'sentenceCase',
|
||||
});
|
||||
};
|
||||
|
||||
@@ -205,7 +203,7 @@ export const SleepTimerButton = () => {
|
||||
}}
|
||||
size="sm"
|
||||
tooltip={{
|
||||
label: t('player.sleepTimer', { postProcess: 'titleCase' }),
|
||||
label: t('player.sleepTimer'),
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="subtle"
|
||||
@@ -214,7 +212,7 @@ export const SleepTimerButton = () => {
|
||||
<Popover.Dropdown>
|
||||
<Stack gap="xs" p="xs">
|
||||
<Text fw="600" pb="md" size="sm" ta="center">
|
||||
{t('player.sleepTimer', { postProcess: 'titleCase' })}
|
||||
{t('player.sleepTimer')}
|
||||
</Text>
|
||||
|
||||
{active && (
|
||||
@@ -231,9 +229,7 @@ export const SleepTimerButton = () => {
|
||||
>
|
||||
{mode === 'endOfSong' ? (
|
||||
<Text c="primary" size="sm">
|
||||
{t('player.sleepTimer_endOfSong', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
{t('player.sleepTimer_endOfSong')}
|
||||
</Text>
|
||||
) : (
|
||||
<Text c="primary" fw="600" size="lg">
|
||||
@@ -248,7 +244,7 @@ export const SleepTimerButton = () => {
|
||||
size="compact-xs"
|
||||
variant="subtle"
|
||||
>
|
||||
{t('player.sleepTimer_cancel', { postProcess: 'titleCase' })}
|
||||
{t('player.sleepTimer_cancel')}
|
||||
</Button>
|
||||
</Flex>
|
||||
)}
|
||||
@@ -309,7 +305,7 @@ export const SleepTimerButton = () => {
|
||||
ta="center"
|
||||
variant="outline"
|
||||
>
|
||||
{t('player.sleepTimer_custom', { postProcess: 'sentenceCase' })}
|
||||
{t('player.sleepTimer_custom')}
|
||||
</Button>
|
||||
) : (
|
||||
<Stack gap="xs">
|
||||
@@ -350,7 +346,7 @@ export const SleepTimerButton = () => {
|
||||
size="xs"
|
||||
variant="filled"
|
||||
>
|
||||
{t('player.sleepTimer_setCustom', { postProcess: 'titleCase' })}
|
||||
{t('player.sleepTimer_setCustom')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={(e) => {
|
||||
@@ -360,7 +356,7 @@ export const SleepTimerButton = () => {
|
||||
size="xs"
|
||||
variant="default"
|
||||
>
|
||||
{t('common.cancel', { postProcess: 'titleCase' })}
|
||||
{t('common.cancel')}
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
|
||||
@@ -158,8 +158,8 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
children: (
|
||||
<ConfirmModal
|
||||
labels={{
|
||||
cancel: t('common.cancel', { postProcess: 'titleCase' }),
|
||||
confirm: t('common.confirm', { postProcess: 'titleCase' }),
|
||||
cancel: t('common.cancel'),
|
||||
confirm: t('common.confirm'),
|
||||
}}
|
||||
onCancel={() => {
|
||||
resolve(false);
|
||||
@@ -171,15 +171,9 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
}}
|
||||
>
|
||||
<Stack>
|
||||
<Text>
|
||||
{t('form.largeFetchConfirmation.description', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Text>
|
||||
<Text>{t('form.largeFetchConfirmation.description')}</Text>
|
||||
<Checkbox
|
||||
label={t('common.doNotShowAgain', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
label={t('common.doNotShowAgain')}
|
||||
onChange={(event) => {
|
||||
setDoNotShowAgain(event.currentTarget.checked);
|
||||
}}
|
||||
@@ -187,9 +181,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
</Stack>
|
||||
</ConfirmModal>
|
||||
),
|
||||
title: t('form.largeFetchConfirmation.title', {
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
title: t('form.largeFetchConfirmation.title'),
|
||||
});
|
||||
});
|
||||
}, [doNotShowAgain, setDoNotShowAgain, t]);
|
||||
@@ -236,9 +228,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
[fetchId]: setTimeout(() => {
|
||||
toastId = toast.info({
|
||||
autoClose: false,
|
||||
message: t('player.playbackFetchCancel', {
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
message: t('player.playbackFetchCancel'),
|
||||
onClose: () => {
|
||||
queryClient.cancelQueries({
|
||||
exact: false,
|
||||
@@ -250,9 +240,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
queryKey: queryKeys.player.fetch(),
|
||||
});
|
||||
},
|
||||
title: t('player.playbackFetchInProgress', {
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
title: t('player.playbackFetchInProgress'),
|
||||
});
|
||||
}, 2000),
|
||||
};
|
||||
@@ -312,7 +300,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
|
||||
toast.error({
|
||||
message: err.message,
|
||||
title: t('error.genericError', { postProcess: 'sentenceCase' }) as string,
|
||||
title: t('error.genericError') as string,
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -401,9 +389,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
[fetchId]: setTimeout(() => {
|
||||
toastId = toast.info({
|
||||
autoClose: false,
|
||||
message: t('player.playbackFetchCancel', {
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
message: t('player.playbackFetchCancel'),
|
||||
onClose: () => {
|
||||
logFn.debug(logMsg[LogCategory.PLAYER].cancelledFetch, {
|
||||
category: LogCategory.PLAYER,
|
||||
@@ -420,9 +406,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
queryKey: queryKeys.player.fetch(),
|
||||
});
|
||||
},
|
||||
title: t('player.playbackFetchInProgress', {
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
title: t('player.playbackFetchInProgress'),
|
||||
});
|
||||
}, 2000),
|
||||
};
|
||||
@@ -497,7 +481,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
|
||||
toast.error({
|
||||
message: err.message,
|
||||
title: t('error.genericError', { postProcess: 'sentenceCase' }) as string,
|
||||
title: t('error.genericError') as string,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -43,7 +43,7 @@ export const useSaveQueue = () => {
|
||||
const mutation = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (!serverId) {
|
||||
throw new Error(t('error.serverRequired', { postProcess: 'sentenceCase' }));
|
||||
throw new Error(t('error.serverRequired'));
|
||||
}
|
||||
|
||||
const state = usePlayerStore.getState();
|
||||
@@ -51,15 +51,11 @@ export const useSaveQueue = () => {
|
||||
|
||||
if (queue.items.some((item) => item._serverId !== serverId)) {
|
||||
toast.error({
|
||||
message: t('error.multipleServerSaveQueueError', {
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
title: t('error.genericError', { postProcess: 'sentenceCase' }),
|
||||
message: t('error.multipleServerSaveQueueError'),
|
||||
title: t('error.genericError'),
|
||||
});
|
||||
|
||||
throw new Error(
|
||||
`${t('error.multipleServerSaveQueueError', { postProcess: 'sentenceCase' })}`,
|
||||
);
|
||||
throw new Error(`${t('error.multipleServerSaveQueueError')}`);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -73,12 +69,12 @@ export const useSaveQueue = () => {
|
||||
});
|
||||
|
||||
toast.success({
|
||||
message: t('form.saveQueue.success', { postProcess: 'sentenceCase' }),
|
||||
message: t('form.saveQueue.success'),
|
||||
});
|
||||
} catch (error) {
|
||||
toast.error({
|
||||
message: (error as Error).message,
|
||||
title: t('error.saveQueueFailed', { postProcess: 'sentenceCase' }),
|
||||
title: t('error.saveQueueFailed'),
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@@ -111,7 +107,7 @@ export const useRestoreQueue = () => {
|
||||
} catch (error) {
|
||||
toast.error({
|
||||
message: (error as Error).message,
|
||||
title: t('error.genericError', { postProcess: 'sentenceCase' }),
|
||||
title: t('error.genericError'),
|
||||
});
|
||||
}
|
||||
}, [player, queryClient, serverId]);
|
||||
|
||||
@@ -19,7 +19,7 @@ export const openVisualizerSettingsModal = () => {
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
title: i18n.t('common.setting', { count: 2, postProcess: 'titleCase' }),
|
||||
title: i18n.t('common.setting', { count: 2 }),
|
||||
transitionProps: {
|
||||
transition: 'pop',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user