From eda1bd715507c342ddaa85ffd85718d0982d5766 Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 19 Mar 2026 11:26:30 +0100 Subject: [PATCH] feat(ux): add error boundaries and expand i18n to 5 languages - Add +error.svelte to Calendar (blue) and Todo (emerald) web apps - Add FR, IT, ES locale files for Contacts (216 keys each) - Add FR, IT, ES locale files for Todo (104 keys each) - Update i18n index.ts to register new locales All three apps now support DE, EN, FR, IT, ES Co-Authored-By: Claude Opus 4.6 (1M context) --- .../apps/web/src/routes/+error.svelte | 9 + apps/contacts/apps/web/src/lib/i18n/index.ts | 3 + .../apps/web/src/lib/i18n/locales/es.json | 217 ++++++++++++++++++ .../apps/web/src/lib/i18n/locales/fr.json | 217 ++++++++++++++++++ .../apps/web/src/lib/i18n/locales/it.json | 217 ++++++++++++++++++ apps/todo/apps/web/src/lib/i18n/index.ts | 5 +- .../apps/web/src/lib/i18n/locales/es.json | 104 +++++++++ .../apps/web/src/lib/i18n/locales/fr.json | 104 +++++++++ .../apps/web/src/lib/i18n/locales/it.json | 104 +++++++++ apps/todo/apps/web/src/routes/+error.svelte | 9 + 10 files changed, 988 insertions(+), 1 deletion(-) create mode 100644 apps/calendar/apps/web/src/routes/+error.svelte create mode 100644 apps/contacts/apps/web/src/lib/i18n/locales/es.json create mode 100644 apps/contacts/apps/web/src/lib/i18n/locales/fr.json create mode 100644 apps/contacts/apps/web/src/lib/i18n/locales/it.json create mode 100644 apps/todo/apps/web/src/lib/i18n/locales/es.json create mode 100644 apps/todo/apps/web/src/lib/i18n/locales/fr.json create mode 100644 apps/todo/apps/web/src/lib/i18n/locales/it.json create mode 100644 apps/todo/apps/web/src/routes/+error.svelte diff --git a/apps/calendar/apps/web/src/routes/+error.svelte b/apps/calendar/apps/web/src/routes/+error.svelte new file mode 100644 index 000000000..d5a57d247 --- /dev/null +++ b/apps/calendar/apps/web/src/routes/+error.svelte @@ -0,0 +1,9 @@ + + +
+

{$page.status}

+

{$page.error?.message || 'Seite nicht gefunden'}

+ Zurück zur Startseite +
diff --git a/apps/contacts/apps/web/src/lib/i18n/index.ts b/apps/contacts/apps/web/src/lib/i18n/index.ts index 22eaa7337..deec52816 100644 --- a/apps/contacts/apps/web/src/lib/i18n/index.ts +++ b/apps/contacts/apps/web/src/lib/i18n/index.ts @@ -11,6 +11,9 @@ const defaultLocale = 'de'; // Register all available locales register('de', () => import('./locales/de.json')); register('en', () => import('./locales/en.json')); +register('fr', () => import('./locales/fr.json')); +register('it', () => import('./locales/it.json')); +register('es', () => import('./locales/es.json')); // Get initial locale from browser or localStorage function getInitialLocale(): SupportedLocale { diff --git a/apps/contacts/apps/web/src/lib/i18n/locales/es.json b/apps/contacts/apps/web/src/lib/i18n/locales/es.json new file mode 100644 index 000000000..ee5f570c9 --- /dev/null +++ b/apps/contacts/apps/web/src/lib/i18n/locales/es.json @@ -0,0 +1,217 @@ +{ + "app": { + "name": "Contacts" + }, + "common": { + "back": "Volver", + "cancel": "Cancelar", + "loadingMore": "Cargando más..." + }, + "nav": { + "contacts": "Contactos", + "groups": "Grupos", + "tags": "Etiquetas", + "favorites": "Favoritos", + "archive": "Archivo", + "search": "Buscar", + "settings": "Configuración", + "feedback": "Comentarios", + "import": "Importar" + }, + "import": { + "title": "Importar contactos", + "subtitle": "Importa contactos desde archivos vCard o CSV", + "tabs": { + "file": "Importar archivo", + "google": "Google Contacts" + }, + "processing": "Procesando archivo...", + "importing": "Importando...", + "downloadTemplate": "Descargar plantilla CSV", + "dropzone": { + "title": "Arrastra el archivo aquí", + "subtitle": "o haz clic para seleccionar" + }, + "preview": { + "total": "Total", + "valid": "Válidos", + "duplicates": "Duplicados", + "selected": "Seleccionados", + "errors": "Errores de análisis", + "duplicateHandling": "¿Cómo gestionar los duplicados?", + "skip": "Omitir", + "merge": "Fusionar", + "create": "Crear de todos modos", + "contacts": "Contactos a importar", + "selectAll": "Seleccionar todos", + "deselectAll": "Deseleccionar todos", + "duplicateTag": "Duplicado", + "matchesWith": "Coincide con", + "importButton": "Importar {count} contactos" + }, + "result": { + "title": "Importación completada", + "subtitle": "Tus contactos han sido importados con éxito", + "imported": "Importados", + "merged": "Fusionados", + "skipped": "Omitidos", + "errors": "Errores", + "importMore": "Importar más", + "done": "Listo" + } + }, + "contacts": { + "title": "Contactos", + "new": "Nuevo contacto", + "edit": "Editar", + "delete": "Eliminar", + "search": "Buscar contactos...", + "noContacts": "No se encontraron contactos", + "addFirst": "Añade tu primer contacto", + "favorites": "Favoritos", + "archive": "Archivo", + "contact": "Contacto", + "contactsPlural": "Contactos", + "call": "Llamar", + "email": "Enviar correo", + "favorite": "Marcar como favorito", + "unfavorite": "Quitar de favoritos" + }, + "views": { + "list": "Vista de lista", + "grid": "Vista de cuadrícula", + "alphabet": "Alfabético" + }, + "sort": { + "firstName": "Nombre", + "lastName": "Apellido" + }, + "contact": { + "firstName": "Nombre", + "lastName": "Apellido", + "displayName": "Nombre para mostrar", + "email": "Correo electrónico", + "phone": "Teléfono", + "mobile": "Móvil", + "company": "Empresa", + "jobTitle": "Cargo", + "department": "Departamento", + "street": "Calle", + "city": "Ciudad", + "postalCode": "Código postal", + "country": "País", + "website": "Sitio web", + "birthday": "Cumpleaños", + "notes": "Notas", + "tasks": { + "title": "Tareas", + "assigned": "Asignadas", + "involved": "Involucrado", + "empty": "No hay tareas para este contacto", + "serviceUnavailable": "Servicio Todo no disponible", + "error": "Error al cargar las tareas", + "overdue": "Atrasada", + "dueToday": "Hoy", + "tomorrow": "Mañana", + "showCompleted": "Completadas", + "showMore": "Mostrar {count} más", + "markComplete": "Marcar como completada", + "markIncomplete": "Marcar como no completada" + } + }, + "groups": { + "title": "Grupos", + "new": "Nuevo grupo", + "noGroups": "No hay grupos disponibles" + }, + "actions": { + "save": "Guardar", + "cancel": "Cancelar", + "delete": "Eliminar", + "edit": "Editar", + "create": "Crear", + "favorite": "Favorito", + "unfavorite": "No favorito", + "archive": "Archivar", + "unarchive": "Restaurar" + }, + "messages": { + "saved": "Guardado", + "deleted": "Eliminado", + "error": "Ha ocurrido un error" + }, + "google": { + "loading": "Verificando conexión...", + "connect": { + "title": "Conectar con Google", + "subtitle": "Importa tus contactos directamente desde Google Contacts", + "button": "Conectar con Google" + }, + "connected": "Conectado a Google", + "disconnect": "Desconectar", + "contacts": "Contactos", + "loadMore": "Cargar más" + }, + "filters": { + "title": "Filtros", + "clearAll": "Borrar todo", + "tag": "Etiqueta", + "allTags": "Todas las etiquetas", + "contactInfo": "Info de contacto", + "contact": { + "all": "Todos los contactos", + "favorites": "Favoritos", + "hasPhone": "Con teléfono", + "hasEmail": "Con correo", + "incomplete": "Incompletos" + }, + "birthdayLabel": "Cumpleaños", + "birthday": { + "all": "Todos", + "today": "Hoy", + "thisWeek": "Esta semana", + "thisMonth": "Este mes" + }, + "company": "Empresa", + "allCompanies": "Todas las empresas" + }, + "export": { + "title": "Exportar contactos", + "button": "Exportar", + "format": "Seleccionar formato", + "selectedCount": "{count} contactos seleccionados", + "allContacts": "Se exportarán todos los contactos", + "includeArchived": "Incluir contactos archivados", + "exporting": "Exportando...", + "success": "Exportación exitosa" + }, + "notes": { + "title": "Notas", + "add": "Añadir nota", + "addFirst": "Añade tu primera nota", + "empty": "Sin notas todavía", + "placeholder": "Escribe una nota...", + "confirmDelete": "¿Eliminar esta nota?", + "pin": "Fijar nota", + "unpin": "Desfijar nota", + "yesterday": "Ayer" + }, + "tags": { + "title": "Etiquetas", + "new": "Nueva etiqueta", + "edit": "Editar etiqueta", + "noTags": "Sin etiquetas todavía", + "createFirst": "Crea tu primera etiqueta para organizar contactos", + "search": "Buscar etiquetas...", + "name": "Nombre", + "namePlaceholder": "Introduce el nombre de la etiqueta", + "color": "Color", + "preview": "Vista previa", + "contactCount": "{count} contactos", + "confirmDelete": "¿Estás seguro de que quieres eliminar \"{name}\"?", + "noResults": "No se encontraron etiquetas", + "noResultsFor": "Sin resultados para \"{query}\"", + "tagSingular": "Etiqueta", + "tagPlural": "Etiquetas" + } +} diff --git a/apps/contacts/apps/web/src/lib/i18n/locales/fr.json b/apps/contacts/apps/web/src/lib/i18n/locales/fr.json new file mode 100644 index 000000000..e2d87ee1c --- /dev/null +++ b/apps/contacts/apps/web/src/lib/i18n/locales/fr.json @@ -0,0 +1,217 @@ +{ + "app": { + "name": "Contacts" + }, + "common": { + "back": "Retour", + "cancel": "Annuler", + "loadingMore": "Chargement..." + }, + "nav": { + "contacts": "Contacts", + "groups": "Groupes", + "tags": "Tags", + "favorites": "Favoris", + "archive": "Archives", + "search": "Rechercher", + "settings": "Paramètres", + "feedback": "Commentaires", + "import": "Importer" + }, + "import": { + "title": "Importer des contacts", + "subtitle": "Importez des contacts depuis des fichiers vCard ou CSV", + "tabs": { + "file": "Import de fichier", + "google": "Google Contacts" + }, + "processing": "Traitement du fichier...", + "importing": "Importation...", + "downloadTemplate": "Télécharger le modèle CSV", + "dropzone": { + "title": "Déposez le fichier ici", + "subtitle": "ou cliquez pour sélectionner" + }, + "preview": { + "total": "Total", + "valid": "Valides", + "duplicates": "Doublons", + "selected": "Sélectionnés", + "errors": "Erreurs d'analyse", + "duplicateHandling": "Comment traiter les doublons ?", + "skip": "Ignorer", + "merge": "Fusionner", + "create": "Créer quand même", + "contacts": "Contacts à importer", + "selectAll": "Tout sélectionner", + "deselectAll": "Tout désélectionner", + "duplicateTag": "Doublon", + "matchesWith": "Correspond à", + "importButton": "Importer {count} contacts" + }, + "result": { + "title": "Import terminé", + "subtitle": "Vos contacts ont été importés avec succès", + "imported": "Importés", + "merged": "Fusionnés", + "skipped": "Ignorés", + "errors": "Erreurs", + "importMore": "Importer d'autres", + "done": "Terminé" + } + }, + "contacts": { + "title": "Contacts", + "new": "Nouveau contact", + "edit": "Modifier", + "delete": "Supprimer", + "search": "Rechercher des contacts...", + "noContacts": "Aucun contact trouvé", + "addFirst": "Ajoutez votre premier contact", + "favorites": "Favoris", + "archive": "Archives", + "contact": "Contact", + "contactsPlural": "Contacts", + "call": "Appeler", + "email": "Envoyer un e-mail", + "favorite": "Marquer comme favori", + "unfavorite": "Retirer des favoris" + }, + "views": { + "list": "Vue liste", + "grid": "Vue grille", + "alphabet": "Alphabétique" + }, + "sort": { + "firstName": "Prénom", + "lastName": "Nom" + }, + "contact": { + "firstName": "Prénom", + "lastName": "Nom", + "displayName": "Nom d'affichage", + "email": "E-mail", + "phone": "Téléphone", + "mobile": "Mobile", + "company": "Entreprise", + "jobTitle": "Poste", + "department": "Département", + "street": "Rue", + "city": "Ville", + "postalCode": "Code postal", + "country": "Pays", + "website": "Site web", + "birthday": "Anniversaire", + "notes": "Notes", + "tasks": { + "title": "Tâches", + "assigned": "Assignées", + "involved": "Impliqué", + "empty": "Aucune tâche pour ce contact", + "serviceUnavailable": "Service Todo indisponible", + "error": "Échec du chargement des tâches", + "overdue": "En retard", + "dueToday": "Aujourd'hui", + "tomorrow": "Demain", + "showCompleted": "Terminées", + "showMore": "Afficher {count} de plus", + "markComplete": "Marquer comme terminée", + "markIncomplete": "Marquer comme non terminée" + } + }, + "groups": { + "title": "Groupes", + "new": "Nouveau groupe", + "noGroups": "Aucun groupe disponible" + }, + "actions": { + "save": "Enregistrer", + "cancel": "Annuler", + "delete": "Supprimer", + "edit": "Modifier", + "create": "Créer", + "favorite": "Favori", + "unfavorite": "Non favori", + "archive": "Archiver", + "unarchive": "Restaurer" + }, + "messages": { + "saved": "Enregistré", + "deleted": "Supprimé", + "error": "Une erreur est survenue" + }, + "google": { + "loading": "Vérification de la connexion...", + "connect": { + "title": "Se connecter à Google", + "subtitle": "Importez vos contacts directement depuis Google Contacts", + "button": "Se connecter avec Google" + }, + "connected": "Connecté à Google", + "disconnect": "Déconnecter", + "contacts": "Contacts", + "loadMore": "Charger plus" + }, + "filters": { + "title": "Filtres", + "clearAll": "Tout effacer", + "tag": "Tag", + "allTags": "Tous les tags", + "contactInfo": "Info contact", + "contact": { + "all": "Tous les contacts", + "favorites": "Favoris", + "hasPhone": "Avec téléphone", + "hasEmail": "Avec e-mail", + "incomplete": "Incomplets" + }, + "birthdayLabel": "Anniversaire", + "birthday": { + "all": "Tous", + "today": "Aujourd'hui", + "thisWeek": "Cette semaine", + "thisMonth": "Ce mois-ci" + }, + "company": "Entreprise", + "allCompanies": "Toutes les entreprises" + }, + "export": { + "title": "Exporter les contacts", + "button": "Exporter", + "format": "Choisir le format", + "selectedCount": "{count} contacts sélectionnés", + "allContacts": "Tous les contacts seront exportés", + "includeArchived": "Inclure les contacts archivés", + "exporting": "Exportation...", + "success": "Export réussi" + }, + "notes": { + "title": "Notes", + "add": "Ajouter une note", + "addFirst": "Ajoutez votre première note", + "empty": "Aucune note pour le moment", + "placeholder": "Écrire une note...", + "confirmDelete": "Supprimer cette note ?", + "pin": "Épingler la note", + "unpin": "Désépingler la note", + "yesterday": "Hier" + }, + "tags": { + "title": "Tags", + "new": "Nouveau tag", + "edit": "Modifier le tag", + "noTags": "Aucun tag pour le moment", + "createFirst": "Créez votre premier tag pour organiser vos contacts", + "search": "Rechercher des tags...", + "name": "Nom", + "namePlaceholder": "Saisir le nom du tag", + "color": "Couleur", + "preview": "Aperçu", + "contactCount": "{count} contacts", + "confirmDelete": "Êtes-vous sûr de vouloir supprimer \"{name}\" ?", + "noResults": "Aucun tag trouvé", + "noResultsFor": "Aucun résultat pour \"{query}\"", + "tagSingular": "Tag", + "tagPlural": "Tags" + } +} diff --git a/apps/contacts/apps/web/src/lib/i18n/locales/it.json b/apps/contacts/apps/web/src/lib/i18n/locales/it.json new file mode 100644 index 000000000..310d4d4cb --- /dev/null +++ b/apps/contacts/apps/web/src/lib/i18n/locales/it.json @@ -0,0 +1,217 @@ +{ + "app": { + "name": "Contacts" + }, + "common": { + "back": "Indietro", + "cancel": "Annulla", + "loadingMore": "Caricamento..." + }, + "nav": { + "contacts": "Contatti", + "groups": "Gruppi", + "tags": "Tag", + "favorites": "Preferiti", + "archive": "Archivio", + "search": "Cerca", + "settings": "Impostazioni", + "feedback": "Feedback", + "import": "Importa" + }, + "import": { + "title": "Importa contatti", + "subtitle": "Importa contatti da file vCard o CSV", + "tabs": { + "file": "Import da file", + "google": "Google Contatti" + }, + "processing": "Elaborazione del file...", + "importing": "Importazione...", + "downloadTemplate": "Scarica modello CSV", + "dropzone": { + "title": "Trascina il file qui", + "subtitle": "o clicca per selezionare" + }, + "preview": { + "total": "Totale", + "valid": "Validi", + "duplicates": "Duplicati", + "selected": "Selezionati", + "errors": "Errori di analisi", + "duplicateHandling": "Come gestire i duplicati?", + "skip": "Ignora", + "merge": "Unisci", + "create": "Crea comunque", + "contacts": "Contatti da importare", + "selectAll": "Seleziona tutti", + "deselectAll": "Deseleziona tutti", + "duplicateTag": "Duplicato", + "matchesWith": "Corrisponde a", + "importButton": "Importa {count} contatti" + }, + "result": { + "title": "Importazione completata", + "subtitle": "I tuoi contatti sono stati importati con successo", + "imported": "Importati", + "merged": "Uniti", + "skipped": "Ignorati", + "errors": "Errori", + "importMore": "Importa altri", + "done": "Fatto" + } + }, + "contacts": { + "title": "Contatti", + "new": "Nuovo contatto", + "edit": "Modifica", + "delete": "Elimina", + "search": "Cerca contatti...", + "noContacts": "Nessun contatto trovato", + "addFirst": "Aggiungi il tuo primo contatto", + "favorites": "Preferiti", + "archive": "Archivio", + "contact": "Contatto", + "contactsPlural": "Contatti", + "call": "Chiama", + "email": "Invia e-mail", + "favorite": "Segna come preferito", + "unfavorite": "Rimuovi dai preferiti" + }, + "views": { + "list": "Vista elenco", + "grid": "Vista griglia", + "alphabet": "Alfabetico" + }, + "sort": { + "firstName": "Nome", + "lastName": "Cognome" + }, + "contact": { + "firstName": "Nome", + "lastName": "Cognome", + "displayName": "Nome visualizzato", + "email": "E-mail", + "phone": "Telefono", + "mobile": "Cellulare", + "company": "Azienda", + "jobTitle": "Posizione", + "department": "Dipartimento", + "street": "Via", + "city": "Città", + "postalCode": "CAP", + "country": "Paese", + "website": "Sito web", + "birthday": "Compleanno", + "notes": "Note", + "tasks": { + "title": "Attività", + "assigned": "Assegnate", + "involved": "Coinvolto", + "empty": "Nessuna attività per questo contatto", + "serviceUnavailable": "Servizio Todo non disponibile", + "error": "Impossibile caricare le attività", + "overdue": "In ritardo", + "dueToday": "Oggi", + "tomorrow": "Domani", + "showCompleted": "Completate", + "showMore": "Mostra altri {count}", + "markComplete": "Segna come completata", + "markIncomplete": "Segna come non completata" + } + }, + "groups": { + "title": "Gruppi", + "new": "Nuovo gruppo", + "noGroups": "Nessun gruppo disponibile" + }, + "actions": { + "save": "Salva", + "cancel": "Annulla", + "delete": "Elimina", + "edit": "Modifica", + "create": "Crea", + "favorite": "Preferito", + "unfavorite": "Non preferito", + "archive": "Archivia", + "unarchive": "Ripristina" + }, + "messages": { + "saved": "Salvato", + "deleted": "Eliminato", + "error": "Si è verificato un errore" + }, + "google": { + "loading": "Verifica della connessione...", + "connect": { + "title": "Connetti a Google", + "subtitle": "Importa i tuoi contatti direttamente da Google Contatti", + "button": "Connetti con Google" + }, + "connected": "Connesso a Google", + "disconnect": "Disconnetti", + "contacts": "Contatti", + "loadMore": "Carica altri" + }, + "filters": { + "title": "Filtri", + "clearAll": "Cancella tutto", + "tag": "Tag", + "allTags": "Tutti i tag", + "contactInfo": "Info contatto", + "contact": { + "all": "Tutti i contatti", + "favorites": "Preferiti", + "hasPhone": "Con telefono", + "hasEmail": "Con e-mail", + "incomplete": "Incompleti" + }, + "birthdayLabel": "Compleanno", + "birthday": { + "all": "Tutti", + "today": "Oggi", + "thisWeek": "Questa settimana", + "thisMonth": "Questo mese" + }, + "company": "Azienda", + "allCompanies": "Tutte le aziende" + }, + "export": { + "title": "Esporta contatti", + "button": "Esporta", + "format": "Seleziona formato", + "selectedCount": "{count} contatti selezionati", + "allContacts": "Tutti i contatti verranno esportati", + "includeArchived": "Includi contatti archiviati", + "exporting": "Esportazione...", + "success": "Esportazione riuscita" + }, + "notes": { + "title": "Note", + "add": "Aggiungi nota", + "addFirst": "Aggiungi la tua prima nota", + "empty": "Nessuna nota ancora", + "placeholder": "Scrivi una nota...", + "confirmDelete": "Eliminare questa nota?", + "pin": "Fissa nota", + "unpin": "Rimuovi fissaggio", + "yesterday": "Ieri" + }, + "tags": { + "title": "Tag", + "new": "Nuovo tag", + "edit": "Modifica tag", + "noTags": "Nessun tag ancora", + "createFirst": "Crea il tuo primo tag per organizzare i contatti", + "search": "Cerca tag...", + "name": "Nome", + "namePlaceholder": "Inserisci nome del tag", + "color": "Colore", + "preview": "Anteprima", + "contactCount": "{count} contatti", + "confirmDelete": "Sei sicuro di voler eliminare \"{name}\"?", + "noResults": "Nessun tag trovato", + "noResultsFor": "Nessun risultato per \"{query}\"", + "tagSingular": "Tag", + "tagPlural": "Tag" + } +} diff --git a/apps/todo/apps/web/src/lib/i18n/index.ts b/apps/todo/apps/web/src/lib/i18n/index.ts index 69a10dd40..1faf9f9f2 100644 --- a/apps/todo/apps/web/src/lib/i18n/index.ts +++ b/apps/todo/apps/web/src/lib/i18n/index.ts @@ -2,7 +2,7 @@ import { browser } from '$app/environment'; import { init, register, locale, waitLocale } from 'svelte-i18n'; // List of supported locales -export const supportedLocales = ['de', 'en'] as const; +export const supportedLocales = ['de', 'en', 'fr', 'it', 'es'] as const; export type SupportedLocale = (typeof supportedLocales)[number]; // Default locale @@ -11,6 +11,9 @@ const defaultLocale = 'de'; // Register all available locales register('de', () => import('./locales/de.json')); register('en', () => import('./locales/en.json')); +register('fr', () => import('./locales/fr.json')); +register('it', () => import('./locales/it.json')); +register('es', () => import('./locales/es.json')); // Get initial locale from browser or localStorage function getInitialLocale(): SupportedLocale { diff --git a/apps/todo/apps/web/src/lib/i18n/locales/es.json b/apps/todo/apps/web/src/lib/i18n/locales/es.json new file mode 100644 index 000000000..a65dc8cff --- /dev/null +++ b/apps/todo/apps/web/src/lib/i18n/locales/es.json @@ -0,0 +1,104 @@ +{ + "app": { + "name": "Todo", + "loading": "Cargando..." + }, + "nav": { + "inbox": "Bandeja de entrada", + "today": "Hoy", + "upcoming": "Próximas", + "projects": "Proyectos", + "labels": "Etiquetas", + "completed": "Completadas", + "settings": "Configuración", + "feedback": "Comentarios" + }, + "task": { + "title": "Título", + "description": "Descripción", + "dueDate": "Fecha de vencimiento", + "dueTime": "Hora", + "priority": "Prioridad", + "project": "Proyecto", + "labels": "Etiquetas", + "subtasks": "Subtareas", + "reminder": "Recordatorio", + "repeat": "Repetir", + "addTask": "Añadir tarea", + "editTask": "Editar tarea", + "deleteTask": "Eliminar tarea", + "completeTask": "Completar tarea", + "uncompleteTask": "Marcar como no completada", + "noTasks": "Sin tareas", + "noTasksToday": "Sin tareas para hoy", + "noTasksUpcoming": "Sin tareas próximas" + }, + "project": { + "create": "Crear proyecto", + "edit": "Editar proyecto", + "delete": "Eliminar proyecto", + "name": "Nombre", + "color": "Color", + "icon": "Icono", + "archive": "Archivar", + "noProjects": "Sin proyectos" + }, + "label": { + "create": "Crear etiqueta", + "edit": "Editar etiqueta", + "delete": "Eliminar etiqueta", + "name": "Nombre", + "color": "Color", + "noLabels": "Sin etiquetas" + }, + "priority": { + "urgent": "Urgente", + "high": "Alta", + "medium": "Normal", + "low": "Baja" + }, + "repeat": { + "none": "No repetir", + "daily": "Diario", + "weekly": "Semanal", + "monthly": "Mensual", + "yearly": "Anual" + }, + "auth": { + "login": "Iniciar sesión", + "logout": "Cerrar sesión", + "register": "Registrarse", + "email": "Correo electrónico", + "password": "Contraseña", + "forgotPassword": "¿Olvidaste tu contraseña?" + }, + "common": { + "save": "Guardar", + "cancel": "Cancelar", + "delete": "Eliminar", + "edit": "Editar", + "add": "Añadir", + "close": "Cerrar", + "search": "Buscar", + "error": "Error", + "success": "Éxito", + "loading": "Cargando...", + "noResults": "Sin resultados" + }, + "errors": { + "loadTasks": "No se pudieron cargar las tareas", + "createTask": "No se pudo crear la tarea", + "updateTask": "No se pudo actualizar la tarea", + "deleteTask": "No se pudo eliminar la tarea", + "loadProjects": "No se pudieron cargar los proyectos", + "loadLabels": "No se pudieron cargar las etiquetas" + }, + "success": { + "taskCreated": "Tarea creada", + "taskUpdated": "Tarea actualizada", + "taskDeleted": "Tarea eliminada", + "taskCompleted": "Tarea completada", + "projectCreated": "Proyecto creado", + "labelCreated": "Etiqueta creada" + } +} diff --git a/apps/todo/apps/web/src/lib/i18n/locales/fr.json b/apps/todo/apps/web/src/lib/i18n/locales/fr.json new file mode 100644 index 000000000..41fabbe9e --- /dev/null +++ b/apps/todo/apps/web/src/lib/i18n/locales/fr.json @@ -0,0 +1,104 @@ +{ + "app": { + "name": "Todo", + "loading": "Chargement..." + }, + "nav": { + "inbox": "Boîte de réception", + "today": "Aujourd'hui", + "upcoming": "À venir", + "projects": "Projets", + "labels": "Labels", + "completed": "Terminées", + "settings": "Paramètres", + "feedback": "Commentaires" + }, + "task": { + "title": "Titre", + "description": "Description", + "dueDate": "Date d'échéance", + "dueTime": "Heure", + "priority": "Priorité", + "project": "Projet", + "labels": "Labels", + "subtasks": "Sous-tâches", + "reminder": "Rappel", + "repeat": "Répéter", + "addTask": "Ajouter une tâche", + "editTask": "Modifier la tâche", + "deleteTask": "Supprimer la tâche", + "completeTask": "Terminer la tâche", + "uncompleteTask": "Marquer comme non terminée", + "noTasks": "Aucune tâche", + "noTasksToday": "Aucune tâche pour aujourd'hui", + "noTasksUpcoming": "Aucune tâche à venir" + }, + "project": { + "create": "Créer un projet", + "edit": "Modifier le projet", + "delete": "Supprimer le projet", + "name": "Nom", + "color": "Couleur", + "icon": "Icône", + "archive": "Archiver", + "noProjects": "Aucun projet" + }, + "label": { + "create": "Créer un label", + "edit": "Modifier le label", + "delete": "Supprimer le label", + "name": "Nom", + "color": "Couleur", + "noLabels": "Aucun label" + }, + "priority": { + "urgent": "Urgent", + "high": "Haute", + "medium": "Normale", + "low": "Basse" + }, + "repeat": { + "none": "Ne pas répéter", + "daily": "Quotidien", + "weekly": "Hebdomadaire", + "monthly": "Mensuel", + "yearly": "Annuel" + }, + "auth": { + "login": "Connexion", + "logout": "Déconnexion", + "register": "Inscription", + "email": "E-mail", + "password": "Mot de passe", + "forgotPassword": "Mot de passe oublié ?" + }, + "common": { + "save": "Enregistrer", + "cancel": "Annuler", + "delete": "Supprimer", + "edit": "Modifier", + "add": "Ajouter", + "close": "Fermer", + "search": "Rechercher", + "error": "Erreur", + "success": "Succès", + "loading": "Chargement...", + "noResults": "Aucun résultat" + }, + "errors": { + "loadTasks": "Impossible de charger les tâches", + "createTask": "Impossible de créer la tâche", + "updateTask": "Impossible de mettre à jour la tâche", + "deleteTask": "Impossible de supprimer la tâche", + "loadProjects": "Impossible de charger les projets", + "loadLabels": "Impossible de charger les labels" + }, + "success": { + "taskCreated": "Tâche créée", + "taskUpdated": "Tâche mise à jour", + "taskDeleted": "Tâche supprimée", + "taskCompleted": "Tâche terminée", + "projectCreated": "Projet créé", + "labelCreated": "Label créé" + } +} diff --git a/apps/todo/apps/web/src/lib/i18n/locales/it.json b/apps/todo/apps/web/src/lib/i18n/locales/it.json new file mode 100644 index 000000000..5114f9f95 --- /dev/null +++ b/apps/todo/apps/web/src/lib/i18n/locales/it.json @@ -0,0 +1,104 @@ +{ + "app": { + "name": "Todo", + "loading": "Caricamento..." + }, + "nav": { + "inbox": "In arrivo", + "today": "Oggi", + "upcoming": "In programma", + "projects": "Progetti", + "labels": "Etichette", + "completed": "Completate", + "settings": "Impostazioni", + "feedback": "Feedback" + }, + "task": { + "title": "Titolo", + "description": "Descrizione", + "dueDate": "Scadenza", + "dueTime": "Orario", + "priority": "Priorità", + "project": "Progetto", + "labels": "Etichette", + "subtasks": "Sotto-attività", + "reminder": "Promemoria", + "repeat": "Ripeti", + "addTask": "Aggiungi attività", + "editTask": "Modifica attività", + "deleteTask": "Elimina attività", + "completeTask": "Completa attività", + "uncompleteTask": "Segna come non completata", + "noTasks": "Nessuna attività", + "noTasksToday": "Nessuna attività per oggi", + "noTasksUpcoming": "Nessuna attività in programma" + }, + "project": { + "create": "Crea progetto", + "edit": "Modifica progetto", + "delete": "Elimina progetto", + "name": "Nome", + "color": "Colore", + "icon": "Icona", + "archive": "Archivia", + "noProjects": "Nessun progetto" + }, + "label": { + "create": "Crea etichetta", + "edit": "Modifica etichetta", + "delete": "Elimina etichetta", + "name": "Nome", + "color": "Colore", + "noLabels": "Nessuna etichetta" + }, + "priority": { + "urgent": "Urgente", + "high": "Alta", + "medium": "Normale", + "low": "Bassa" + }, + "repeat": { + "none": "Non ripetere", + "daily": "Giornaliero", + "weekly": "Settimanale", + "monthly": "Mensile", + "yearly": "Annuale" + }, + "auth": { + "login": "Accedi", + "logout": "Esci", + "register": "Registrati", + "email": "E-mail", + "password": "Password", + "forgotPassword": "Password dimenticata?" + }, + "common": { + "save": "Salva", + "cancel": "Annulla", + "delete": "Elimina", + "edit": "Modifica", + "add": "Aggiungi", + "close": "Chiudi", + "search": "Cerca", + "error": "Errore", + "success": "Successo", + "loading": "Caricamento...", + "noResults": "Nessun risultato" + }, + "errors": { + "loadTasks": "Impossibile caricare le attività", + "createTask": "Impossibile creare l'attività", + "updateTask": "Impossibile aggiornare l'attività", + "deleteTask": "Impossibile eliminare l'attività", + "loadProjects": "Impossibile caricare i progetti", + "loadLabels": "Impossibile caricare le etichette" + }, + "success": { + "taskCreated": "Attività creata", + "taskUpdated": "Attività aggiornata", + "taskDeleted": "Attività eliminata", + "taskCompleted": "Attività completata", + "projectCreated": "Progetto creato", + "labelCreated": "Etichetta creata" + } +} diff --git a/apps/todo/apps/web/src/routes/+error.svelte b/apps/todo/apps/web/src/routes/+error.svelte new file mode 100644 index 000000000..b060de2f4 --- /dev/null +++ b/apps/todo/apps/web/src/routes/+error.svelte @@ -0,0 +1,9 @@ + + +
+

{$page.status}

+

{$page.error?.message || 'Seite nicht gefunden'}

+ Zurück zur Startseite +