Added date formatting according to chosen language in the settings (#2414)

* added date formatting according to chosen language

* deleted spaces

* deleted spaces

* fixed typos

* set date formats after

* error handling

---------

Co-authored-by: Utku Bakir <74243531+utkubakir@users.noreply.github.com>
This commit is contained in:
Artsiom Voitas 2024-04-30 19:52:20 +03:00 committed by GitHub
parent 25eb77165c
commit dee3ca0524
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 694 additions and 38 deletions

View file

@ -70,10 +70,9 @@ export const INSPECTOR_WIDTH = 260;
type MetadataDate = Date | { from: Date; to: Date } | null;
const DATE_FORMAT = 'D MMM YYYY';
const formatDate = (date: MetadataDate | string | undefined) => {
const formatDate = (date: MetadataDate | string | undefined, dateFormat: string) => {
if (!date) return;
if (date instanceof Date || typeof date === 'string') return dayjs(date).format(DATE_FORMAT);
if (date instanceof Date || typeof date === 'string') return dayjs(date).format(dateFormat);
const { from, to } = date;
@ -82,7 +81,7 @@ const formatDate = (date: MetadataDate | string | undefined) => {
const format = ['D', !sameMonth && 'MMM', !sameYear && 'YYYY'].filter(Boolean).join(' ');
return `${dayjs(from).format(format)} - ${dayjs(to).format(DATE_FORMAT)}`;
return `${dayjs(from).format(format)} - ${dayjs(to).format(dateFormat)}`;
};
interface Props extends HTMLAttributes<HTMLDivElement> {
@ -175,7 +174,7 @@ export const SingleItemMetadata = ({ item }: { item: ExplorerItem }) => {
let filePathData: FilePath | FilePathWithObject | null = null;
let ephemeralPathData: NonIndexedPathItem | null = null;
const { t } = useLocale();
const { t, dateFormat } = useLocale();
const result = useLibraryQuery(['locations.list']);
const locations = result.data || [];
@ -308,19 +307,31 @@ export const SingleItemMetadata = ({ item }: { item: ExplorerItem }) => {
value={!!ephemeralPathData && ephemeralPathData.is_dir ? null : `${size}`}
/>
<MetaData icon={Clock} label={t('created')} value={formatDate(dateCreated)} />
<MetaData
icon={Clock}
label={t('created')}
value={formatDate(dateCreated, dateFormat)}
/>
<MetaData icon={Eraser} label={t('modified')} value={formatDate(dateModified)} />
<MetaData
icon={Eraser}
label={t('modified')}
value={formatDate(dateModified, dateFormat)}
/>
{ephemeralPathData != null || (
<MetaData icon={Barcode} label={t('indexed')} value={formatDate(dateIndexed)} />
<MetaData
icon={Barcode}
label={t('indexed')}
value={formatDate(dateIndexed, dateFormat)}
/>
)}
{ephemeralPathData != null || (
<MetaData
icon={FolderOpen}
label={t('accessed')}
value={formatDate(dateAccessed)}
value={formatDate(dateAccessed, dateFormat)}
/>
)}
@ -507,7 +518,7 @@ const MultiItemMetadata = ({ items }: { items: ExplorerItem[] }) => {
[items, getDate]
);
const { t } = useLocale();
const { t, dateFormat } = useLocale();
const onlyNonIndexed = metadata.types.has('NonIndexedPath') && metadata.types.size === 1;
@ -519,24 +530,28 @@ const MultiItemMetadata = ({ items }: { items: ExplorerItem[] }) => {
label={t('size')}
value={metadata.size !== null ? `${byteSize(metadata.size)}` : null}
/>
<MetaData icon={Clock} label={t('created')} value={formatDate(metadata.created)} />
<MetaData
icon={Clock}
label={t('created')}
value={formatDate(metadata.created, dateFormat)}
/>
<MetaData
icon={Eraser}
label={t('modified')}
value={formatDate(metadata.modified)}
value={formatDate(metadata.modified, dateFormat)}
/>
{onlyNonIndexed || (
<MetaData
icon={Barcode}
label={t('indexed')}
value={formatDate(metadata.indexed)}
value={formatDate(metadata.indexed, dateFormat)}
/>
)}
{onlyNonIndexed || (
<MetaData
icon={FolderOpen}
label={t('accessed')}
value={formatDate(metadata.accessed)}
value={formatDate(metadata.accessed, dateFormat)}
/>
)}
</MetaContainer>

View file

@ -95,7 +95,7 @@ export const useTable = () => {
const explorer = useExplorerContext();
const explorerSettings = explorer.useSettingsSnapshot();
const { t } = useLocale();
const { t, dateFormat } = useLocale();
const columns = useMemo<ColumnDef<ExplorerItem>[]>(
() => [
@ -130,7 +130,7 @@ export const useTable = () => {
header: t('date_created'),
accessorFn: (item) => {
if (item.type === 'SpacedropPeer') return;
return dayjs(item.item.date_created).format('MMM Do YYYY');
return dayjs(item.item.date_created).format(dateFormat);
}
},
{
@ -138,7 +138,7 @@ export const useTable = () => {
header: t('date_modified'),
accessorFn: (item) => {
const filePath = getItemFilePath(item);
if (filePath) return dayjs(filePath.date_modified).format('MMM Do YYYY');
if (filePath) return dayjs(filePath.date_modified).format(dateFormat);
}
},
{
@ -146,7 +146,7 @@ export const useTable = () => {
header: t('date_indexed'),
accessorFn: (item) => {
const filePath = getIndexedItemFilePath(item);
if (filePath) return dayjs(filePath.date_indexed).format('MMM Do YYYY');
if (filePath) return dayjs(filePath.date_indexed).format(dateFormat);
}
},
{
@ -155,7 +155,7 @@ export const useTable = () => {
accessorFn: (item) => {
const object = getItemObject(item);
if (!object || !object.date_accessed) return;
return dayjs(object.date_accessed).format('MMM Do YYYY');
return dayjs(object.date_accessed).format(dateFormat);
}
},
{

View file

@ -1,6 +1,7 @@
import { LoadMoreTrigger, useGrid, useScrollMargin, useVirtualizer } from '@virtual-grid/react';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { getOrderingDirection, OrderingKey, orderingKey } from '@sd/client';
import { useLocale } from '~/hooks';
import { useExplorerContext } from '../../Context';
import { getItemData, getItemId, uniqueId } from '../../util';
@ -30,6 +31,8 @@ export const MediaView = () => {
const orderBy = explorerSettings.order && orderingKey(explorerSettings.order);
const orderDirection = explorerSettings.order && getOrderingDirection(explorerSettings.order);
const { dateFormat } = useLocale();
const isSortingByDate = orderBy && SORT_BY_DATE[orderBy];
const grid = useGrid({
@ -142,19 +145,22 @@ export const MediaView = () => {
? new Date(new Date(lastFilePathDate).setHours(0, 0, 0, 0))
: undefined;
if (firstDate && !lastDate) return formatDate(firstDate);
if (firstDate && !lastDate) return formatDate(firstDate, dateFormat);
if (!firstDate && lastDate) return formatDate(lastDate);
if (!firstDate && lastDate) return formatDate(lastDate, dateFormat);
if (firstDate && lastDate) {
if (firstDate.getTime() === lastDate.getTime()) {
return formatDate(firstDate);
return formatDate(firstDate, dateFormat);
}
return formatDate({
from: orderDirection === 'Asc' ? firstDate : lastDate,
to: orderDirection === 'Asc' ? lastDate : firstDate
});
return formatDate(
{
from: orderDirection === 'Asc' ? firstDate : lastDate,
to: orderDirection === 'Asc' ? lastDate : firstDate
},
dateFormat
);
}
}, [
explorer.items,

View file

@ -1,10 +1,8 @@
import dayjs from 'dayjs';
import { ExplorerItem, getExplorerItemData, OrderingKey } from '@sd/client';
const DATE_FORMAT = 'D MMM YYYY';
export const formatDate = (date: Date | { from: Date; to: Date }) => {
if (date instanceof Date) return dayjs(date).format(DATE_FORMAT);
export const formatDate = (date: Date | { from: Date; to: Date }, dateFormat: string) => {
if (date instanceof Date) return dayjs(date).format(dateFormat);
const sameMonth = date.from.getMonth() === date.to.getMonth();
const sameYear = date.from.getFullYear() === date.to.getFullYear();
@ -13,7 +11,7 @@ export const formatDate = (date: Date | { from: Date; to: Date }) => {
.filter(Boolean)
.join(' ');
return `${dayjs(date.from).format(fromDateFormat)} - ${dayjs(date.to).format(DATE_FORMAT)}`;
return `${dayjs(date.from).format(fromDateFormat)} - ${dayjs(date.to).format(dateFormat)}`;
};
export function getDate(item: ExplorerItem, orderBy: OrderingKey) {

View file

@ -1,3 +1,4 @@
import dayjs from 'dayjs';
import { type ExplorerItem } from '@sd/client';
import { ExplorerParamsSchema } from '~/app/route-schemas';
import { useZodSearchParams } from '~/hooks';
@ -33,3 +34,69 @@ export function getItemId(index: number, items: ExplorerItem[]) {
export function getItemData(index: number, items: ExplorerItem[]) {
return items[index];
}
const dayjsLocales: Record<string, any> = {
en: () => import('dayjs/locale/en.js'),
en_gb: () => import('dayjs/locale/en-gb.js'),
de: () => import('dayjs/locale/de.js'),
es: () => import('dayjs/locale/es.js'),
fr: () => import('dayjs/locale/fr.js'),
tr: () => import('dayjs/locale/tr.js'),
nl: () => import('dayjs/locale/nl.js'),
be: () => import('dayjs/locale/be.js'),
ru: () => import('dayjs/locale/ru.js'),
zh_CN: () => import('dayjs/locale/zh-cn.js'),
zh_TW: () => import('dayjs/locale/zh-tw.js'),
it: () => import('dayjs/locale/it.js'),
ja: () => import('dayjs/locale/ja.js')
};
export function loadDayjsLocale(language: string) {
if (dayjsLocales[language]) {
dayjsLocales[language]()
.then(() => {
language = language.replace('_', '-');
dayjs.locale(language);
})
.catch((error: any) => {
console.error(`Failed to load ${language} locale:`, error);
// Optionally set a default locale here
dayjs.locale('en');
});
} else {
console.warn(`Locale for ${language} not available, falling back to default.`);
dayjs.locale('en');
}
}
// Generate list of localized formats available in the app
export function generateLocaleDateFormats(language: string) {
language = language.replace('_', '-');
const DATE_FORMATS = [
{
value: 'L',
label: dayjs().locale(language).format('L')
},
{
value: 'll',
label: dayjs().locale(language).format('ll')
},
{
value: 'LL',
label: dayjs().locale(language).format('LL')
},
{
value: 'lll',
label: dayjs().locale(language).format('lll')
},
{
value: 'LLL',
label: dayjs().locale(language).format('LLL')
},
{
value: 'llll',
label: dayjs().locale(language).format('llll')
}
];
return DATE_FORMATS;
}

View file

@ -1,5 +1,7 @@
import clsx from 'clsx';
import { Controller, FormProvider } from 'react-hook-form';
import dayjs from 'dayjs';
import { useState } from 'react';
import { FormProvider } from 'react-hook-form';
import {
useBridgeMutation,
useBridgeQuery,
@ -8,12 +10,13 @@ import {
useFeatureFlag,
useZodForm
} from '@sd/client';
import { Button, Card, Input, Select, SelectOption, Slider, Switch, toast, tw, z } from '@sd/ui';
import { Button, Card, Input, Select, SelectOption, Slider, Switch, tw, z } from '@sd/ui';
import i18n from '~/app/I18n';
import { Icon } from '~/components';
import { useDebouncedFormWatch, useLocale } from '~/hooks';
import { usePlatform } from '~/util/Platform';
import { generateLocaleDateFormats } from '../../Explorer/util';
import { Heading } from '../Layout';
import Setting from '../Setting';
@ -22,7 +25,8 @@ const NodeSettingLabel = tw.div`mb-1 text-xs font-medium`;
// Unsorted list of languages available in the app.
const LANGUAGE_OPTIONS = [
{ value: 'en', label: 'English' },
{ value: 'en', label: 'English (US)' },
{ value: 'en_gb', label: 'English (UK)' },
{ value: 'de', label: 'Deutsch' },
{ value: 'es', label: 'Español' },
{ value: 'fr', label: 'Français' },
@ -50,6 +54,10 @@ export const Component = () => {
// const image_labeler_versions = useBridgeQuery(['models.image_detection.list']);
const updateThumbnailerPreferences = useBridgeMutation('nodes.updateThumbnailerPreferences');
const [dateFormats, setDateFormats] = useState(
generateLocaleDateFormats(i18n.resolvedLanguage || i18n.language || 'en')
);
const form = useZodForm({
schema: z
.object({
@ -124,7 +132,7 @@ export const Component = () => {
}
});
const { t } = useLocale();
const { t, dateFormat, setDateFormat } = useLocale();
const isP2PWipFeatureEnabled = useFeatureFlag('wipP2P');
@ -231,6 +239,8 @@ export const Component = () => {
// add "i18nextLng" key to localStorage and set it to the selected language
localStorage.setItem('i18nextLng', e);
i18n.changeLanguage(e);
setDateFormats(generateLocaleDateFormats(e));
}}
containerClassName="h-[30px] whitespace-nowrap"
>
@ -242,6 +252,26 @@ export const Component = () => {
</Select>
</div>
</Setting>
{/* Date Formatting Settings */}
<Setting mini title={t('date_format')} description={t('date_format_description')}>
<div className="flex h-[30px] gap-2">
<Select
value={dateFormat}
onChange={(e) => {
// add "dateFormat" key to localStorage and set it as default date format
localStorage.setItem('sd-date-format', e);
setDateFormat(e);
}}
containerClassName="h-[30px] whitespace-nowrap"
>
{dateFormats.map((format, key) => (
<SelectOption key={key} value={format.value}>
{format.label}
</SelectOption>
))}
</Select>
</div>
</Setting>
{/* Debug Mode */}
<Setting mini title={t('debug_mode')} description={t('debug_mode_description')}>
<Switch

View file

@ -1,12 +1,22 @@
import dayjs from 'dayjs';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { loadDayjsLocale } from '~/app/$libraryId/Explorer/util';
dayjs.extend(localizedFormat);
export const useLocale = (namespace: Parameters<typeof useTranslation>[0] = 'translation') => {
const { i18n, t } = useTranslation(namespace);
const isLocaleReady = Object.keys(i18n).length > 0;
loadDayjsLocale(i18n.resolvedLanguage || i18n.language || 'en');
const [dateFormat, setDateFormat] = useState(localStorage.getItem('sd-date-format') || 'LL');
return {
i18n,
t,
isLocaleReady
isLocaleReady,
dateFormat,
setDateFormat
};
};

View file

@ -87,6 +87,8 @@
"cut_object": "Выразаць аб'ект",
"cut_success": "Элементы выразаны",
"data_folder": "Папка з дадзенымі",
"date_format": "Фармат даты",
"date_format_description": "Змяніць фармат даты, які адлюстроўваецца ў Spacedrive",
"date_accessed": "Дата доступу",
"date_created": "Дата стварэння",
"date_indexed": "Дата індэксавання",
@ -461,7 +463,7 @@
"tags_description": "Кіруйце сваімі тэгамі.",
"tags_notice_message": "Гэтаму тэгу не прысвоена ні аднаго элемента.",
"telemetry_description": "Уключыце, каб падаць распрацоўнікам дэталёвыя дадзеныя пра выкарыстанне і тэлеметрыю для паляпшэння дадатку. Выключыце, каб адпраўляць толькі асноўныя дадзеныя: статус актыўнасці, версію дадатку, версію ядра і платформу (прыкладам, мабільную, ўэб- ці настольную).",
"telemetry_title": "Падаванне дадатковай телеметриии і дадзеных пра выкарыстанне",
"telemetry_title": "Падаванне дадатковай тэлеметрыi і дадзеных пра выкарыстанне",
"temperature": "Тэмпература",
"text_file": "Тэкставы файл",
"text_size": "Памер тэксту",

View file

@ -87,6 +87,8 @@
"cut_object": "Objekt ausschneiden",
"cut_success": "Elemente ausschneiden",
"data_folder": "Datenordner",
"date_format": "Datumsformat",
"date_format_description": "Wählen Sie das in Spacedrive angezeigte Datumsformat",
"date_accessed": "Datum zugegriffen",
"date_created": "Datum erstellt",
"date_indexed": "Datum der Indexierung",

View file

@ -0,0 +1,506 @@
{
"about": "About",
"about_vision_text": "Many of us have multiple cloud accounts, drives that arent backed up and data at risk of loss. We depend on cloud services like Google Photos and iCloud, but are locked in with limited capacity and almost zero interoperability between services and operating systems. Photo albums shouldnt be stuck in a device ecosystem, or harvested for advertising data. They should be OS agnostic, permanent and personally owned. Data we create is our legacy, that will long outlive us—open source technology is the only way to ensure we retain absolute control over the data that defines our lives, at unlimited scale.",
"about_vision_title": "Vision",
"accept": "Accept",
"accessed": "Accessed",
"account": "Account",
"actions": "Actions",
"add": "Add",
"add_device": "Add Device",
"add_library": "Add Library",
"add_location": "Add Location",
"add_location_description": "Enhance your Spacedrive experience by adding your favorite locations to your personal library, for seamless and efficient file management.",
"add_location_tooltip": "Add path as an indexed location",
"add_locations": "Add Locations",
"add_tag": "Add Tag",
"advanced_settings": "Advanced settings",
"all_jobs_have_been_cleared": "All jobs have been cleared.",
"alpha_release_description": "We are delighted for you to try Spacedrive, now in Alpha release, showcasing exciting new features. As with any initial release, this version may contain some bugs. We kindly request your assistance in reporting any issues you encounter on our Discord channel. Your valuable feedback will greatly contribute to enhancing the user experience.",
"alpha_release_title": "Alpha Release",
"appearance": "Appearance",
"appearance_description": "Change the look of your client.",
"archive": "Archive",
"archive_coming_soon": "Archiving locations is coming soon...",
"archive_info": "Extract data from Library as an archive, useful to preserve Location folder structure.",
"are_you_sure": "Are you sure?",
"ask_spacedrive": "Ask Spacedrive",
"assign_tag": "Assign tag",
"audio_preview_not_supported": "Audio preview is not supported.",
"back": "Back",
"backups": "Backups",
"backups_description": "Manage your Spacedrive database backups.",
"blur_effects": "Blur Effects",
"blur_effects_description": "Some components will have a blur effect applied to them.",
"cancel": "Cancel",
"cancel_selection": "Cancel selection",
"celcius": "Celsius",
"change": "Change",
"change_view_setting_description": "Change the default explorer view",
"changelog": "Changelog",
"changelog_page_description": "See what cool new features we're making",
"changelog_page_title": "Changelog",
"checksum": "Checksum",
"clear_finished_jobs": "Clear out finished jobs",
"client": "Client",
"close": "Close",
"close_command_palette": "Close command palette",
"close_current_tab": "Close current tab",
"clouds": "Clouds",
"color": "Color",
"coming_soon": "Coming soon",
"compress": "Compress",
"configure_location": "Configure Location",
"connected": "Connected",
"contacts": "Contacts",
"contacts_description": "Manage your contacts in Spacedrive.",
"content_id": "Content ID",
"continue": "Continue",
"convert_to": "Convert to",
"coordinates": "Coordinates",
"copied": "Copied",
"copy": "Copy",
"copy_as_path": "Copy as path",
"copy_object": "Copy object",
"copy_path_to_clipboard": "Copy path to clipboard",
"copy_success": "Items copied",
"create": "Create",
"create_file_error": "Error creating file",
"create_file_success": "Created new file: {{name}}",
"create_folder_error": "Error creating folder",
"create_folder_success": "Created new folder: {{name}}",
"create_library": "Create a Library",
"create_library_description": "Libraries are a secure, on-device database. Your files remain where they are, the Library catalogs them and stores all Spacedrive related data.",
"create_new_library": "Create new library",
"create_new_library_description": "Libraries are a secure, on-device database. Your files remain where they are, the Library catalogs them and stores all Spacedrive related data.",
"create_new_tag": "Create New Tag",
"create_new_tag_description": "Choose a name and color.",
"create_tag": "Create Tag",
"created": "Created",
"creating_library": "Creating library...",
"creating_your_library": "Creating your library",
"current": "Current",
"current_directory": "Current Directory",
"current_directory_with_descendants": "Current Directory With Descendants",
"custom": "Custom",
"cut": "Cut",
"cut_object": "Cut object",
"cut_success": "Items cut",
"data_folder": "Data Folder",
"date_format": "Date Format",
"date_format_description": "Choose the date format displayed in Spacedrive",
"date_accessed": "Date Accessed",
"date_created": "Date Created",
"date_indexed": "Date Indexed",
"date_modified": "Date Modified",
"debug_mode": "Debug mode",
"debug_mode_description": "Enable extra debugging features within the app.",
"default": "Default",
"random": "Random",
"ipv6": "IPv6 networking",
"ipv6_description": "Allow peer-to-peer communication using IPv6 networking",
"default_settings": "Default Settings",
"delete": "Delete",
"delete_dialog_title": "Delete {{prefix}} {{type}}",
"delete_forever": "Delete Forever",
"delete_info": "This will not delete the actual folder on disk. Preview media will be deleted.",
"delete_library": "Delete Library",
"delete_library_description": "This is permanent, your files will not be deleted, only the Spacedrive library.",
"delete_location": "Delete Location",
"delete_location_description": "Deleting a location will also remove all files associated with it from the Spacedrive database, the files themselves will not be deleted.",
"delete_object": "Delete object",
"delete_rule": "Delete rule",
"delete_tag": "Delete Tag",
"delete_tag_description": "Are you sure you want to delete this tag? This cannot be undone and tagged files will be unlinked.",
"delete_warning": "This will delete your {{type}}. This action cannot be undone as of right now. If you Move to Trash, you can restore it later. If you Delete Forever, it will be gone forever.",
"description": "Description",
"deselect": "Deselect",
"details": "Details",
"devices": "Devices",
"devices_coming_soon_tooltip": "Coming soon! This alpha release doesn't include library sync, it will be ready very soon.",
"dialog": "Dialog",
"dialog_shortcut_description": "To perform actions and operations",
"direction": "Direction",
"disabled": "Disabled",
"disconnected": "Disconnected",
"display_formats": "Display Formats",
"display_name": "Display Name",
"distance": "Distance",
"done": "Done",
"dont_show_again": "Don't show again",
"double_click_action": "Double click action",
"download": "Download",
"downloading_update": "Downloading Update",
"duplicate": "Duplicate",
"duplicate_object": "Duplicate object",
"duplicate_success": "Items duplicated",
"edit": "Edit",
"edit_library": "Edit Library",
"edit_location": "Edit Location",
"empty_file": "Empty file",
"enable_networking": "Enable Networking",
"enable_networking_description": "Allow your node to communicate with other Spacedrive nodes around you.",
"enable_networking_description_required": "Required for library sync or Spacedrop!",
"spacedrop": "Spacedrop visibility",
"spacedrop_everyone": "Everyone",
"spacedrop_contacts_only": "Contacts Only",
"spacedrop_disabled": "Disabled",
"remote_access": "Enable remote access",
"remote_access_description": "Enable other nodes to directly connect to this node.",
"encrypt": "Encrypt",
"encrypt_library": "Encrypt Library",
"encrypt_library_coming_soon": "Library encryption coming soon",
"encrypt_library_description": "Enable encryption for this library, this will only encrypt the Spacedrive database, not the files themselves.",
"ephemeral_notice_browse": "Browse your files and folders directly from your device.",
"ephemeral_notice_consider_indexing": "Consider indexing your local locations for a faster and more efficient exploration.",
"erase": "Erase",
"erase_a_file": "Erase a file",
"erase_a_file_description": "Configure your erasure settings.",
"error": "Error",
"error_loading_original_file": "Error loading original file",
"expand": "Expand",
"explorer": "Explorer",
"explorer_settings": "Explorer settings",
"explorer_shortcut_description": "To navigate and interact with the file system",
"explorer_view": "Explorer view",
"export": "Export",
"export_library": "Export Library",
"export_library_coming_soon": "Export Library coming soon",
"export_library_description": "Export this library to a file.",
"extensions": "Extensions",
"extensions_description": "Install extensions to extend the functionality of this client.",
"fahrenheit": "Fahrenheit",
"failed_to_cancel_job": "Failed to cancel job.",
"failed_to_clear_all_jobs": "Failed to clear all jobs.",
"failed_to_copy_file": "Failed to copy file",
"failed_to_copy_file_path": "Failed to copy file path",
"failed_to_cut_file": "Failed to cut file",
"failed_to_download_update": "Failed to download update",
"failed_to_duplicate_file": "Failed to duplicate file",
"failed_to_generate_checksum": "Failed to generate checksum",
"failed_to_generate_labels": "Failed to generate labels",
"failed_to_generate_thumbnails": "Failed to generate thumbnails",
"failed_to_load_tags": "Failed to load tags",
"failed_to_pause_job": "Failed to pause job.",
"failed_to_reindex_location": "Failed to re-index location",
"failed_to_remove_file_from_recents": "Failed to remove file from recents",
"failed_to_remove_job": "Failed to remove job.",
"failed_to_rescan_location": "Failed to rescan location",
"failed_to_resume_job": "Failed to resume job.",
"failed_to_update_location_settings": "Failed to update location settings",
"favorite": "Favorite",
"favorites": "Favorites",
"feedback": "Feedback",
"feedback_is_required": "Feedback is required",
"feedback_login_description": "Logging in allows us to respond to your feedback",
"feedback_placeholder": "Your feedback...",
"feedback_toast_error_message": "There was an error submitting your feedback. Please try again.",
"file_already_exist_in_this_location": "File already exists in this location",
"file_indexing_rules": "File indexing rules",
"filters": "Filters",
"forward": "Forward",
"full_disk_access": "Full disk access",
"full_disk_access_description": "To provide the best experience, we need access to your disk in order to index your files. Your files are only available to you.",
"full_reindex": "Full Reindex",
"full_reindex_info": "Perform a full rescan of this Location.",
"general": "General",
"general_settings": "General Settings",
"general_settings_description": "General settings related to this client.",
"general_shortcut_description": "General usage shortcuts",
"generatePreviewMedia_label": "Generate preview media for this Location",
"generate_checksums": "Generate Checksums",
"go_back": "Go Back",
"go_to_labels": "Go to labels",
"go_to_location": "Go to location",
"go_to_overview": "Go to overview",
"go_to_recents": "Go to recents",
"go_to_settings": "Go to settings",
"go_to_tag": "Go to tag",
"got_it": "Got it",
"grid_gap": "Gap",
"grid_view": "Grid View",
"grid_view_notice_description": "Get a visual overview of your files with Grid View. This view displays your files and folders as thumbnail images, making it easy to quickly identify the file you're looking for.",
"hidden_label": "Prevents the location and its contents from appearing in summary categories, search and tags unless \"Show hidden items\" is enabled.",
"hide_in_library_search": "Hide in Library search",
"hide_in_library_search_description": "Hide files with this tag from results when searching entire library.",
"hide_in_sidebar": "Hide in sidebar",
"hide_in_sidebar_description": "Prevent this tag from showing in the sidebar of the app.",
"hide_location_from_view": "Hide location and contents from view",
"home": "Home",
"icon_size": "Icon size",
"image_labeler_ai_model": "Image label recognition AI model",
"image_labeler_ai_model_description": "The model used to recognize objects in images. Larger models are more accurate but slower.",
"import": "Import",
"indexed": "Indexed",
"indexer_rule_reject_allow_label": "By default, an indexer rule functions as a Reject list, resulting in the exclusion of any files that match its criteria. Enabling this option will transform it into a Allow list, allowing the location to solely index files that meet its specified rules.",
"indexer_rules": "Indexer rules",
"indexer_rules_info": "Indexer rules allow you to specify paths to ignore using globs.",
"install": "Install",
"install_update": "Install Update",
"installed": "Installed",
"item_size": "Item size",
"item_with_count_one": "{{count}} item",
"item_with_count_other": "{{count}} items",
"job_has_been_canceled": "Job has been canceled.",
"job_has_been_paused": "Job has been paused.",
"job_has_been_removed": "Job has been removed.",
"job_has_been_resumed": "Job has been resumed.",
"join": "Join",
"join_discord": "Join Discord",
"join_library": "Join a Library",
"join_library_description": "Libraries are a secure, on-device database. Your files remain where they are, the Library catalogs them and stores all Spacedrive related data.",
"key": "Key",
"key_manager": "Key Manager",
"key_manager_description": "Create encryption keys, mount and unmount your keys to see files decrypted on the fly.",
"keybinds": "Keybinds",
"keybinds_description": "View and manage client keybinds",
"keys": "Keys",
"kilometers": "Kilometers",
"labels": "Labels",
"language": "Language",
"language_description": "Change the language of the Spacedrive interface",
"learn_more_about_telemetry": "Learn more about telemetry",
"libraries": "Libraries",
"libraries_description": "The database contains all library data and file metadata.",
"library": "Library",
"library_name": "Library name",
"library_overview": "Library Overview",
"library_settings": "Library Settings",
"library_settings_description": "General settings related to the currently active library.",
"list_view": "List View",
"list_view_notice_description": "Easily navigate through your files and folders with List View. This view displays your files in a simple, organized list format, allowing you to quickly locate and access the files you need.",
"loading": "Loading",
"local": "Local",
"local_locations": "Local Locations",
"local_node": "Local Node",
"location_connected_tooltip": "Location is being watched for changes",
"location_disconnected_tooltip": "Location is not being watched for changes",
"location_display_name_info": "The name of this Location, this is what will be displayed in the sidebar. Will not rename the actual folder on disk.",
"location_empty_notice_message": "No files found here",
"location_is_already_linked": "Location is already linked",
"location_path_info": "The path to this Location, this is where the files will be stored on disk.",
"location_type": "Location Type",
"location_type_managed": "Spacedrive will sort files for you. If Location isn't empty a \"spacedrive\" folder will be created.",
"location_type_normal": "Contents will be indexed as-is, new files will not be automatically sorted.",
"location_type_replica": "This Location is a replica of another, its contents will be automatically synchronized.",
"locations": "Locations",
"locations_description": "Manage your storage locations.",
"lock": "Lock",
"log_in": "Log in",
"log_in_with_browser": "Log in with browser",
"log_out": "Log out",
"logged_in_as": "Logged in as {{email}}",
"logging_in": "Logging in...",
"logout": "Logout",
"manage_library": "Manage Library",
"managed": "Managed",
"media": "Media",
"media_view": "Media View",
"media_view_context": "Media View Context",
"media_view_notice_description": "Discover photos and videos easily, Media View will show results starting at the current location including sub directories.",
"meet_contributors_behind_spacedrive": "Meet the contributors behind Spacedrive",
"meet_title": "Meet {{title}}",
"miles": "Miles",
"mode": "Mode",
"modified": "Modified",
"more": "More",
"more_actions": "More actions...",
"more_info": "More info",
"move_back_within_quick_preview": "Move back within quick preview",
"move_files": "Move Files",
"move_forward_within_quick_preview": "Move forward within quick preview",
"move_to_trash": "Move to Trash",
"name": "Name",
"navigate_back": "Navigate back",
"navigate_backwards": "Navigate backwards",
"navigate_files_downwards": "Navigate files downwards",
"navigate_files_leftwards": "Navigate files leftwards",
"navigate_files_rightwards": "Navigate files rightwards",
"navigate_files_upwards": "Navigate files upwards",
"navigate_forward": "Navigate forward",
"navigate_forwards": "Navigate forwards",
"navigate_to_settings_page": "Navigate to Settings page",
"network": "Network",
"network_page_description": "Other Spacedrive nodes on your LAN will appear here, along with your default OS network mounts.",
"networking": "Networking",
"networking_port": "Networking Port",
"networking_port_description": "The port for Spacedrive's Peer-to-peer networking to communicate on. You should leave this disabled unless you have a restrictive firewall. Do not expose to the internet!",
"new": "New",
"new_folder": "Folder",
"new_library": "New library",
"new_location": "New location",
"new_location_web_description": "As you are using the browser version of Spacedrive you will (for now) need to specify an absolute URL of a directory local to the remote node.",
"new_tab": "New Tab",
"new_tag": "New tag",
"new_update_available": "New Update Available!",
"no_favorite_items": "No favorite items",
"no_items_found": "No items found",
"no_jobs": "No jobs.",
"no_labels": "No labels",
"no_nodes_found": "No Spacedrive nodes were found.",
"no_tag_selected": "No Tag Selected",
"no_tags": "No tags",
"node_name": "Node Name",
"nodes": "Nodes",
"nodes_description": "Manage the nodes connected to this library. A node is an instance of Spacedrive's backend, running on a device or server. Each node carries a copy of the database and synchronizes via peer-to-peer connections in realtime.",
"none": "None",
"normal": "Normal",
"not_you": "Not you?",
"number_of_passes": "# of passes",
"object_id": "Object ID",
"offline": "Offline",
"online": "Online",
"open": "Open",
"open_file": "Open File",
"open_in_new_tab": "Open in new tab",
"open_new_location_once_added": "Open new location once added",
"open_new_tab": "Open new tab",
"open_object": "Open object",
"open_object_from_quick_preview_in_native_file_manager": "Open object from quick preview in native file manager",
"open_settings": "Open Settings",
"open_with": "Open with",
"or": "OR",
"overview": "Overview",
"page": "Page",
"page_shortcut_description": "Different pages in the app",
"pair": "Pair",
"pairing_with_node": "Pairing with {{node}}",
"paste": "Paste",
"paste_object": "Paste object",
"paste_success": "Items pasted",
"path": "Path",
"path_copied_to_clipboard_description": "Path for location {{location}} copied to clipboard.",
"path_copied_to_clipboard_title": "Path copied to clipboard",
"pause": "Pause",
"peers": "Peers",
"people": "People",
"pin": "Pin",
"privacy": "Privacy",
"privacy_description": "Spacedrive is built for privacy, that's why we're open source and local first. So we'll make it very clear what data is shared with us.",
"quick_preview": "Quick Preview",
"quick_view": "Quick view",
"recent_jobs": "Recent Jobs",
"recents": "Recents",
"recents_notice_message": "Recents are created when you open a file.",
"regen_labels": "Regen Labels",
"regen_thumbnails": "Regen Thumbnails",
"regenerate_thumbs": "Regenerate Thumbs",
"reindex": "Re-index",
"reject": "Reject",
"reload": "Reload",
"remove": "Remove",
"remove_from_recents": "Remove From Recents",
"rename": "Rename",
"rename_object": "Rename object",
"replica": "Replica",
"rescan": "Rescan",
"rescan_directory": "Rescan Directory",
"rescan_location": "Rescan Location",
"reset": "Reset",
"resources": "Resources",
"restore": "Restore",
"resume": "Resume",
"retry": "Retry",
"reveal_in_native_file_manager": "Reveal in native file manager",
"revel_in_browser": "Reveal in {{browser}}",
"running": "Running",
"save": "Save",
"save_changes": "Save Changes",
"saved_searches": "Saved Searches",
"search": "Search",
"search_extensions": "Search extensions",
"search_for_files_and_actions": "Search for files and actions...",
"secure_delete": "Secure delete",
"security": "Security",
"security_description": "Keep your client safe.",
"send": "Send",
"settings": "Settings",
"setup": "Set up",
"share": "Share",
"share_anonymous_usage": "Share anonymous usage",
"share_anonymous_usage_description": "Share completely anonymous telemetry data to help the developers improve the app",
"share_bare_minimum": "Share the bare minimum",
"share_bare_minimum_description": "Only share that I am an active user of Spacedrive and a few technical bits",
"sharing": "Sharing",
"sharing_description": "Manage who has access to your libraries.",
"show_details": "Show details",
"show_hidden_files": "Show Hidden Files",
"show_inspector": "Show Inspector",
"show_object_size": "Show Object size",
"show_path_bar": "Show Path Bar",
"show_slider": "Show slider",
"size": "Size",
"size_b": "B",
"size_gb": "GB",
"size_kb": "kB",
"size_mb": "MB",
"size_tb": "TB",
"skip_login": "Skip login",
"sort_by": "Sort by",
"spacedrive_account": "Spacedrive Account",
"spacedrive_cloud": "Spacedrive Cloud",
"spacedrive_cloud_description": "Spacedrive is always local first, but we will offer our own optional cloud services in the future. For now, authentication is only used for the Feedback feature, otherwise it is not required.",
"spacedrop_a_file": "Spacedrop a File",
"spacedrop_already_progress": "Spacedrop already in progress",
"spacedrop_description": "Share instantly with devices running Spacedrive on your network.",
"spacedrop_rejected": "Spacedrop rejected",
"square_thumbnails": "Square Thumbnails",
"star_on_github": "Star on GitHub",
"stop": "Stop",
"success": "Success",
"support": "Support",
"switch_to_grid_view": "Switch to grid view",
"switch_to_list_view": "Switch to list view",
"switch_to_media_view": "Switch to media view",
"switch_to_next_tab": "Switch to next tab",
"switch_to_previous_tab": "Switch to previous tab",
"sync": "Sync",
"syncPreviewMedia_label": "Sync preview media for this Location with your devices",
"sync_description": "Manage how Spacedrive syncs.",
"sync_with_library": "Sync with Library",
"sync_with_library_description": "If enabled, your keybinds will be synced with library, otherwise they will apply only to this client.",
"tags": "Tags",
"tags_description": "Manage your tags.",
"tags_notice_message": "No items assigned to this tag.",
"telemetry_description": "Toggle ON to provide developers with detailed usage and telemetry data to enhance the app. Toggle OFF to send only basic data: your activity status, app version, core version, and platform (e.g., mobile, web, or desktop).",
"telemetry_title": "Share Additional Telemetry and Usage Data",
"temperature": "Temperature",
"text_file": "Text File",
"text_size": "Text size",
"thank_you_for_your_feedback": "Thanks for your feedback!",
"thumbnailer_cpu_usage": "Thumbnailer CPU usage",
"thumbnailer_cpu_usage_description": "Limit how much CPU the thumbnailer can use for background processing.",
"toggle_all": "Toggle All",
"toggle_command_palette": "Toggle command palette",
"toggle_hidden_files": "Toggle hidden files",
"toggle_image_slider_within_quick_preview": "Toggle image slider within quick preview",
"toggle_inspector": "Toggle inspector",
"toggle_job_manager": "Toggle job manager",
"toggle_metadata": "Toggle metadata",
"toggle_path_bar": "Toggle path bar",
"toggle_quick_preview": "Toggle quick preview",
"tools": "Tools",
"trash": "Trash",
"type": "Type",
"ui_animations": "UI Animations",
"ui_animations_description": "Dialogs and other UI elements will animate when opening and closing.",
"unnamed_location": "Unnamed Location",
"update": "Update",
"update_downloaded": "Update Downloaded. Restart Spacedrive to install",
"updated_successfully": "Updated successfully, you're on version {{version}}",
"usage": "Usage",
"usage_description": "Your library usage and hardware information",
"vaccum": "Vaccum",
"vaccum_library": "Vaccum Library",
"vaccum_library_description": "Repack your database to free up unnecessary space.",
"value": "Value",
"version": "Version {{version}}",
"video_preview_not_supported": "Video preview is not supported.",
"view_changes": "View Changes",
"want_to_do_this_later": "Want to do this later?",
"website": "Website",
"your_account": "Your account",
"your_account_description": "Spacedrive account and information.",
"your_local_network": "Your Local Network",
"your_privacy": "Your Privacy"
}

View file

@ -87,6 +87,8 @@
"cut_object": "Cut object",
"cut_success": "Items cut",
"data_folder": "Data Folder",
"date_format": "Date Format",
"date_format_description": "Choose the date format displayed in Spacedrive",
"date_accessed": "Date Accessed",
"date_created": "Date Created",
"date_indexed": "Date Indexed",

View file

@ -87,6 +87,8 @@
"cut_object": "Cortar objeto",
"cut_success": "Elementos cortados",
"data_folder": "Carpeta de datos",
"date_format": "Formato de fecha",
"date_format_description": "Elija el formato de fecha que se muestra en Spacedrive",
"date_accessed": "Fecha accesada",
"date_created": "fecha de creacion",
"date_indexed": "Fecha indexada",

View file

@ -87,6 +87,8 @@
"cut_object": "Couper l'objet",
"cut_success": "Éléments coupés",
"data_folder": "Dossier de données",
"date_format": "Format de date",
"date_format_description": "Choisissez le format de date affiché dans Spacedrive",
"date_accessed": "Date d'accès",
"date_created": "date créée",
"date_indexed": "Date d'indexation",

View file

@ -87,6 +87,8 @@
"cut_object": "Taglia oggetto",
"cut_success": "Articoli tagliati",
"data_folder": "Cartella dati",
"date_format": "Formato data",
"date_format_description": "Scegli il formato della data visualizzato in Spacedrive",
"date_accessed": "Data di accesso",
"date_created": "data di creazione",
"date_indexed": "Data indicizzata",

View file

@ -87,6 +87,8 @@
"cut_object": "オブジェクトを切り取り",
"cut_success": "アイテムを切り取りました",
"data_folder": "データフォルダー",
"date_format": "日付形式",
"date_format_description": "Spacedrive に表示される日付形式を選択します",
"date_accessed": "アクセス日時",
"date_created": "作成日時",
"date_indexed": "インデックス化日時",

View file

@ -87,6 +87,8 @@
"cut_object": "Object knippen",
"cut_success": "Items knippen",
"data_folder": "Gegevens Map",
"date_format": "Datumnotatie",
"date_format_description": "Kies het datumformaat dat wordt weergegeven in Spacedrive",
"date_accessed": "Datum geopend",
"date_created": "Datum gecreeërd",
"date_indexed": "Datum geïndexeerd",

View file

@ -87,6 +87,8 @@
"cut_object": "Вырезать объект",
"cut_success": "Элементы вырезаны",
"data_folder": "Папка с данными",
"date_format": "Формат даты",
"date_format_description": "Изменить формат даты, отображаемый в Spacedrive",
"date_accessed": "Дата доступа",
"date_created": "Дата создания",
"date_indexed": "Дата индексации",
@ -461,7 +463,7 @@
"tags_description": "Управляйте своими тегами.",
"tags_notice_message": "Этому тегу не присвоено ни одного элемента.",
"telemetry_description": "Включите, чтобы предоставить разработчикам подробные данные об использовании и телеметрии для улучшения приложения. Выключите, чтобы отправлять только основные данные: статус активности, версию приложения, версию ядра и платформу (например, мобильную, веб- или настольную).",
"telemetry_title": "Предоставление дополнительной телеметриии и данных об использовании",
"telemetry_title": "Предоставление дополнительной телеметрии и данных об использовании",
"temperature": "Температура",
"text_file": "Текстовый файл",
"text_size": "Размер текста",

View file

@ -87,6 +87,8 @@
"cut_object": "Nesneyi kes",
"cut_success": "Öğeleri kes",
"data_folder": "Veri Klasörü",
"date_format": "Tarih Formatı",
"date_format_description": "Spacedrive'da görüntülenen tarih biçimini değiştirme",
"date_accessed": "Erişilen tarih",
"date_created": "tarih oluşturuldu",
"date_indexed": "Dizine Eklenme Tarihi",

View file

@ -88,6 +88,8 @@
"cut_object": "剪切对象",
"cut_success": "剪切项目",
"data_folder": "数据文件夹",
"date_format": "日期格式",
"date_format_description": "选择 Spacedrive 中显示的日期格式",
"date_accessed": "访问日期",
"date_created": "创建日期",
"date_indexed": "索引日期",

View file

@ -87,6 +87,8 @@
"cut_object": "剪下物件",
"cut_success": "剪下項目",
"data_folder": "數據文件夾",
"date_format": "日期格式",
"date_format_description": "選擇 Spacedrive 中顯示的日期格式",
"date_accessed": "訪問日期",
"date_created": "建立日期",
"date_indexed": "索引日期",