mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-01 18:33:33 +00:00
Add localization support (#333)
* Add updated i18n config and en locale
This commit is contained in:
parent
11863fd4c1
commit
8430b1ec95
90 changed files with 2679 additions and 908 deletions
|
|
@ -11,6 +11,7 @@ import {
|
|||
import { closeAllModals, openContextModal, openModal } from '@mantine/modals';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import isElectron from 'is-electron';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
RiAddBoxFill,
|
||||
RiAddCircleFill,
|
||||
|
|
@ -87,6 +88,7 @@ export interface ContextMenuProviderProps {
|
|||
}
|
||||
|
||||
export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [opened, setOpened] = useState(false);
|
||||
const clickOutsideRef = useClickOutside(() => setOpened(false));
|
||||
|
||||
|
|
@ -229,7 +231,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
onError: (err) => {
|
||||
toast.error({
|
||||
message: err.message,
|
||||
title: 'Error deleting playlist',
|
||||
title: t('error.genericError', { postProcess: 'sentenceCase' }),
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
|
|
@ -245,14 +247,14 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
}
|
||||
|
||||
closeAllModals();
|
||||
}, [ctx, deletePlaylistMutation]);
|
||||
}, [ctx, deletePlaylistMutation, t]);
|
||||
|
||||
const openDeletePlaylistModal = useCallback(() => {
|
||||
openModal({
|
||||
children: (
|
||||
<ConfirmModal onConfirm={handleDeletePlaylist}>
|
||||
<Stack>
|
||||
<Text>Are you sure you want to delete the following playlist(s)?</Text>
|
||||
<Text>{t('common.areYouSure', { postProcess: 'sentenceCase' })}</Text>
|
||||
<ul>
|
||||
{ctx.data.map((item) => (
|
||||
<li key={item.id}>
|
||||
|
|
@ -265,9 +267,9 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
</Stack>
|
||||
</ConfirmModal>
|
||||
),
|
||||
title: 'Delete playlist(s)',
|
||||
title: t('page.contextMenu.deletePlaylist', { postProcess: 'titleCase' }),
|
||||
});
|
||||
}, [ctx.data, handleDeletePlaylist]);
|
||||
}, [ctx.data, handleDeletePlaylist, t]);
|
||||
|
||||
const createFavoriteMutation = useCreateFavorite({});
|
||||
const deleteFavoriteMutation = useDeleteFavorite({});
|
||||
|
|
@ -301,7 +303,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
onError: (err) => {
|
||||
toast.error({
|
||||
message: err.message,
|
||||
title: 'Error adding to favorites',
|
||||
title: t('error.genericError', { postProcess: 'sentenceCase' }),
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
|
|
@ -337,14 +339,14 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
onError: (err) => {
|
||||
toast.error({
|
||||
message: err.message,
|
||||
title: 'Error adding to favorites',
|
||||
title: t('error.genericError', { postProcess: 'sentenceCase' }),
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [createFavoriteMutation, ctx.data, ctx.dataNodes, ctx.type]);
|
||||
}, [createFavoriteMutation, ctx.data, ctx.dataNodes, ctx.type, t]);
|
||||
|
||||
const handleRemoveFromFavorites = useCallback(() => {
|
||||
if (!ctx.dataNodes && !ctx.data) return;
|
||||
|
|
@ -459,9 +461,9 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
},
|
||||
modal: 'addToPlaylist',
|
||||
size: 'md',
|
||||
title: 'Add to playlist',
|
||||
title: t('page.contextMenu.addToPlaylist', { postProcess: 'sentenceCase' }),
|
||||
});
|
||||
}, [ctx.data, ctx.dataNodes]);
|
||||
}, [ctx.data, ctx.dataNodes, t]);
|
||||
|
||||
const removeFromPlaylistMutation = useRemoveFromPlaylist();
|
||||
|
||||
|
|
@ -484,13 +486,10 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
onError: (err) => {
|
||||
toast.error({
|
||||
message: err.message,
|
||||
title: 'Error removing song(s) from playlist',
|
||||
title: t('error.genericError', { postProcess: 'sentenceCase' }),
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success({
|
||||
message: `${songId.length} song(s) were removed from the playlist`,
|
||||
});
|
||||
ctx.context?.tableRef?.current?.api?.refreshInfiniteCache();
|
||||
closeAllModals();
|
||||
},
|
||||
|
|
@ -504,10 +503,10 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
loading={removeFromPlaylistMutation.isLoading}
|
||||
onConfirm={confirm}
|
||||
>
|
||||
Are you sure you want to remove the following song(s) from the playlist?
|
||||
{t('common.areYouSure', { postProcess: 'sentenceCase' })}
|
||||
</ConfirmModal>
|
||||
),
|
||||
title: 'Remove song(s) from playlist',
|
||||
title: t('page.contextMenu.removeFromPlaylist', { postProcess: 'sentenceCase' }),
|
||||
});
|
||||
}, [
|
||||
ctx.context?.playlistId,
|
||||
|
|
@ -516,6 +515,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
ctx.dataNodes,
|
||||
removeFromPlaylistMutation,
|
||||
serverType,
|
||||
t,
|
||||
]);
|
||||
|
||||
const updateRatingMutation = useSetRating({});
|
||||
|
|
@ -631,74 +631,78 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
return {
|
||||
addToFavorites: {
|
||||
id: 'addToFavorites',
|
||||
label: 'Add favorite',
|
||||
label: t('page.contextMenu.addToFavorites', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiHeartFill size="1.1rem" />,
|
||||
onClick: handleAddToFavorites,
|
||||
},
|
||||
addToPlaylist: {
|
||||
id: 'addToPlaylist',
|
||||
label: 'Add to playlist',
|
||||
label: t('page.contextMenu.addToPlaylist', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiPlayListAddFill size="1.1rem" />,
|
||||
onClick: handleAddToPlaylist,
|
||||
},
|
||||
createPlaylist: { id: 'createPlaylist', label: 'Create playlist', onClick: () => {} },
|
||||
createPlaylist: {
|
||||
id: 'createPlaylist',
|
||||
label: t('page.contextMenu.createPlaylist', { postProcess: 'sentenceCase' }),
|
||||
onClick: () => {},
|
||||
},
|
||||
deletePlaylist: {
|
||||
id: 'deletePlaylist',
|
||||
label: 'Delete playlist',
|
||||
label: t('page.contextMenu.deletePlaylist', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiDeleteBinFill size="1.1rem" />,
|
||||
onClick: openDeletePlaylistModal,
|
||||
},
|
||||
deselectAll: {
|
||||
id: 'deselectAll',
|
||||
label: 'Deselect all',
|
||||
label: t('page.contextMenu.deselectAll', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiCloseCircleLine size="1.1rem" />,
|
||||
onClick: handleDeselectAll,
|
||||
},
|
||||
moveToBottomOfQueue: {
|
||||
id: 'moveToBottomOfQueue',
|
||||
label: 'Move to bottom',
|
||||
label: t('page.contextMenu.moveToBottom', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiArrowDownLine size="1.1rem" />,
|
||||
onClick: handleMoveToBottom,
|
||||
},
|
||||
moveToTopOfQueue: {
|
||||
id: 'moveToTopOfQueue',
|
||||
label: 'Move to top',
|
||||
label: t('page.contextMenu.moveToTop', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiArrowUpLine size="1.1rem" />,
|
||||
onClick: handleMoveToTop,
|
||||
},
|
||||
play: {
|
||||
id: 'play',
|
||||
label: 'Play',
|
||||
label: t('page.contextMenu.play', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiPlayFill size="1.1rem" />,
|
||||
onClick: () => handlePlay(Play.NOW),
|
||||
},
|
||||
playLast: {
|
||||
id: 'playLast',
|
||||
label: 'Add to queue',
|
||||
label: t('page.contextMenu.addLast', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiAddBoxFill size="1.1rem" />,
|
||||
onClick: () => handlePlay(Play.LAST),
|
||||
},
|
||||
playNext: {
|
||||
id: 'playNext',
|
||||
label: 'Add to queue next',
|
||||
label: t('page.contextMenu.addNext', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiAddCircleFill size="1.1rem" />,
|
||||
onClick: () => handlePlay(Play.NEXT),
|
||||
},
|
||||
removeFromFavorites: {
|
||||
id: 'removeFromFavorites',
|
||||
label: 'Remove favorite',
|
||||
label: t('page.contextMenu.removeFromFavorites', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiDislikeFill size="1.1rem" />,
|
||||
onClick: handleRemoveFromFavorites,
|
||||
},
|
||||
removeFromPlaylist: {
|
||||
id: 'removeFromPlaylist',
|
||||
label: 'Remove from playlist',
|
||||
label: t('page.contextMenu.removeFromPlaylist', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiDeleteBinFill size="1.1rem" />,
|
||||
onClick: handleRemoveFromPlaylist,
|
||||
},
|
||||
removeFromQueue: {
|
||||
id: 'moveToBottomOfQueue',
|
||||
label: 'Remove songs',
|
||||
id: 'removeSongs',
|
||||
label: t('page.contextMenu.removeFromQueue', { postProcess: 'sentenceCase' }),
|
||||
leftIcon: <RiDeleteBinFill size="1.1rem" />,
|
||||
onClick: handleRemoveSelected,
|
||||
},
|
||||
|
|
@ -784,6 +788,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
handleRemoveSelected,
|
||||
handleUpdateRating,
|
||||
openDeletePlaylistModal,
|
||||
t,
|
||||
]);
|
||||
|
||||
const mergedRef = useMergedRef(ref, clickOutsideRef);
|
||||
|
|
@ -888,7 +893,10 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
|||
size="sm"
|
||||
/>
|
||||
<ContextMenuButton disabled>
|
||||
{ctx.data?.length} selected
|
||||
{t('page.contextMenu.numberSelected', {
|
||||
count: ctx.data?.length || 0,
|
||||
postProcess: 'lowerCase',
|
||||
})}
|
||||
</ContextMenuButton>
|
||||
</Stack>
|
||||
</ContextMenu>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue