Translations, UI

This commit is contained in:
Chris Veleris 2025-07-10 22:38:50 +03:00
parent 89439b67db
commit 2e15d809a6
15 changed files with 336 additions and 177 deletions

View file

@ -117,10 +117,10 @@ const Navbar: React.FC<NavbarProps> = ({
<nav className="fixed top-0 left-0 right-0 z-50 bg-white dark:bg-gray-900 text-gray-900 dark:text-white shadow-md h-16">
<div className="h-full flex items-center">
{/* Sidebar-width area with logo and hamburger */}
<div className={`${isSidebarOpen ? 'w-full sm:w-72' : 'w-16'} flex items-center ${isSidebarOpen ? 'justify-start' : 'justify-center'} transition-all duration-300 ease-in-out px-4 relative`}>
<div className={`${isSidebarOpen ? 'w-full sm:w-72' : 'w-16'} flex items-center ${isSidebarOpen ? 'sm:justify-center' : 'sm:justify-start'} transition-all duration-300 ease-in-out px-4 relative`}>
<button
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
className="flex items-center focus:outline-none text-gray-500 dark:text-gray-500 absolute left-4"
className={`flex items-center focus:outline-none text-gray-500 dark:text-gray-500 ${isSidebarOpen ? 'sm:absolute sm:left-4' : 'sm:relative'}`}
aria-label={
isSidebarOpen
? 'Collapse Sidebar'
@ -130,23 +130,15 @@ const Navbar: React.FC<NavbarProps> = ({
<Bars3Icon className="h-6 mt-1 w-6" />
</button>
{isSidebarOpen && (
<Link
to="/"
className="flex items-center no-underline text-gray-900 dark:text-white ml-12"
>
<span className="text-2xl font-bold">tududi</span>
</Link>
)}
{!isSidebarOpen && (
<Link
to="/"
className="flex items-center no-underline text-gray-900 dark:text-white"
>
<span className="text-2xl font-bold">tududi</span>
</Link>
)}
<Link
to="/"
className={`flex items-center no-underline text-gray-900 dark:text-white ml-2 ${isSidebarOpen ? 'sm:ml-0' : 'sm:ml-2'}`}
>
<span className="text-2xl font-bold">
<span className="sm:hidden">t</span>
<span className="hidden sm:inline">tududi</span>
</span>
</Link>
</div>
{/* Right section - Actions and user menu */}
@ -183,7 +175,7 @@ const Navbar: React.FC<NavbarProps> = ({
{isDropdownOpen && (
<div
ref={dropdownRef}
className="absolute right-4 top-16 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-1 border border-gray-200 dark:border-gray-700"
className="absolute right-0 top-16 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-1 border border-gray-200 dark:border-gray-700"
>
<Link
to="/profile"

View file

@ -787,19 +787,19 @@ const ProfileSettings: React.FC<ProfileSettingsProps> = ({
{/* Navigation Tabs */}
<div className="mb-8">
<div className="border-b border-gray-200 dark:border-gray-700">
<nav className="-mb-px flex space-x-8">
<nav className="-mb-px flex space-x-2 sm:space-x-8 overflow-x-auto scrollbar-hide">
{tabs.map((tab) => (
<button
key={tab.id}
type="button"
onClick={() => setActiveTab(tab.id)}
className={`group inline-flex items-center py-2 px-1 border-b-2 font-medium text-sm ${
className={`group inline-flex items-center py-2 px-1 sm:px-2 border-b-2 font-medium text-sm whitespace-nowrap ${
activeTab === tab.id
? 'border-blue-500 text-blue-600 dark:text-blue-400'
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300'
}`}
>
<span className="mr-2">
<span className="mr-1 sm:mr-2">
{renderTabIcon(tab.icon)}
</span>
{tab.name}

View file

@ -543,7 +543,7 @@ const ProjectDetails: React.FC = () => {
{completedTasks.length > 0 && (
<label className="flex items-center space-x-2 cursor-pointer">
<span className="text-sm text-gray-600 dark:text-gray-400">
Show completed
{t('project.showCompleted', 'Show completed')}
</span>
<div className="relative flex items-center">
<input
@ -666,7 +666,7 @@ const ProjectDetails: React.FC = () => {
</div>
) : (
<p className="text-gray-500 dark:text-gray-400">
{t('notes.noNotes', 'No notes for this project.')}
{t('project.noNotes', 'No notes for this project.')}
</p>
)}
</div>

View file

@ -231,38 +231,40 @@ const DatePicker: React.FC<DatePickerProps> = ({
ref={dropdownRef}
className={`relative inline-block text-left w-full ${className}`}
>
<button
type="button"
className={`inline-flex justify-between w-full px-3 py-2 bg-white dark:bg-gray-900 text-sm text-gray-900 dark:text-gray-100 border border-gray-300 dark:border-gray-900 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors ${
disabled
? 'opacity-50 cursor-not-allowed'
: 'hover:bg-gray-50 dark:hover:bg-gray-800'
}`}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleToggle();
}}
disabled={disabled}
>
<span
className={`truncate ${!value ? 'text-gray-500 dark:text-gray-400' : ''}`}
<div className="relative">
<button
type="button"
className={`inline-flex justify-between w-full px-3 py-2 bg-white dark:bg-gray-900 text-sm text-gray-900 dark:text-gray-100 border border-gray-300 dark:border-gray-900 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors ${
disabled
? 'opacity-50 cursor-not-allowed'
: 'hover:bg-gray-50 dark:hover:bg-gray-800'
}`}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleToggle();
}}
disabled={disabled}
>
{formatDisplayDate(value)}
</span>
<div className="flex items-center space-x-1">
{value && (
<button
type="button"
onClick={handleClear}
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-xs"
>
×
</button>
)}
<CalendarDaysIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
</div>
</button>
<span
className={`truncate ${!value ? 'text-gray-500 dark:text-gray-400' : ''}`}
>
{formatDisplayDate(value)}
</span>
<div className="flex items-center space-x-1">
<CalendarDaysIcon className="w-5 h-5 text-gray-500 dark:text-gray-300" />
</div>
</button>
{value && (
<button
type="button"
onClick={handleClear}
className="absolute right-8 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-xs w-4 h-4 flex items-center justify-center"
>
×
</button>
)}
</div>
{isOpen &&
createPortal(

View file

@ -18,7 +18,6 @@ export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const [toasts, setToasts] = useState<Toast[]>([]);
const [nextId, setNextId] = useState(1);
const removeToast = useCallback((id: number) => {
setToasts(prev => prev.filter(toast => toast.id !== id));
@ -26,22 +25,20 @@ export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({
const showSuccessToast = useCallback(
(message: string | React.ReactNode) => {
const id = nextId;
setNextId(prev => prev + 1);
const id = Date.now() + Math.random();
const newToast: Toast = { id, message, type: 'success' };
setToasts(prev => [...prev, newToast]);
setTimeout(() => removeToast(id), 4000);
},
[nextId, removeToast]
[removeToast]
);
const showErrorToast = useCallback((message: string | React.ReactNode) => {
const id = nextId;
setNextId(prev => prev + 1);
const id = Date.now() + Math.random();
const newToast: Toast = { id, message, type: 'error' };
setToasts(prev => [...prev, newToast]);
setTimeout(() => removeToast(id), 4000);
}, [nextId, removeToast]);
}, [removeToast]);
return (
<ToastContext.Provider value={{ showSuccessToast, showErrorToast }}>

View file

@ -262,9 +262,9 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
{/* Mobile view (below md breakpoint) */}
<div className="block md:hidden">
<div className="flex items-start">
<div className="flex items-center">
{/* Priority Icon - Centered vertically with entire card */}
<div className="flex items-center justify-center w-5 mt-4 flex-shrink-0">
<div className="flex items-center justify-center w-5 flex-shrink-0">
<TaskPriorityIcon
priority={task.priority}
status={task.status}
@ -272,11 +272,11 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
/>
</div>
{/* All content - Task name and metadata */}
<div className="ml-2 flex-1">
{/* Task content - 65% width */}
<div className="ml-2 flex-1 w-[65%]">
{/* Task Title */}
<div className="flex items-center font-light text-md text-gray-900 dark:text-gray-100">
<span>{task.name}</span>
<span className="break-words">{task.name}</span>
{isOverdue && (
<span
className="ml-2 px-2 py-0.5 text-xs bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 rounded-md"
@ -324,70 +324,70 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
)}
</div>
</div>
</div>
{/* Mobile badges row */}
<div className="flex items-center flex-wrap justify-start space-x-2 mt-2 ml-7">
{/* Play/In Progress Controls - Mobile */}
{(task.status === 'not_started' ||
task.status === 'in_progress' ||
task.status === 0 ||
task.status === 1) && (
<button
onClick={handlePlayToggle}
className={`flex items-center justify-center w-6 h-6 rounded-full transition-all duration-200 ${
task.status === 'in_progress' ||
task.status === 1
? 'bg-green-100 dark:bg-green-900 text-green-600 dark:text-green-400 hover:bg-green-200 dark:hover:bg-green-800 animate-pulse'
: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 opacity-0 group-hover:opacity-100'
}`}
title={
task.status === 'in_progress' ||
task.status === 1
? t(
'tasks.setNotStarted',
'Set to not started'
)
: t(
'tasks.setInProgress',
'Set in progress'
)
}
>
<PlayIcon className="h-3 w-3" />
</button>
)}
{/* Mobile buttons on the right */}
<div className="flex items-center space-x-2 ml-2">
{/* Today Plan Controls - Mobile */}
{onToggleToday && (
<button
onClick={handleTodayToggle}
className={`items-center justify-center ${Number(task.today_move_count) > 1 ? 'px-2 h-6' : 'w-6 h-6'} rounded-full transition-all duration-200 opacity-0 group-hover:opacity-100 ${
task.today
? 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 flex'
: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 hidden group-hover:flex'
}`}
title={
task.today
? t(
'tasks.removeFromToday',
'Remove from today plan'
)
: t('tasks.addToToday', 'Add to today plan')
}
>
{task.today ? (
<CalendarDaysIcon className="h-3 w-3" />
) : (
<CalendarIcon className="h-3 w-3" />
)}
{Number(task.today_move_count) > 1 && (
<span className="ml-1 text-xs font-medium">
{Number(task.today_move_count)}
</span>
)}
</button>
)}
{/* Today Plan Controls - Mobile */}
{onToggleToday && (
<button
onClick={handleTodayToggle}
className={`items-center justify-center ${Number(task.today_move_count) > 1 ? 'px-2 h-6' : 'w-6 h-6'} rounded-full transition-all duration-200 opacity-0 group-hover:opacity-100 ${
task.today
? 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 flex'
: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 hidden group-hover:flex'
}`}
title={
task.today
? t(
'tasks.removeFromToday',
'Remove from today plan'
)
: t('tasks.addToToday', 'Add to today plan')
}
>
{task.today ? (
<CalendarDaysIcon className="h-3 w-3" />
) : (
<CalendarIcon className="h-3 w-3" />
)}
{Number(task.today_move_count) > 1 && (
<span className="ml-1 text-xs font-medium">
{Number(task.today_move_count)}
</span>
)}
</button>
)}
{/* Play/In Progress Controls - Mobile */}
{(task.status === 'not_started' ||
task.status === 'in_progress' ||
task.status === 0 ||
task.status === 1) && (
<button
onClick={handlePlayToggle}
className={`flex items-center justify-center w-6 h-6 rounded-full transition-all duration-200 ${
task.status === 'in_progress' ||
task.status === 1
? 'bg-green-100 dark:bg-green-900 text-green-600 dark:text-green-400 hover:bg-green-200 dark:hover:bg-green-800 animate-pulse'
: 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 opacity-0 group-hover:opacity-100'
}`}
title={
task.status === 'in_progress' ||
task.status === 1
? t(
'tasks.setNotStarted',
'Set to not started'
)
: t(
'tasks.setInProgress',
'Set in progress'
)
}
>
<PlayIcon className="h-3 w-3" />
</button>
)}
</div>
</div>
</div>
</div>

View file

@ -502,11 +502,11 @@ const TasksToday: React.FC = () => {
<div className="mb-4">
<div className="flex items-end justify-between mb-4">
<div className="flex items-end">
<CalendarDaysIcon className="h-5 w-5 mr-2 mb-1" />
<h2 className="text-2xl font-light mr-4">
{t('tasks.today')}
<CalendarDaysIcon className="h-6 w-6 mr-2 mb-1" />
<h2 className="text-2xl font-light mr-2">
{t('tasks.today')},
</h2>
<span className="text-gray-500">
<span className="text-lg font-light text-gray-500 dark:text-gray-400 opacity-80">
{format(new Date(), 'PPP', {
locale: getLocale(i18n.language),
})}

View file

@ -40,7 +40,7 @@ const i18nInstance = i18n
i18nInstance
.init({
fallbackLng: 'en',
debug: isDevelopment,
debug: false,
load: 'languageOnly',
supportedLngs: ['en', 'es', 'el', 'jp', 'ua', 'de'],
nonExplicitSupportedLngs: true,

View file

@ -109,3 +109,13 @@ input:focus, select:focus, textarea:focus {
box-shadow: none;
}
/* Hide scrollbar for mobile tab navigation */
.scrollbar-hide {
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE/Edge */
}
.scrollbar-hide::-webkit-scrollbar {
display: none; /* Chrome/Safari */
}

View file

@ -31,6 +31,7 @@
"profile": "Profil",
"profileSettings": "Profil-Einstellungen",
"settings": "Einstellungen",
"about": "Über",
"logout": "Abmelden"
},
"settings": {
@ -60,6 +61,7 @@
"myPlanToday": "Mein Plan für Heute",
"noPlanToday": "Noch keine Aufgaben für heute geplant",
"addToPlanHint": "Verwende die Kalendersymbole neben den Aufgaben, um sie zu deinem heutigen Plan hinzuzufügen",
"blankSlateHint": "Beginnen Sie mit der Erstellung einer neuen Aufgabe oder ändern Sie Ihre Filter.",
"addToToday": "Zu heutigem Plan hinzufügen",
"removeFromToday": "Aus heutigem Plan entfernen"
},
@ -120,7 +122,11 @@
"noteCreation": "Neue Notiz erstellen",
"noteEdit": "Notiz bearbeiten",
"createProject": "Projekt erstellen",
"updateProject": "Projekt aktualisieren"
"updateProject": "Projekt aktualisieren",
"deleteProject": {
"title": "Projekt löschen",
"message": "Sind Sie sicher, dass Sie das Projekt \"{{projectName}}\" löschen möchten?"
}
},
"errors": {
"noteTitleRequired": "Notiz-Titel ist erforderlich.",
@ -167,11 +173,43 @@
"saturday": "Samstag"
},
"inbox": {
"title": "Posteingang",
"empty": "Ihr Posteingang ist leer",
"emptyDescription": "Erfassen Sie schnell Gedanken und Ideen mit dem ⚡ Symbol in der oberen Navigationsleiste oder dem + Button in der Seitenleiste"
"emptyDescription": "Erfassen Sie schnell Gedanken und Ideen mit dem ⚡ Symbol in der oberen Navigationsleiste oder dem + Button in der Seitenleiste",
"description": "Der Posteingang ist der Ort, an dem sich alle unkategorisierten Aufgaben befinden. Aufgaben, die keinem Projekt zugewiesen wurden oder kein Fälligkeitsdatum haben, werden hier angezeigt. Dies ist Ihr 'Gedankendeponie'-Bereich, in dem Sie schnell Aufgaben notieren und später organisieren können."
},
"project": {
"name": "Projektname",
"projectImage": "Projektbild",
"uploadImageHint": "Laden Sie ein Bild für Ihr Projekt hoch (max. 5MB)",
"browseImage": "Bild durchsuchen",
"noNotes": "Keine Notizen für dieses Projekt.",
"deleteProject": "Projekt löschen",
"showCompleted": "Abgeschlossene anzeigen"
},
"profile": {
"title": "Profil-Einstellungen",
"appearance": "Erscheinungsbild",
"language": "Sprache",
"timezone": "Zeitzone",
"english": "Englisch",
"spanish": "Spanisch",
"greek": "Griechisch",
"ukrainian": "Ukrainisch",
"deutsch": "Deutsch",
"japanese": "Japanisch",
"pollingNote": "Das Polling prüft regelmäßig neue Nachrichten von Telegram und fügt sie zu Ihrem Posteingang hinzu.",
"pollingDescription": "Das Polling prüft regelmäßig neue Nachrichten von Telegram und fügt sie zu Ihrem Posteingang hinzu.",
"startPolling": "Polling starten",
"stopPolling": "Polling stoppen",
"startPollingLower": "polling starten",
"stopPollingLower": "polling stoppen",
"openTelegram": "In Telegram öffnen",
"openInTelegram": "in telegram öffnen",
"setupTelegram": "Telegram einrichten",
"setupTelegramLower": "telegram einrichten",
"passwordChangeNote": "Passwort-Änderungen werden gespeichert, wenn Sie unten im Formular auf \"Änderungen speichern\" klicken.",
"passwordChangeOptional": "Lassen Sie die Passwort-Felder leer, um andere Einstellungen zu aktualisieren, ohne Ihr Passwort zu ändern."
"taskIntelligence": "Aufgaben-Intelligenz",
"taskIntelligenceDescription": "Erhalten Sie hilfreiche Vorschläge, um Ihre Aufgabennamen beschreibender und umsetzbarer zu machen.",
"enableTaskIntelligence": "Aufgaben-Intelligenz-Assistent aktivieren",

View file

@ -45,6 +45,7 @@
"profile": "Προφίλ",
"profileSettings": "Ρυθμίσεις Προφίλ",
"settings": "Ρυθμίσεις",
"about": "Σχετικά",
"logout": "Αποσύνδεση"
},
"settings": {
@ -96,6 +97,8 @@
"languagePreference": "Προτίμηση Γλώσσας",
"personalInfo": "Προσωπικές Πληροφορίες",
"notifications": "Ειδοποιήσεις",
"title": "Ρυθμίσεις Προφίλ",
"language": "Γλώσσα",
"appearance": "Εμφάνιση",
"lightMode": "Φωτεινό Θέμα",
"darkMode": "Σκοτεινό Θέμα",
@ -111,6 +114,17 @@
"telegramTokenDescription": "Δημιουργήστε ένα bot με το @BotFather στο Telegram και επικολλήστε το token εδώ.",
"telegramConnected": "Ο λογαριασμός σας στο Telegram είναι συνδεδεμένος! Στείλτε μηνύματα στο bot σας για να προσθέσετε στοιχεία στα εισερχόμενά σας στο tududi.",
"setupTelegram": "Ρύθμιση Telegram",
"setupTelegramLower": "ρύθμιση telegram",
"pollingNote": "Η ανίχνευση ελέγχει περιοδικά για νέα μηνύματα από το Telegram και τα προσθέτει στα εισερχόμενά σας.",
"pollingDescription": "Η ανίχνευση ελέγχει περιοδικά για νέα μηνύματα από το Telegram και τα προσθέτει στα εισερχόμενά σας.",
"startPolling": "Έναρξη Ανίχνευσης",
"stopPolling": "Διακοπή Ανίχνευσης",
"startPollingLower": "έναρξη ανίχνευσης",
"stopPollingLower": "διακοπή ανίχνευσης",
"openTelegram": "Άνοιγμα στο Telegram",
"openInTelegram": "άνοιγμα στο telegram",
"passwordChangeNote": "Οι αλλαγές κωδικού πρόσβασης θα αποθηκευτούν όταν κάνετε κλικ στο \"Αποθήκευση Αλλαγών\" στο κάτω μέρος της φόρμας.",
"passwordChangeOptional": "Αφήστε τα πεδία κωδικού πρόσβασης κενά για να ενημερώσετε άλλες ρυθμίσεις χωρίς να αλλάξετε τον κωδικό πρόσβασής σας.",
"taskSummaryNotifications": "Ειδοποιήσεις Περίληψης Εργασιών",
"taskSummaryDescription": "Λάβετε τακτικές περιλήψεις των εργασιών σας μέσω Telegram. Αυτή η λειτουργία απαιτεί να έχει ρυθμιστεί η ενσωμάτωση Telegram.",
"enableTaskSummaries": "Ενεργοποίηση Περιλήψεων Εργασιών",
@ -227,6 +241,7 @@
"myPlanToday": "Το πλάνο μου για σήμερα",
"noPlanToday": "Δεν υπάρχουν ακόμη εργασίες προγραμματισμένες για σήμερα",
"addToPlanHint": "Χρησιμοποιήστε τα εικονίδια ημερολογίου δίπλα στις εργασίες για να τις προσθέσετε στο σημερινό σας σχέδιο",
"blankSlateHint": "Ξεκινήστε δημιουργώντας μια νέα εργασία ή αλλάζοντας τα φίλτρα σας.",
"addToToday": "Προσθήκη στο σημερινό σχέδιο",
"removeFromToday": "Αφαίρεση από το σημερινό σχέδιο"
},
@ -338,6 +353,10 @@
"updateNote": "Ενημέρωση Σημείωσης",
"createNote": "Δημιουργία Σημείωσης",
"submitting": "Υποβολή...",
"deleteProject": {
"title": "Διαγραφή Έργου",
"message": "Είστε σίγουροι ότι θέλετε να διαγράψετε το έργο \"{{projectName}}\";"
},
"deleteTask": {
"title": "Διαγραφή Εργασίας",
"confirmation": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτή την εργασία; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί."
@ -483,6 +502,7 @@
"title": "Εισερχόμενα",
"empty": "Τα εισερχόμενά σας είναι άδεια",
"emptyDescription": "Καταγράψτε γρήγορα σκέψεις και ιδέες χρησιμοποιώντας το εικονίδιο ⚡ στην άνω μπάρα ή το κουμπί + στην πλευρική μπάρα",
"description": "Τα εισερχόμενα είναι όπου βρίσκονται όλες οι μη κατηγοριοποιημένες εργασίες. Εργασίες που δεν έχουν αντιστοιχιστεί σε ένα έργο ή δεν έχουν ημερομηνία λήξης θα εμφανίζονται εδώ. Αυτή είναι η περιοχή 'αποφόρτισης του μυαλού σας' όπου μπορείτε γρήγορα να σημειώσετε εργασίες και να τις οργανώσετε αργότερα.",
"unprocessedItems": "Έχετε {{count}} αντικείμενο(α) στα εισερχόμενά σας.",
"processNow": "Επεξεργαστείτε τα τώρα",
"captureThought": "Καταγράψτε μια σκέψη",
@ -579,7 +599,10 @@
"name": "Όνομα Έργου",
"projectImage": "Εικόνα Έργου",
"uploadImageHint": "Μεταφορτώστε μια εικόνα για το έργο σας (μέγ. 5MB)",
"browseImage": "Περιήγηση Εικόνας"
"browseImage": "Περιήγηση Εικόνας",
"noNotes": "Δεν υπάρχουν σημειώσεις για αυτό το έργο.",
"deleteProject": "Διαγραφή Έργου",
"showCompleted": "Εμφάνιση Ολοκληρωμένων"
},
"pomodoro": {
"play": "Αναπαραγωγή",

View file

@ -143,6 +143,8 @@
"appearance": "Appearance",
"lightMode": "Light Mode",
"darkMode": "Dark Mode",
"light": "Light",
"dark": "Dark",
"timezone": "Timezone",
"saveChanges": "Save Changes",
"successMessage": "Profile updated successfully!",
@ -157,6 +159,7 @@
"telegramTokenDescription": "Create a bot with @BotFather on Telegram and paste the token here.",
"telegramConnected": "Your Telegram account is connected! Send messages to your bot to add items to your tududi inbox.",
"setupTelegram": "Setup Telegram",
"setupTelegramLower": "setup telegram",
"settingUp": "Setting up...",
"telegramSetupSuccess": "Telegram bot \"{{botName}}\" configured successfully!",
"telegramSetupFailed": "Failed to set up Telegram bot.",
@ -168,14 +171,18 @@
"pollingActive": "Active - Receiving messages",
"pollingInactive": "Inactive - Not receiving messages",
"pollingNote": "Polling periodically checks for new messages from Telegram and adds them to your inbox.",
"pollingDescription": "Polling periodically checks for new messages from Telegram and adds them to your inbox.",
"startPolling": "Start Polling",
"stopPolling": "Stop Polling",
"startPollingLower": "start polling",
"stopPollingLower": "stop polling",
"pollingStarted": "Telegram polling started",
"pollingStopped": "Telegram polling stopped",
"pollingError": "Error managing Telegram polling",
"startPollingFailed": "Failed to start polling",
"stopPollingFailed": "Failed to stop polling",
"openTelegram": "Open in Telegram",
"openInTelegram": "open in telegram",
"testTelegramMessage": "Test Telegram",
"testMessageSent": "Test message sent successfully!",
"testMessageFailed": "Failed to send test message.",
@ -345,7 +352,21 @@
"creatingProject": "Creating...",
"createProject": "+ Create",
"recurrenceSettings": "Recurrence Settings",
"completionBasedHelp": "If checked, the next task will be created based on completion date instead of due date"
"completionBasedHelp": "If checked, the next task will be created based on completion date instead of due date",
"dueDatePlaceholder": "Select due date",
"endDatePlaceholder": "Select end date",
"nameHelper": {
"title": "Make it more descriptive!",
"suggestion": "Try adding more details like \"Call dentist to schedule cleaning appointment\" instead of just \"Call dentist\"",
"short": "Make it more descriptive!",
"noVerb": "Add an action verb!",
"vague": "Be more specific!"
},
"suggestions": {
"short": "Try to be more specific about what needs to be done",
"noVerb": "What specific action do you need to take? Try starting with a verb.",
"vague": "Try starting with an action verb like \"Call\", \"Write\", \"Schedule\", or \"Research\""
}
},
"noteTitle": "Note Title",
"noteContent": "Note Content",
@ -359,21 +380,7 @@
"tagNamePlaceholder": "Enter tag name",
"tagInputPlaceholder": "Type to add a tag",
"createTagOption": "+ Create \"{{tagName}}\"",
"removeTagAriaLabel": "Remove tag {{tagName}}",
"task": {
"nameHelper": {
"title": "Make it more descriptive!",
"suggestion": "Try adding more details like \"Call dentist to schedule cleaning appointment\" instead of just \"Call dentist\"",
"short": "Make it more descriptive!",
"noVerb": "Add an action verb!",
"vague": "Be more specific!"
},
"suggestions": {
"short": "Try to be more specific about what needs to be done",
"noVerb": "What specific action do you need to take? Try starting with a verb.",
"vague": "Try starting with an action verb like \"Call\", \"Write\", \"Schedule\", or \"Research\""
}
}
"removeTagAriaLabel": "Remove tag {{tagName}}"
},
"auth": {
"login": "Login",
@ -423,7 +430,9 @@
"name": "Project Name",
"projectImage": "Project Image",
"uploadImageHint": "Upload an image for your project (max 5MB)",
"browseImage": "Browse Image"
"browseImage": "Browse Image",
"noNotes": "No notes for this project.",
"deleteProject": "Delete Project"
},
"errors": {
"required": "This field is required",
@ -454,6 +463,7 @@
"title": "Inbox",
"empty": "Your inbox is empty",
"emptyDescription": "Capture thoughts and ideas quickly using the ⚡ icon in the top navbar or the + button in the sidebar",
"description": "Inbox is where all uncategorized tasks are located. Tasks that have not been assigned to a project or don't have a due date will appear here. This is your 'brain dump' area where you can quickly note down tasks and organize them later.",
"captureThought": "Capture your thought...",
"saveToInbox": "Save to Inbox",
"itemAdded": "Item added to inbox",
@ -642,7 +652,8 @@
"secondWeek": "Second week",
"thirdWeek": "Third week",
"fourthWeek": "Fourth week",
"lastWeek": "Last week"
"lastWeek": "Last week",
"days": "days"
},
"weekdays": {
"sunday": "Sunday",
@ -702,14 +713,5 @@
"low": "Low",
"time": "Time",
"allDay": "All day"
},
"weekdays": {
"monday": "Mon",
"tuesday": "Tue",
"wednesday": "Wed",
"thursday": "Thu",
"friday": "Fri",
"saturday": "Sat",
"sunday": "Sun"
}
}

View file

@ -45,6 +45,7 @@
"profile": "Perfil",
"profileSettings": "Configuración de Perfil",
"settings": "Ajustes",
"about": "Acerca de",
"logout": "Cerrar Sesión"
},
"settings": {
@ -85,11 +86,15 @@
},
"profile": {
"title": "Configuración de Perfil",
"appearance": "Apariencia",
"language": "Idioma",
"timezone": "Zona Horaria",
"theme": "Tema",
"english": "Inglés",
"spanish": "Español",
"greek": "Griego",
"ukrainian": "Ucraniano",
"deutsch": "Alemán",
"japanese": "Japonés",
"languagePreference": "Preferencia de Idioma",
"personalInfo": "Información Personal",
@ -143,7 +148,19 @@
"accountSettings": "Cuenta y Preferencias",
"aiProductivityFeatures": "Funciones de IA y Productividad",
"botSetup": "Configuración del Bot",
"successMessage": "¡Perfil actualizado con éxito!"
"successMessage": "¡Perfil actualizado con éxito!",
"pollingNote": "El sondeo verifica periódicamente nuevos mensajes de Telegram y los agrega a tu bandeja de entrada.",
"pollingDescription": "El sondeo verifica periódicamente nuevos mensajes de Telegram y los agrega a tu bandeja de entrada.",
"startPolling": "Iniciar Sondeo",
"stopPolling": "Detener Sondeo",
"startPollingLower": "iniciar sondeo",
"stopPollingLower": "detener sondeo",
"openTelegram": "Abrir en Telegram",
"openInTelegram": "abrir en telegram",
"setupTelegram": "Configurar Telegram",
"setupTelegramLower": "configurar telegram",
"passwordChangeNote": "Los cambios de contraseña se guardarán cuando hagas clic en \"Guardar Cambios\" en la parte inferior del formulario.",
"passwordChangeOptional": "Deja los campos de contraseña vacíos para actualizar otras configuraciones sin cambiar tu contraseña."
},
"errors": {
"required": "Este campo es obligatorio",
@ -184,6 +201,7 @@
"myPlanToday": "Mi Plan para Hoy",
"noPlanToday": "Aún no hay tareas planificadas para hoy",
"addToPlanHint": "Usa los iconos + junto a las tareas sugeridas para añadirlas a tu plan de hoy",
"blankSlateHint": "Comience creando una nueva tarea o cambiando sus filtros.",
"addToToday": "Añadir al plan de hoy",
"removeFromToday": "Eliminar del plan de hoy"
},
@ -264,7 +282,11 @@
"createNote": "Crear Nota",
"submitting": "Enviando...",
"createProject": "Crear Proyecto",
"updateProject": "Actualizar Proyecto"
"updateProject": "Actualizar Proyecto",
"deleteProject": {
"title": "Eliminar Proyecto",
"message": "¿Estás seguro de que quieres eliminar el proyecto \"{{projectName}}\"?"
}
},
"forms": {
"title": "Título",
@ -384,6 +406,7 @@
"title": "Bandeja de Entrada",
"empty": "Su bandeja de entrada está vacía",
"emptyDescription": "Capture rápidamente pensamientos e ideas usando el icono ⚡ en la barra superior o el botón + en la barra lateral",
"description": "La bandeja de entrada es donde se encuentran todas las tareas sin categorizar. Las tareas que no han sido asignadas a un proyecto o no tienen fecha de vencimiento aparecerán aquí. Esta es tu área de 'volcado mental' donde puedes anotar rápidamente tareas y organizarlas más tarde.",
"captureThought": "Capture su pensamiento...",
"saveToInbox": "Guardar en Bandeja de Entrada",
"itemAdded": "Elemento agregado a la bandeja de entrada",
@ -499,9 +522,13 @@
"saturday": "Sábado"
},
"project": {
"name": "Nombre del Proyecto",
"projectImage": "Imagen del Proyecto",
"uploadImageHint": "Sube una imagen para tu proyecto (máx. 5MB)",
"browseImage": "Examinar Imagen"
"browseImage": "Examinar Imagen",
"noNotes": "No hay notas para este proyecto.",
"deleteProject": "Eliminar Proyecto",
"showCompleted": "Mostrar Completados"
},
"pomodoro": {
"play": "Reproducir",

View file

@ -37,6 +37,7 @@
"profile": "プロフィール",
"profileSettings": "プロフィール設定",
"settings": "設定",
"about": "について",
"logout": "ログアウト"
},
"settings": {
@ -72,6 +73,7 @@
"myPlanToday": "今日の私の計画",
"noPlanToday": "今日はまだ予定されたタスクがありません",
"addToPlanHint": "タスクの横にあるカレンダーアイコンを使用して、今日の計画に追加します",
"blankSlateHint": "新しいタスクを作成するか、フィルターを変更して開始してください。",
"addToToday": "今日の計画に追加",
"removeFromToday": "今日の計画から削除"
},
@ -101,13 +103,30 @@
},
"profile": {
"settings": "プロフィール設定",
"title": "プロフィール設定",
"appearance": "外観",
"language": "言語",
"timezone": "タイムゾーン",
"theme": "テーマ",
"notifications": "通知",
"english": "英語",
"spanish": "スペイン語",
"greek": "ギリシャ語",
"japanese": "日本語"
"ukrainian": "ウクライナ語",
"deutsch": "ドイツ語",
"japanese": "日本語",
"pollingNote": "ポーリングはTelegramからの新しいメッセージを定期的にチェックし、受信トレイに追加します。",
"pollingDescription": "ポーリングはTelegramからの新しいメッセージを定期的にチェックし、受信トレイに追加します。",
"startPolling": "ポーリング開始",
"stopPolling": "ポーリング停止",
"startPollingLower": "ポーリング開始",
"stopPollingLower": "ポーリング停止",
"openTelegram": "Telegramで開く",
"openInTelegram": "telegramで開く",
"setupTelegram": "Telegram設定",
"setupTelegramLower": "telegram設定",
"passwordChangeNote": "パスワードの変更は、フォームの下部にある「変更を保存」をクリックすると保存されます。",
"passwordChangeOptional": "パスワードを変更せずに他の設定を更新するには、パスワードフィールドを空のままにしてください。"
},
"nextTask": {
"suggestion": "進行中のものがないので、こちらから始めてみませんか",
@ -140,12 +159,12 @@
"title": "ノートの削除",
"message": "\"{{noteTitle}}\" ノートを削除してもよろしいですか?"
},
"deleteProject": {
"title": "プロジェクトの削除",
"message": "\"{{projectName}}\" プロジェクトを削除してもよろしいですか?"
},
"createProject": "プロジェクトを作成",
"updateProject": "プロジェクトを更新"
"updateProject": "プロジェクトを更新",
"deleteProject": {
"title": "プロジェクトを削除",
"message": "プロジェクト「{{projectName}}」を削除してもよろしいですか?"
}
},
"forms": {
"title": "タイトル",
@ -341,8 +360,19 @@
"saturday": "土曜日"
},
"inbox": {
"title": "受信箱",
"empty": "受信箱は空です",
"emptyDescription": "上部ナビゲーションバーの ⚡ アイコンまたはサイドバーの + ボタンを使用して、思考やアイデアを素早く記録できます"
"emptyDescription": "上部ナビゲーションバーの ⚡ アイコンまたはサイドバーの + ボタンを使用して、思考やアイデアを素早く記録できます",
"description": "受信箱は、カテゴリ未分類のタスクがすべて保存される場所です。プロジェクトに割り当てられていない、または期限が設定されていないタスクがここに表示されます。これは思考を素早くメモし、後で整理できる「頭の整理」エリアです。"
},
"project": {
"name": "プロジェクト名",
"projectImage": "プロジェクト画像",
"uploadImageHint": "プロジェクトの画像をアップロード最大5MB",
"browseImage": "画像を参照",
"noNotes": "このプロジェクトにはメモがありません。",
"deleteProject": "プロジェクトを削除",
"showCompleted": "完了済みを表示"
},
"profile": {
"taskIntelligence": "タスクインテリジェンス",

View file

@ -38,6 +38,7 @@
"profile": "Профіль",
"profileSettings": "Налаштування профілю",
"settings": "Налаштування",
"about": "Про програму",
"logout": "Вийти"
},
"settings": {
@ -73,6 +74,7 @@
"myPlanToday": "Мій План на Сьогодні",
"noPlanToday": "Поки що немає завдань, запланованих на сьогодні",
"addToPlanHint": "Використовуйте іконки календаря поруч із завданнями, щоб додати їх до сьогоднішнього плану",
"blankSlateHint": "Почніть зі створення нового завдання або зміни фільтрів.",
"addToToday": "Додати до сьогоднішнього плану",
"removeFromToday": "Видалити з сьогоднішнього плану"
},
@ -166,7 +168,11 @@
"noteCreation": "Створити нову нотатку",
"noteEdit": "Редагувати нотатку",
"createProject": "Створити проект",
"updateProject": "Оновити проект"
"updateProject": "Оновити проект",
"deleteProject": {
"title": "Видалити Проект",
"message": "Ви впевнені, що хочете видалити проект \"{{projectName}}\"?"
}
},
"errors": {
@ -221,11 +227,43 @@
"saturday": "Субота"
},
"inbox": {
"title": "Вхідні",
"empty": "Ваша скринька порожня",
"emptyDescription": "Швидко записуйте думки та ідеї за допомогою іконки ⚡ у верхній навігаційній панелі або кнопки + у бічній панелі"
"emptyDescription": "Швидко записуйте думки та ідеї за допомогою іконки ⚡ у верхній навігаційній панелі або кнопки + у бічній панелі",
"description": "Вхідні - це місце, де знаходяться всі некатегоризовані завдання. Завдання, які не були призначені проекту або не мають терміну виконання, з'являться тут. Це ваша область 'викидання думок', де ви можете швидко записати завдання та організувати їх пізніше."
},
"project": {
"name": "Назва Проекту",
"projectImage": "Зображення Проекту",
"uploadImageHint": "Завантажте зображення для вашого проекту (макс. 5МБ)",
"browseImage": "Вибрати Зображення",
"noNotes": "Немає нотаток для цього проекту.",
"deleteProject": "Видалити Проект",
"showCompleted": "Показати Завершені"
},
"profile": {
"title": "Налаштування Профілю",
"appearance": "Зовнішній вигляд",
"language": "Мова",
"timezone": "Часовий пояс",
"english": "Англійська",
"spanish": "Іспанська",
"greek": "Грецька",
"ukrainian": "Українська",
"deutsch": "Німецька",
"japanese": "Японська",
"pollingNote": "Опитування періодично перевіряє нові повідомлення з Telegram і додає їх до вашої вхідної скриньки.",
"pollingDescription": "Опитування періодично перевіряє нові повідомлення з Telegram і додає їх до вашої вхідної скриньки.",
"startPolling": "Почати опитування",
"stopPolling": "Зупинити опитування",
"startPollingLower": "почати опитування",
"stopPollingLower": "зупинити опитування",
"openTelegram": "Відкрити в Telegram",
"openInTelegram": "відкрити в telegram",
"setupTelegram": "Налаштувати Telegram",
"setupTelegramLower": "налаштувати telegram",
"passwordChangeNote": "Зміни пароля будуть збережені, коли ви натиснете \"Зберегти зміни\" внизу форми.",
"passwordChangeOptional": "Залиште поля пароля порожніми, щоб оновити інші налаштування без зміни пароля.",
"taskIntelligence": "Інтелект Завдань",
"taskIntelligenceDescription": "Отримуйте корисні пропозиції, щоб зробити назви ваших завдань більш описовими та дієвими.",
"enableTaskIntelligence": "Увімкнути Асистента Інтелекту Завдань",