Skip to content

Commit

Permalink
Added even more i18n translation keys (#2453)
Browse files Browse the repository at this point in the history
* more translation keys

* added i18n keys for future ObjectKindEnum translation

* more keys

* added more keys

* synced all new translation keys with all languages, translated keys on Belarusian and Russian

* added translation for objectkinds in overview

* added translation function for objectkinds

* added more keys to german locale

* renamed 'asc' and 'desc' keys

* rolled back changes

* added missed key

* there are much more keys, than you can imagine

* fixed misspelling

* removed console.log

* removed function "pluralize", added required plural words keys for each language

* fixed condition, which could've lead to undefined value

* hide filter description for boolean filters
  • Loading branch information
artsiom-voitas committed May 4, 2024
1 parent 70039ac commit 2d78ede
Show file tree
Hide file tree
Showing 50 changed files with 2,615 additions and 1,277 deletions.
30 changes: 14 additions & 16 deletions interface/ErrorFallback.tsx
Expand Up @@ -9,7 +9,7 @@ import { useDebugState } from '@sd/client';
import { Button, Dialogs } from '@sd/ui';

import { showAlertDialog } from './components';
import { useOperatingSystem, useTheme } from './hooks';
import { useLocale, useOperatingSystem, useTheme } from './hooks';
import { usePlatform } from './util/Platform';

const sentryBrowserLazy = import('@sentry/browser');
Expand Down Expand Up @@ -75,6 +75,8 @@ export function ErrorPage({
localStorage.getItem(RENDERING_ERROR_LOCAL_STORAGE_KEY)
);

const { t } = useLocale();

// If the user is on a page and the user presses "Reset" on the error boundary, it may crash in rendering causing the user to get stuck on the error page.
// If it crashes again, we redirect them instead of infinitely crashing.
useEffect(() => {
Expand All @@ -91,9 +93,9 @@ export function ErrorPage({

const resetHandler = () => {
showAlertDialog({
title: 'Reset',
value: 'Are you sure you want to reset Spacedrive? Your database will be deleted.',
label: 'Confirm',
title: t('reset'),
value: t('reset_confirmation'),
label: t('confirm'),
cancelBtn: true,
onSubmit: () => {
localStorage.clear();
Expand All @@ -116,16 +118,16 @@ export function ErrorPage({
}
>
<Dialogs />
<p className="m-3 text-sm font-bold text-ink-faint">APP CRASHED</p>
<h1 className="text-2xl font-bold text-ink">We're past the event horizon...</h1>
<p className="m-3 text-sm font-bold text-ink-faint">{t('app_crashed')}</p>
<h1 className="text-2xl font-bold text-ink">{t('app_crashed_description')}</h1>
<pre className="m-2 max-w-[650px] whitespace-normal text-center text-ink">
{message}
</pre>
{submessage && <pre className="m-2 text-sm text-ink-dull">{submessage}</pre>}
<div className="flex flex-row space-x-2 text-ink">
{reloadBtn && (
<Button variant="accent" className="mt-2" onClick={reloadBtn}>
Reload
{t('reload')}
</Button>
)}
<Button
Expand All @@ -139,11 +141,11 @@ export function ErrorPage({
)
}
>
Send report
{t('send_report')}
</Button>
{platform.openLogsDir && (
<Button variant="gray" className="mt-2" onClick={platform.openLogsDir}>
Open Logs
{t('open_logs')}
</Button>
)}

Expand All @@ -152,19 +154,15 @@ export function ErrorPage({
message.startsWith('failed to initialize library manager')) && (
<div className="flex flex-col items-center pt-12">
<p className="text-md max-w-[650px] text-center">
We detected you may have created your library with an older version of
Spacedrive. Please reset it to continue using the app!
</p>
<p className="mt-3 font-bold">
{' '}
YOU WILL LOSE ANY EXISTING SPACEDRIVE DATA!
{t('reset_to_continue')}
</p>
<p className="mt-3 font-bold"> {t('reset_warning')}</p>
<Button
variant="colored"
onClick={resetHandler}
className="mt-4 max-w-xs border-transparent bg-red-500"
>
Reset & Quit App
{t('reset_and_quit')}
</Button>
</div>
)}
Expand Down
Expand Up @@ -250,7 +250,7 @@ export const ParentFolderActions = new ConditionalItem({
} catch (error) {
toast.error({
title: t('failed_to_rescan_location'),
body: `Error: ${error}.`
body: t('error_message', { error })
});
}
}}
Expand Down
Expand Up @@ -35,7 +35,7 @@ export const RemoveFromRecents = new ConditionalItem({
} catch (error) {
toast.error({
title: t('failed_to_remove_file_from_recents'),
body: `Error: ${error}.`
body: t('error_message', { error })
});
}
}}
Expand Down
5 changes: 3 additions & 2 deletions interface/app/$libraryId/Explorer/ContextMenu/OpenWith.tsx
Expand Up @@ -79,6 +79,7 @@ const Items = ({

const ids = selectedFilePaths.map((obj) => obj.id);
const paths = selectedEphemeralPaths.map((obj) => obj.path);
const { t } = useLocale();

const items = useQuery<unknown>(
['openWith', ids, paths],
Expand Down Expand Up @@ -109,15 +110,15 @@ const Items = ({
);
}
} catch (e) {
toast.error(`Failed to open file, with: ${data.url}`);
toast.error(t('failed_to_open_file_with', { data: data.url }));
}
}}
>
{data.name}
</Menu.Item>
))
) : (
<p className="w-full text-center text-sm text-gray-400"> No apps available </p>
<p className="w-full text-center text-sm text-gray-400">{t('no_apps_available')}</p>
)}
</>
);
Expand Down
2 changes: 1 addition & 1 deletion interface/app/$libraryId/Explorer/CopyAsPath.tsx
Expand Up @@ -27,7 +27,7 @@ export const CopyAsPathBase = (
} catch (error) {
toast.error({
title: t('failed_to_copy_file_path'),
body: `Error: ${error}.`
body: t('error_message', { error })
});
}
}}
Expand Down
2 changes: 1 addition & 1 deletion interface/app/$libraryId/Explorer/DismissibleNotice.tsx
Expand Up @@ -50,7 +50,7 @@ const notices = {
},
media: {
key: 'mediaView',
title: 'Media View',
title: i18n.t('media_view'),
description: i18n.t('media_view_notice_description'),
icon: <MediaViewIcon />
}
Expand Down
18 changes: 11 additions & 7 deletions interface/app/$libraryId/Explorer/FilePath/DeleteDialog.tsx
@@ -1,5 +1,6 @@
import { useLibraryMutation, useZodForm } from '@sd/client';
import { CheckBox, Dialog, Tooltip, useDialog, UseDialogProps } from '@sd/ui';
import i18n from '~/app/I18n';
import { Icon } from '~/components';
import { useLocale } from '~/hooks';

Expand All @@ -18,11 +19,11 @@ interface Props extends UseDialogProps {

function getWording(dirCount: number, fileCount: number) {
let type = 'file';
let prefix = 'a';
let prefix = i18n.t('prefix_a');

if (dirCount == 1 && fileCount == 0) {
type = 'directory';
prefix = 'a';
type = i18n.t('directory');
prefix = i18n.t('prefix_a');
}

if (dirCount > 1 && fileCount == 0) {
Expand All @@ -40,7 +41,9 @@ function getWording(dirCount: number, fileCount: number) {
prefix = (fileCount + dirCount).toString();
}

return { type, prefix };
const translatedType = i18n.t(`${type}`);

return { type, prefix, translatedType };
}

export default (props: Props) => {
Expand All @@ -53,11 +56,11 @@ export default (props: Props) => {
const form = useZodForm();
const { dirCount = 0, fileCount = 0, indexedArgs, ephemeralArgs } = props;

const { type, prefix } = getWording(dirCount, fileCount);
const { type, prefix, translatedType } = getWording(dirCount, fileCount);

const icon = type === 'file' || type === 'files' ? 'Document' : 'Folder';

const description = t('delete_warning', { type });
const description = t('delete_warning', { type: translatedType });

return (
<Dialog
Expand Down Expand Up @@ -102,11 +105,12 @@ export default (props: Props) => {
})}
icon={<Icon theme="light" name={icon} size={28} />}
dialog={useDialog(props)}
title={t('delete_dialog_title', { prefix, type })}
title={t('delete_dialog_title', { prefix, type: translatedType })}
description={description}
loading={deleteFile.isLoading}
ctaLabel={t('delete_forever')}
ctaSecondLabel={t('move_to_trash')}
closeLabel={t('close')}
ctaDanger
className="w-[200px]"
>
Expand Down
4 changes: 3 additions & 1 deletion interface/app/$libraryId/Explorer/Inspector/Note.tsx
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from 'react';
import { useDebouncedCallback } from 'use-debounce';
import { Object as SDObject, useLibraryMutation } from '@sd/client';
import { Divider, TextArea } from '@sd/ui';
import { useLocale } from '~/hooks';

import { MetaContainer, MetaTitle } from '../Inspector';

Expand All @@ -27,12 +28,13 @@ export default function Note(props: Props) {
useEffect(() => () => flush.current?.(), []);

const [cachedNote, setCachedNote] = useState(props.data.note);
const { t } = useLocale();

return (
<>
<Divider />
<MetaContainer>
<MetaTitle>Note</MetaTitle>
<MetaTitle>{t('note')}</MetaTitle>
<TextArea
className="mb-1 mt-2 !py-2 text-xs leading-snug"
value={cachedNote ?? ''}
Expand Down
6 changes: 3 additions & 3 deletions interface/app/$libraryId/Explorer/Inspector/index.tsx
Expand Up @@ -54,7 +54,7 @@ import { FileThumb } from '../FilePath/Thumb';
import { useQuickPreviewStore } from '../QuickPreview/store';
import { explorerStore } from '../store';
import { useExplorerItemData } from '../useExplorerItemData';
import { uniqueId } from '../util';
import { translateKindName, uniqueId } from '../util';
import { RenamableItemText } from '../View/RenamableItemText';
import FavoriteButton from './FavoriteButton';
import MediaData from './MediaData';
Expand Down Expand Up @@ -368,7 +368,7 @@ export const SingleItemMetadata = ({ item }: { item: ExplorerItem }) => {
{mediaData.data && <MediaData data={mediaData.data} />}

<MetaContainer className="flex !flex-row flex-wrap gap-1 overflow-hidden">
<InfoPill>{isDir ? 'Folder' : kind}</InfoPill>
<InfoPill>{isDir ? t('folder') : translateKindName(kind)}</InfoPill>

{extension && <InfoPill>{extension}</InfoPill>}

Expand Down Expand Up @@ -561,7 +561,7 @@ const MultiItemMetadata = ({ items }: { items: ExplorerItem[] }) => {

<MetaContainer className="flex !flex-row flex-wrap gap-1 overflow-hidden">
{[...metadata.kinds].map(([kind, items]) => (
<InfoPill key={kind}>{`${kind} (${items.length})`}</InfoPill>
<InfoPill key={kind}>{`${translateKindName(kind)} (${items.length})`}</InfoPill>
))}

{/* {labels.data?.map((label) => {
Expand Down
2 changes: 1 addition & 1 deletion interface/app/$libraryId/Explorer/OptionsPanel/index.tsx
Expand Up @@ -69,7 +69,7 @@ export default () => {
>
{SortOrderSchema.options.map((o) => (
<SelectOption key={o.value} value={o.value}>
{o.value}
{o.description}
</SelectOption>
))}
</Select>
Expand Down
16 changes: 8 additions & 8 deletions interface/app/$libraryId/Explorer/ParentContextMenu.tsx
Expand Up @@ -38,7 +38,7 @@ export default (props: PropsWithChildren) => {
const rescanLocation = useLibraryMutation('locations.subPathRescan');
const createFolder = useLibraryMutation(['files.createFolder'], {
onError: (e) => {
toast.error({ title: t('create_folder_error'), body: `Error: ${e}.` });
toast.error({ title: t('create_folder_error'), body: t('error_message', { error: e }) });
console.error(e);
},
onSuccess: (folder) => {
Expand All @@ -52,7 +52,7 @@ export default (props: PropsWithChildren) => {
});
const createFile = useLibraryMutation(['files.createFile'], {
onError: (e) => {
toast.error({ title: t('create_file_error'), body: `${e}.` });
toast.error({ title: t('create_file_error'), body: t('error_message', { error: e }) });
console.error(e);
},
onSuccess: (file) => {
Expand All @@ -66,7 +66,7 @@ export default (props: PropsWithChildren) => {
});
const createEphemeralFolder = useLibraryMutation(['ephemeralFiles.createFolder'], {
onError: (e) => {
toast.error({ title: t('create_folder_error'), body: `Error: ${e}.` });
toast.error({ title: t('create_folder_error'), body: t('error_message', { error: e }) });
console.error(e);
},
onSuccess: (folder) => {
Expand All @@ -80,7 +80,7 @@ export default (props: PropsWithChildren) => {
});
const createEphemeralFile = useLibraryMutation(['ephemeralFiles.createFile'], {
onError: (e) => {
toast.error({ title: t('create_file_error'), body: `${e}.` });
toast.error({ title: t('create_file_error'), body: t('error_message', { error: e }) });
console.error(e);
},
onSuccess: (file) => {
Expand Down Expand Up @@ -220,7 +220,7 @@ export default (props: PropsWithChildren) => {
} catch (error) {
toast.error({
title: t('failed_to_reindex_location'),
body: `Error: ${error}.`
body: t('error_message', { error })
});
}
}}
Expand All @@ -239,7 +239,7 @@ export default (props: PropsWithChildren) => {
} catch (error) {
toast.error({
title: t('failed_to_generate_thumbnails'),
body: `Error: ${error}.`
body: t('error_message', { error })
});
}
}}
Expand All @@ -258,7 +258,7 @@ export default (props: PropsWithChildren) => {
} catch (error) {
toast.error({
title: t('failed_to_generate_labels'),
body: `Error: ${error}.`
body: t('error_message', { error })
});
}
}}
Expand All @@ -276,7 +276,7 @@ export default (props: PropsWithChildren) => {
} catch (error) {
toast.error({
title: t('failed_to_generate_checksum'),
body: `Error: ${error}.`
body: t('error_message', { error })
});
}
}}
Expand Down
11 changes: 7 additions & 4 deletions interface/app/$libraryId/Explorer/QuickPreview/index.tsx
Expand Up @@ -233,8 +233,8 @@ export const QuickPreview = () => {
}
} catch (error) {
toast.error({
title: 'Failed to open file',
body: `Couldn't open file, due to an error: ${error}`
title: t('failed_to_open_file_title'),
body: t('failed_to_open_file_body', { error: error })
});
}
});
Expand Down Expand Up @@ -408,8 +408,11 @@ export const QuickPreview = () => {
setNewName(newName);
} catch (e) {
toast.error({
title: `Could not rename ${itemData.fullName} to ${newName}`,
body: `Error: ${e}.`
title: t('failed_to_rename_file', {
oldName: itemData.fullName,
newName
}),
body: t('error_message', { error: e })
});
}
}}
Expand Down
2 changes: 1 addition & 1 deletion interface/app/$libraryId/Explorer/TopBarOptions.tsx
Expand Up @@ -131,7 +131,7 @@ export const useExplorerTopBarOptions = () => {
// ),
// // TODO: Assign tag mode is not yet implemented!
// // onClick: () => (explorerStore.tagAssignMode = !explorerStore.tagAssignMode),
// onClick: () => toast.info('Coming soon!'),
// onClick: () => toast.info(t('coming_soon)),
// topBarActive: tagAssignMode,
// individual: true,
// showAtResolution: 'xl:flex'
Expand Down
4 changes: 2 additions & 2 deletions interface/app/$libraryId/Explorer/View/ListView/useTable.tsx
Expand Up @@ -24,7 +24,7 @@ import { useExplorerContext } from '../../Context';
import { FileThumb } from '../../FilePath/Thumb';
import { InfoPill } from '../../Inspector';
import { CutCopyState, explorerStore, isCut } from '../../store';
import { uniqueId } from '../../util';
import { translateKindName, uniqueId } from '../../util';
import { RenamableItemText } from '../RenamableItemText';

export const LIST_VIEW_ICON_SIZES = {
Expand Down Expand Up @@ -84,7 +84,7 @@ const KindCell = ({ kind }: { kind: string }) => {
className="bg-app-button/50"
style={{ fontSize: LIST_VIEW_TEXT_SIZES[explorerSettings.listViewTextSize] }}
>
{kind}
{translateKindName(kind)}
</InfoPill>
);
};
Expand Down

0 comments on commit 2d78ede

Please sign in to comment.