diff --git a/interface/ErrorFallback.tsx b/interface/ErrorFallback.tsx index 4fd76d01b17e..237db090cf85 100644 --- a/interface/ErrorFallback.tsx +++ b/interface/ErrorFallback.tsx @@ -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'); @@ -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(() => { @@ -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(); @@ -116,8 +118,8 @@ export function ErrorPage({ } > -

APP CRASHED

-

We're past the event horizon...

+

{t('app_crashed')}

+

{t('app_crashed_description')}

 				{message}
 			
@@ -125,7 +127,7 @@ export function ErrorPage({
{reloadBtn && ( )} {platform.openLogsDir && ( )} @@ -152,19 +154,15 @@ export function ErrorPage({ message.startsWith('failed to initialize library manager')) && (

- We detected you may have created your library with an older version of - Spacedrive. Please reset it to continue using the app! -

-

- {' '} - YOU WILL LOSE ANY EXISTING SPACEDRIVE DATA! + {t('reset_to_continue')}

+

{t('reset_warning')}

)} diff --git a/interface/app/$libraryId/Explorer/ContextMenu/FilePath/Items.tsx b/interface/app/$libraryId/Explorer/ContextMenu/FilePath/Items.tsx index 016d66463dae..497c1d381ae0 100644 --- a/interface/app/$libraryId/Explorer/ContextMenu/FilePath/Items.tsx +++ b/interface/app/$libraryId/Explorer/ContextMenu/FilePath/Items.tsx @@ -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 }) }); } }} diff --git a/interface/app/$libraryId/Explorer/ContextMenu/Object/Items.tsx b/interface/app/$libraryId/Explorer/ContextMenu/Object/Items.tsx index a084357ea405..502b806a1cd5 100644 --- a/interface/app/$libraryId/Explorer/ContextMenu/Object/Items.tsx +++ b/interface/app/$libraryId/Explorer/ContextMenu/Object/Items.tsx @@ -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 }) }); } }} diff --git a/interface/app/$libraryId/Explorer/ContextMenu/OpenWith.tsx b/interface/app/$libraryId/Explorer/ContextMenu/OpenWith.tsx index 220557a3338f..2a3f9462123b 100644 --- a/interface/app/$libraryId/Explorer/ContextMenu/OpenWith.tsx +++ b/interface/app/$libraryId/Explorer/ContextMenu/OpenWith.tsx @@ -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( ['openWith', ids, paths], @@ -109,7 +110,7 @@ const Items = ({ ); } } catch (e) { - toast.error(`Failed to open file, with: ${data.url}`); + toast.error(t('failed_to_open_file_with', { data: data.url })); } }} > @@ -117,7 +118,7 @@ const Items = ({ )) ) : ( -

No apps available

+

{t('no_apps_available')}

)} ); diff --git a/interface/app/$libraryId/Explorer/CopyAsPath.tsx b/interface/app/$libraryId/Explorer/CopyAsPath.tsx index ab8c2d193eec..9b15b6e08d9c 100644 --- a/interface/app/$libraryId/Explorer/CopyAsPath.tsx +++ b/interface/app/$libraryId/Explorer/CopyAsPath.tsx @@ -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 }) }); } }} diff --git a/interface/app/$libraryId/Explorer/DismissibleNotice.tsx b/interface/app/$libraryId/Explorer/DismissibleNotice.tsx index eab622efdadd..7e93accfac3e 100644 --- a/interface/app/$libraryId/Explorer/DismissibleNotice.tsx +++ b/interface/app/$libraryId/Explorer/DismissibleNotice.tsx @@ -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: } diff --git a/interface/app/$libraryId/Explorer/FilePath/DeleteDialog.tsx b/interface/app/$libraryId/Explorer/FilePath/DeleteDialog.tsx index dc3425a01e11..910965bc255d 100644 --- a/interface/app/$libraryId/Explorer/FilePath/DeleteDialog.tsx +++ b/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'; @@ -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) { @@ -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) => { @@ -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 ( { })} icon={} 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]" > diff --git a/interface/app/$libraryId/Explorer/Inspector/Note.tsx b/interface/app/$libraryId/Explorer/Inspector/Note.tsx index 4ab35e0c0d9e..bd440441c3b0 100644 --- a/interface/app/$libraryId/Explorer/Inspector/Note.tsx +++ b/interface/app/$libraryId/Explorer/Inspector/Note.tsx @@ -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'; @@ -27,12 +28,13 @@ export default function Note(props: Props) { useEffect(() => () => flush.current?.(), []); const [cachedNote, setCachedNote] = useState(props.data.note); + const { t } = useLocale(); return ( <> - Note + {t('note')}