Add localization support (#333)

* Add updated i18n config and en locale
This commit is contained in:
Jeff 2023-10-30 19:22:45 -07:00 committed by GitHub
parent 11863fd4c1
commit 8430b1ec95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
90 changed files with 2679 additions and 908 deletions

View file

@ -1,4 +1,5 @@
import { useCallback, Dispatch } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router';
import { Command, CommandPalettePages } from '/@/renderer/features/search/components/command';
import { AppRoute } from '/@/renderer/router/routes';
@ -10,6 +11,7 @@ interface GoToCommandsProps {
}
export const GoToCommands = ({ setQuery, setPages, handleClose }: GoToCommandsProps) => {
const { t } = useTranslation();
const navigate = useNavigate();
const goTo = useCallback(
@ -25,19 +27,35 @@ export const GoToCommands = ({ setQuery, setPages, handleClose }: GoToCommandsPr
return (
<>
<Command.Group>
<Command.Item onSelect={() => goTo(AppRoute.HOME)}>Home</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.SEARCH)}>Search</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.SETTINGS)}>Settings</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.HOME)}>
{t('page.sidebar.home', { postProcess: 'titleCase' })}
</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.SEARCH)}>
{t('page.sidebar.search', { postProcess: 'titleCase' })}
</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.SETTINGS)}>
{t('page.sidebar.settings', { postProcess: 'titleCase' })}
</Command.Item>
</Command.Group>
<Command.Group heading="Library">
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_ALBUMS)}>Albums</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_SONGS)}>Tracks</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_ALBUM_ARTISTS)}>
Album artists
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_ALBUMS)}>
{t('page.sidebar.albums', { postProcess: 'titleCase' })}
</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_SONGS)}>
{t('page.sidebar.tracks', { postProcess: 'titleCase' })}
</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_ALBUM_ARTISTS)}>
{t('page.sidebar.albumArtists', { postProcess: 'titleCase' })}
</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_GENRES)}>
{t('page.sidebar.genres', { postProcess: 'titleCase' })}
</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_FOLDERS)}>
{t('page.sidebar.folders', { postProcess: 'titleCase' })}
</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.PLAYLISTS)}>
{t('page.sidebar.playlists', { postProcess: 'titleCase' })}
</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_GENRES)}>Genres</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.LIBRARY_FOLDERS)}>Folders</Command.Item>
<Command.Item onSelect={() => goTo(AppRoute.PLAYLISTS)}>Playlists</Command.Item>
</Command.Group>
<Command.Separator />
</>

View file

@ -1,6 +1,7 @@
import { Dispatch, useCallback } from 'react';
import { openModal, closeAllModals } from '@mantine/modals';
import { nanoid } from 'nanoid/non-secure';
import { Dispatch, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { generatePath, useNavigate } from 'react-router';
import { createSearchParams } from 'react-router-dom';
import { LibraryItem } from '/@/renderer/api/types';
@ -25,6 +26,7 @@ export const HomeCommands = ({
setPages,
handleClose,
}: HomeCommandsProps) => {
const { t } = useTranslation();
const navigate = useNavigate();
const server = useCurrentServer();
@ -34,9 +36,9 @@ export const HomeCommands = ({
openModal({
children: <CreatePlaylistForm onCancel={() => closeAllModals()} />,
size: server?.type === ServerType?.NAVIDROME ? 'xl' : 'sm',
title: 'Create Playlist',
title: t('form.createPlaylist.title', { postProcess: 'sentenceCase' }),
});
}, [handleClose, server?.type]);
}, [handleClose, server?.type, t]);
const handleSearch = () => {
navigate(
@ -58,21 +60,31 @@ export const HomeCommands = ({
return (
<>
<Command.Group heading="Commands">
<Command.Group heading={t('page.globalSearch.title', { postProcess: 'titleCase' })}>
<Command.Item
value="Search"
value={t('common.search', { postProcess: 'sentenceCase' })}
onSelect={handleSearch}
>
{query ? `Search for "${query}"...` : 'Search...'}
{query
? t('page.globalSearch.commands.searchFor', {
postProcess: 'sentenceCase',
query,
})
: `${t('common.search', { postProcess: 'sentenceCase' })}...`}
</Command.Item>
<Command.Item onSelect={handleCreatePlaylistModal}>
{t('action.createPlaylist', { postProcess: 'sentenceCase' })}...
</Command.Item>
<Command.Item onSelect={handleCreatePlaylistModal}>Create playlist...</Command.Item>
<Command.Item onSelect={() => setPages([...pages, CommandPalettePages.GO_TO])}>
Go to page...
{t('page.globalSearch.commands.goToPage', { postProcess: 'sentenceCase' })}...
</Command.Item>
<Command.Item
onSelect={() => setPages([...pages, CommandPalettePages.MANAGE_SERVERS])}
>
Server commands...
{t('page.globalSearch.commands.serverCommands', {
postProcess: 'sentenceCase',
})}
...
</Command.Item>
</Command.Group>
</>

View file

@ -1,5 +1,6 @@
import { Center, Flex } from '@mantine/core';
import { useCallback, MouseEvent } from 'react';
import { Center, Flex } from '@mantine/core';
import { useTranslation } from 'react-i18next';
import {
RiAddBoxFill,
RiAddCircleFill,
@ -68,6 +69,7 @@ export const LibraryCommandItem = ({
itemType,
handlePlayQueueAdd,
}: LibraryCommandItemProps) => {
const { t } = useTranslation();
let Placeholder = RiAlbumFill;
switch (itemType) {
@ -153,7 +155,10 @@ export const LibraryCommandItem = ({
<Button
compact
size="md"
tooltip={{ label: 'Play', openDelay: 500 }}
tooltip={{
label: t('player.play', { postProcess: 'sentenceCase' }),
openDelay: 500,
}}
variant="default"
onClick={(e) => handlePlay(e, id, Play.NOW)}
>
@ -162,7 +167,11 @@ export const LibraryCommandItem = ({
<Button
compact
size="md"
tooltip={{ label: 'Add to queue', openDelay: 500 }}
tooltip={{
label: t('player.addLast', { postProcess: 'sentenceCase' }),
openDelay: 500,
}}
variant="default"
onClick={(e) => handlePlay(e, id, Play.LAST)}
>
@ -171,7 +180,10 @@ export const LibraryCommandItem = ({
<Button
compact
size="md"
tooltip={{ label: 'Play next', openDelay: 500 }}
tooltip={{
label: t('player.addNext', { postProcess: 'sentenceCase' }),
openDelay: 500,
}}
variant="default"
onClick={(e) => handlePlay(e, id, Play.NEXT)}
>

View file

@ -4,6 +4,7 @@ import { Command, CommandPalettePages } from '/@/renderer/features/search/compon
import { ServerList } from '/@/renderer/features/servers';
import { useAuthStoreActions, useServerList } from '/@/renderer/store';
import { ServerListItem } from '/@/renderer/types';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router';
import { AppRoute } from '/@/renderer/router/routes';
@ -14,6 +15,7 @@ interface ServerCommandsProps {
}
export const ServerCommands = ({ setQuery, setPages, handleClose }: ServerCommandsProps) => {
const { t } = useTranslation();
const serverList = useServerList();
const navigate = useNavigate();
const { setCurrentServer } = useAuthStoreActions();
@ -21,12 +23,12 @@ export const ServerCommands = ({ setQuery, setPages, handleClose }: ServerComman
const handleManageServersModal = useCallback(() => {
openModal({
children: <ServerList />,
title: 'Manage Servers',
title: t('page.appMenu.manageServers', { postProcess: 'sentenceCase' }),
});
handleClose();
setQuery('');
setPages([CommandPalettePages.HOME]);
}, [handleClose, setPages, setQuery]);
}, [handleClose, setPages, setQuery, t]);
const handleSelectServer = useCallback(
(server: ServerListItem) => {
@ -41,16 +43,20 @@ export const ServerCommands = ({ setQuery, setPages, handleClose }: ServerComman
return (
<>
<Command.Group heading="Select a server">
<Command.Group
heading={t('page.appMenu.selectServer', { postProcess: 'sentenceCase' })}
>
{Object.keys(serverList).map((key) => (
<Command.Item
key={key}
onSelect={() => handleSelectServer(serverList[key])}
>{`Switch to ${serverList[key].name}...`}</Command.Item>
>{`${serverList[key].name}...`}</Command.Item>
))}
</Command.Group>
<Command.Group heading="Manage">
<Command.Item onSelect={handleManageServersModal}>Manage servers...</Command.Item>
<Command.Group heading={t('common.manage', { postProcess: 'sentenceCase' })}>
<Command.Item onSelect={handleManageServersModal}>
{t('page.appMenu.manageServers', { postProcess: 'sentenceCase' })}...
</Command.Item>
</Command.Group>
<Command.Separator />
</>