1a7ef09805
Dashboard: - ApexCharts bar chart (income vs fixed costs vs expenses) and donut chart - KPI cards: income, fixed costs, savings rate with configurable goal - Greeting with time-of-day and locale-aware date/time display Authentication & security: - Email-based login (no username), case-insensitive lookup - JWT access/refresh tokens with rotation and blacklist - TOTP 2FA with QR code, backup codes (copy + PDF export) - 2FA recovery via email code - Cloudflare Turnstile CAPTCHA on login and register Email flows: - Email verification on registration (24h token) - Password reset flow (15min token, anti-enumeration) - Brevo SMTP integration with HTML + plaintext email templates - Notification emails: 2FA recovery, password changed, email changed Settings page: - 2FA management (enable/disable, QR, backup codes) - Active sessions list with per-device revoke - Data export: ZIP with 6 PDFs via fpdf2 - Notification preferences (3 toggles) - Danger zone: account deletion with mandatory export + confirmation phrase UI & layout: - Sidebar with collapsible/flyout mode, Angular signal-based dropdowns - Dark mode (class-based), language switcher (DE/FR/IT/EN) - Mobile-responsive layout with touch-friendly targets - Roboto font via @fontsource (GDPR-compliant, no Google CDN) - Pure Tailwind CSS v3 Infrastructure: - Forgejo Actions CI/CD pipeline (auto-deploy on push to main) - Gunicorn + Nginx + PostgreSQL production setup - Rate limiting, HSTS, secure cookies, CSRF protection
405 lines
15 KiB
JSON
405 lines
15 KiB
JSON
{
|
|
"common": {
|
|
"save_changes": "Salva modifiche",
|
|
"cancel": "Annulla",
|
|
"delete": "Elimina",
|
|
"edit": "Modifica",
|
|
"create": "Crea",
|
|
"add": "Aggiungi",
|
|
"close": "Chiudi",
|
|
"save": "Salva",
|
|
"name": "Nome",
|
|
"optional": "opzionale",
|
|
"delete_confirm_title": "Eliminare la voce?",
|
|
"delete_confirm_text": "Questa azione non può essere annullata.",
|
|
"no_accounts_title": "Nessun conto disponibile",
|
|
"no_accounts_text": "Per creare una voce, devi prima configurare un conto.",
|
|
"go_to_accounts": "Vai ai conti"
|
|
},
|
|
"auth": {
|
|
"sign_in": "Accedi",
|
|
"sign_up": "Registrati",
|
|
"signing_in": "Accesso in corso...",
|
|
"creating_account": "Creazione account...",
|
|
"username": "Nome utente",
|
|
"email": "E-mail",
|
|
"password": "Password",
|
|
"confirm_password": "Conferma password",
|
|
"tagline_login": "Accedi al tuo account",
|
|
"tagline_register": "Crea il tuo account",
|
|
"no_account": "Non hai un account?",
|
|
"create_account": "Crea un account",
|
|
"has_account": "Hai già un account?",
|
|
"password_hint": "Almeno 8 caratteri.",
|
|
"username_hint": "Utilizzato come nome visualizzato nell'app.",
|
|
"totp_title": "Autenticazione a due fattori",
|
|
"totp_hint": "Inserisci il codice a 6 cifre dalla tua app di autenticazione.",
|
|
"totp_or_backup": "Oppure inserisci un codice di backup.",
|
|
"totp_no_device": "Non ho il mio dispositivo 2FA",
|
|
"totp_use_backup": "Usa il codice di recupero",
|
|
"totp_no_backup": "Non ho nemmeno un codice di recupero",
|
|
"backup_format_hint": "Formato: XXXXXXXX-XXXXXXXX",
|
|
"recovery_title": "Recupero account",
|
|
"recovery_intro": "Per mantenere il tuo account sicuro, vogliamo assicurarci che tu sia davvero tu. Un codice di conferma verrà inviato alla tua e-mail di recupero registrata.",
|
|
"recovery_send": "Invia codice di conferma",
|
|
"recovery_sent": "Un'e-mail con un codice di conferma è stata appena inviata a:",
|
|
"recovery_spam_hint": "Se non trovi il messaggio nella tua casella di posta, controlla la cartella spam.",
|
|
"recovery_confirm": "Conferma codice",
|
|
"recovery_verifying": "Verifica del link in corso…",
|
|
"recovery_success": "2FA disattivato. Reindirizzamento in corso…",
|
|
"recovery_redirecting": "Reindirizzamento al dashboard…",
|
|
"recovery_error": "Il link non è valido o è scaduto.",
|
|
"keep_signed_in": "Rimani connesso",
|
|
"keep_signed_in_hint": "Consigliato sui dispositivi affidabili.",
|
|
"back_to_login": "Torna al login",
|
|
"errors": {
|
|
"fields_required": "Tutti i campi sono obbligatori.",
|
|
"passwords_mismatch": "Le password non corrispondono.",
|
|
"password_too_short": "La password deve contenere almeno 8 caratteri.",
|
|
"invalid_credentials": "Nome utente o password non validi.",
|
|
"enter_credentials": "Inserisci nome utente e password.",
|
|
"registration_failed": "Registrazione fallita.",
|
|
"invalid_totp": "Codice non valido o scaduto.",
|
|
"captcha_failed": "Verifica di sicurezza fallita. Riprova.",
|
|
"reset_failed": "Link non valido o scaduto.",
|
|
"token_missing": "Nessun token trovato.",
|
|
"verify_failed": "Link di verifica non valido o scaduto."
|
|
},
|
|
"forgot_password": "Password dimenticata?",
|
|
"forgot_password_tagline": "Reimposta password",
|
|
"forgot_password_hint": "Inserisci il tuo indirizzo e-mail. Se esiste un account, ti invieremo un link di reimpostazione.",
|
|
"send_reset_link": "Invia link di reimpostazione",
|
|
"sending": "Invio in corso...",
|
|
"reset_link_sent": "Link inviato",
|
|
"reset_link_sent_hint": "Se esiste un account con questo indirizzo, riceverai un'e-mail. Controlla anche la cartella spam.",
|
|
"reset_password": "Reimposta password",
|
|
"reset_password_tagline": "Imposta nuova password",
|
|
"reset_password_hint": "Inserisci la tua nuova password.",
|
|
"new_password": "Nuova password",
|
|
"resetting": "Reimpostazione in corso...",
|
|
"reset_success": "Password modificata con successo.",
|
|
"verifying": "Verifica dell'indirizzo e-mail in corso...",
|
|
"email_verified": "Indirizzo e-mail verificato.",
|
|
"verify_email_error": "Verifica non riuscita"
|
|
},
|
|
"settings": {
|
|
"subtitle": "Sicurezza e impostazioni dell'account",
|
|
"recovery_email": "E-mail di recupero",
|
|
"recovery_email_hint": "Questa e-mail viene utilizzata per il recupero 2FA. Usa un indirizzo diverso dalla tua e-mail di accesso.",
|
|
"recovery_email_saved": "E-mail salvata.",
|
|
"sessions_title": "Sessioni attive",
|
|
"sessions_hint": "Tutti i dispositivi su cui sei attualmente connesso.",
|
|
"sessions_current": "Sessione corrente",
|
|
"sessions_revoke": "Disconnetti",
|
|
"sessions_revoke_all": "Disconnetti tutte le altre",
|
|
"sessions_loading": "Caricamento sessioni…",
|
|
"export_title": "Esporta dati",
|
|
"export_hint": "Scarica una cartella ZIP con tutti i tuoi dati in formato PDF.",
|
|
"export_btn": "Scarica esportazione",
|
|
"export_loading": "Preparazione esportazione…",
|
|
"notif_title": "Notifiche",
|
|
"notif_hint": "Scegli di cosa vuoi essere informato.",
|
|
"notif_deadlines": "Scadenze imminenti",
|
|
"notif_deadlines_hint": "Promemoria per appuntamenti e scadenze imminenti.",
|
|
"notif_budget_alerts": "Avvisi budget",
|
|
"notif_budget_alerts_hint": "Notifica quando un budget viene superato.",
|
|
"notif_monthly_summary": "Riepilogo mensile",
|
|
"notif_monthly_summary_hint": "Panoramica di entrate e uscite a fine mese.",
|
|
"notif_saved": "Impostazioni salvate.",
|
|
"delete_step1_title": "Esporta prima i tuoi dati",
|
|
"delete_step1_hint": "Scarica i tuoi dati prima di eliminare l'account. Questa azione non può essere annullata.",
|
|
"delete_step1_btn": "Esporta dati",
|
|
"delete_step2_exported": "Esportazione scaricata",
|
|
"delete_password_label": "Conferma la tua password",
|
|
"delete_phrase_label": "Digita per confermare:",
|
|
"delete_wrong_password": "La password non è corretta.",
|
|
"sessions_unknown_device": "Dispositivo sconosciuto"
|
|
},
|
|
"nav": {
|
|
"search_placeholder": "Cerca...",
|
|
"no_results": "Nessun risultato trovato.",
|
|
"notifications": "Notifiche",
|
|
"no_notifications": "Nessuna nuova notifica.",
|
|
"mark_read": "Segna come letto",
|
|
"mark_all_read": "Segna tutto come letto",
|
|
"more_coming_soon": "Altre funzionalità in arrivo",
|
|
"sign_out": "Esci",
|
|
"profile": "Profilo",
|
|
"settings": "Impostazioni",
|
|
"dark_mode": "Modalità scura",
|
|
"light_mode": "Modalità chiara"
|
|
},
|
|
"search": {
|
|
"accounts": "Conti",
|
|
"budgets": "Budget",
|
|
"expenses": "Spese",
|
|
"transactions": "Transazioni",
|
|
"deadlines": "Scadenze"
|
|
},
|
|
"sidebar": {
|
|
"dashboard": "Dashboard",
|
|
"budgets": "Budget",
|
|
"fixed_costs": "Costi fissi",
|
|
"expenses": "Spese",
|
|
"calendar": "Calendario",
|
|
"accounts": "Conti",
|
|
"revenue_accounts": "Conti entrate",
|
|
"transactions": "Transazioni"
|
|
},
|
|
"dashboard": {
|
|
"title": "Dashboard",
|
|
"subtitle": "Panoramica finanziaria",
|
|
"total_income": "Entrate totali",
|
|
"fixed_costs": "Costi fissi",
|
|
"expenses": "Spese",
|
|
"balance": "Saldo",
|
|
"per_month": "CHF / mese",
|
|
"chf_total": "CHF totale",
|
|
"chf_remaining": "CHF rimanenti",
|
|
"income_vs_expenses": "Entrate vs. Spese {{ year }}",
|
|
"fixed_costs_breakdown": "Ripartizione costi fissi",
|
|
"savings_rate": "Tasso di risparmio",
|
|
"of_income": "delle entrate",
|
|
"goal": "Obiettivo di risparmio",
|
|
"goal_hint": "Consigliato: risparmiare almeno il 20% delle entrate.",
|
|
"recent_expenses": "Spese recenti",
|
|
"no_expenses": "Nessuna spesa registrata.",
|
|
"series_income": "Entrate",
|
|
"series_fixed_costs": "Costi fissi",
|
|
"series_expenses": "Spese variabili",
|
|
"view_report": "Visualizza rapporto",
|
|
"greeting_morning": "Buongiorno",
|
|
"greeting_afternoon": "Buon pomeriggio",
|
|
"greeting_evening": "Buona sera",
|
|
"greeting_night": "Buona notte"
|
|
},
|
|
"accounts": {
|
|
"title": "Tutti i conti",
|
|
"add": "Aggiungi conto",
|
|
"col_type": "Tipo",
|
|
"col_balance": "Saldo (CHF)",
|
|
"no_accounts": "Nessun conto ancora.",
|
|
"create_title": "Crea conto",
|
|
"edit_title": "Modifica conto",
|
|
"label_balance": "Saldo (CHF)",
|
|
"label_type": "Tipo di conto",
|
|
"type_asset": "Attivo",
|
|
"type_revenue": "Entrate",
|
|
"placeholder_name": "es. Conto risparmio"
|
|
},
|
|
"budgets": {
|
|
"title": "Costi fissi & Budget",
|
|
"subtitle": "Spese totali: ",
|
|
"add": "Aggiungi",
|
|
"new_entry": "Nuova voce — {{ category }}",
|
|
"edit_entry": "Modifica voce",
|
|
"label_amount": "Importo (CHF)",
|
|
"label_category": "Categoria",
|
|
"label_account": "Conto",
|
|
"label_active": "Attivo",
|
|
"label_suggestions": "Suggerimenti",
|
|
"no_entries": "Nessuna voce in questa categoria.",
|
|
"entries_count": "({{ count }} voci)",
|
|
"placeholder_name": "es. Affitto",
|
|
"categories": {
|
|
"fixed_expenses": "Spese fisse",
|
|
"mobile_internet": "Mobile & Internet",
|
|
"subscriptions": "Abbonamenti",
|
|
"leisure": "Tempo libero",
|
|
"tax_reserves": "Riserve fiscali",
|
|
"insurance": "Assicurazioni",
|
|
"loans": "Prestiti & Crediti"
|
|
}
|
|
},
|
|
"expenses": {
|
|
"title": "Spese",
|
|
"total": "Totale:",
|
|
"add": "Aggiungi spesa",
|
|
"col_date": "Data",
|
|
"col_name": "Nome",
|
|
"col_category": "Categoria",
|
|
"col_account": "Conto",
|
|
"col_amount": "Importo",
|
|
"no_expenses": "Nessuna spesa registrata.",
|
|
"create_title": "Aggiungi spesa",
|
|
"edit_title": "Modifica spesa",
|
|
"label_amount": "Importo (CHF)",
|
|
"label_date": "Data",
|
|
"label_category": "Categoria",
|
|
"label_account": "Conto",
|
|
"label_due_date": "Data di scadenza",
|
|
"label_notes": "Note",
|
|
"placeholder_name": "es. Migros",
|
|
"categories": {
|
|
"groceries": "Spesa alimentare",
|
|
"dining": "Ristoranti",
|
|
"transport": "Trasporti",
|
|
"health": "Salute & Medicina",
|
|
"clothing": "Abbigliamento",
|
|
"electronics": "Elettronica",
|
|
"household": "Casa",
|
|
"entertainment": "Intrattenimento",
|
|
"travel": "Viaggi",
|
|
"other": "Altro"
|
|
}
|
|
},
|
|
"transactions": {
|
|
"title": "Tutte le transazioni",
|
|
"add": "Aggiungi transazione",
|
|
"col_date": "Data",
|
|
"col_description": "Descrizione",
|
|
"col_from": "Da",
|
|
"col_to": "A",
|
|
"col_amount": "Importo",
|
|
"no_transactions": "Nessuna transazione ancora.",
|
|
"create_title": "Crea transazione",
|
|
"edit_title": "Modifica transazione",
|
|
"label_description": "Descrizione",
|
|
"label_amount": "Importo (CHF)",
|
|
"label_date": "Data",
|
|
"label_from": "Conto di origine",
|
|
"label_to": "Conto di destinazione",
|
|
"select_account": "Seleziona conto...",
|
|
"placeholder_description": "es. Affitto gennaio"
|
|
},
|
|
"calendar": {
|
|
"year_view": "Vista annuale",
|
|
"subscribe": "Abbonati",
|
|
"ical_title": "Il tuo URL del feed iCal",
|
|
"ical_desc": "Aggiungi questo URL a qualsiasi app di calendario (Protonmail, Google, Apple, Outlook).",
|
|
"ical_copy": "Copia",
|
|
"ical_copied": "Copiato!",
|
|
"filter_holidays": "Festività",
|
|
"filter_school": "Vacanze scolastiche",
|
|
"filter_invoices": "Fatture",
|
|
"filter_deadlines": "Scadenze",
|
|
"add_deadline": "Aggiungi scadenza",
|
|
"select_type": "Seleziona motivo...",
|
|
"label_title": "Titolo",
|
|
"label_date": "Data",
|
|
"label_type": "Tipo",
|
|
"label_notes": "Note",
|
|
"deadline_types": {
|
|
"tax": "Tasse",
|
|
"insurance": "Assicurazione",
|
|
"invoice": "Fattura",
|
|
"personal": "Personale",
|
|
"other": "Altro"
|
|
},
|
|
"months": {
|
|
"1": "Gennaio",
|
|
"2": "Febbraio",
|
|
"3": "Marzo",
|
|
"4": "Aprile",
|
|
"5": "Maggio",
|
|
"6": "Giugno",
|
|
"7": "Luglio",
|
|
"8": "Agosto",
|
|
"9": "Settembre",
|
|
"10": "Ottobre",
|
|
"11": "Novembre",
|
|
"12": "Dicembre"
|
|
},
|
|
"weekdays": [
|
|
"Lun",
|
|
"Mar",
|
|
"Mer",
|
|
"Gio",
|
|
"Ven",
|
|
"Sab",
|
|
"Dom"
|
|
],
|
|
"no_events": "Nessun evento in questo giorno.",
|
|
"more_events": "+{{ count }} altri",
|
|
"legend_national": "Festa nazionale",
|
|
"legend_cantonal": "Festa cantonale",
|
|
"legend_school": "Vacanze scolastiche",
|
|
"legend_expense": "Data di scadenza",
|
|
"legend_personal": "Scadenza personale"
|
|
},
|
|
"canton_names": {
|
|
"AG": "Argovia",
|
|
"AI": "Appenzello Interno",
|
|
"AR": "Appenzello Esterno",
|
|
"BE": "Berna",
|
|
"BL": "Basilea Campagna",
|
|
"BS": "Basilea Città",
|
|
"FR": "Friburgo",
|
|
"GE": "Ginevra",
|
|
"GL": "Glarona",
|
|
"GR": "Grigioni",
|
|
"JU": "Giura",
|
|
"LU": "Lucerna",
|
|
"NE": "Neuchâtel",
|
|
"NW": "Nidvaldo",
|
|
"OW": "Obvaldo",
|
|
"SG": "San Gallo",
|
|
"SH": "Sciaffusa",
|
|
"SO": "Soletta",
|
|
"SZ": "Svitto",
|
|
"TG": "Turgovia",
|
|
"TI": "Ticino",
|
|
"UR": "Uri",
|
|
"VD": "Vaud",
|
|
"VS": "Vallese",
|
|
"ZG": "Zugo",
|
|
"ZH": "Zurigo"
|
|
},
|
|
"profile": {
|
|
"title": "Profilo",
|
|
"subtitle": "Gestisci le tue informazioni personali e impostazioni",
|
|
"personal_info": "Informazioni personali",
|
|
"profile_photo": "Foto profilo",
|
|
"photo_hint": "Clicca sull'avatar per caricare una foto",
|
|
"fallback_color": "Colore di riserva",
|
|
"first_name": "Nome",
|
|
"last_name": "Cognome",
|
|
"email": "E-mail",
|
|
"canton": "Cantone",
|
|
"language": "Lingua",
|
|
"save_changes": "Salva modifiche",
|
|
"save_success": "Profilo salvato con successo.",
|
|
"change_password": "Cambia password",
|
|
"new_password": "Nuova password",
|
|
"confirm_password": "Conferma password",
|
|
"update_password": "Aggiorna password",
|
|
"password_success": "Password aggiornata con successo.",
|
|
"totp_title": "Autenticazione a due fattori",
|
|
"totp_subtitle": "Proteggi il tuo account con un'app di autenticazione. Consigliato: Proton Pass, Aegis (Android) o Raivo OTP (iOS).",
|
|
"totp_on": "Attivo",
|
|
"totp_off": "Disattivo",
|
|
"totp_enable": "Attiva 2FA",
|
|
"totp_disable": "Disattiva 2FA",
|
|
"totp_scan_hint": "Scansiona il codice QR con la tua app di autenticazione, poi inserisci il codice a 6 cifre.",
|
|
"totp_disable_hint": "Inserisci il codice attuale dalla tua app di autenticazione per disattivare il 2FA.",
|
|
"totp_code_label": "Codice di conferma",
|
|
"totp_confirm": "Conferma e attiva",
|
|
"totp_enabled_success": "2FA attivato con successo.",
|
|
"totp_disabled_success": "Il 2FA è stato disattivato.",
|
|
"totp_invalid_code": "Codice non valido. Riprova.",
|
|
"backup_codes_title": "Salva i tuoi codici di backup",
|
|
"backup_codes_hint": "Questi codici vengono mostrati una sola volta. Conservali in un posto sicuro.",
|
|
"backup_copy": "Copia",
|
|
"backup_copied": "Copiato!",
|
|
"backup_download_pdf": "Scarica come PDF",
|
|
"backup_saved": "Li ho salvati",
|
|
"danger_zone": "Zona pericolosa",
|
|
"danger_text": "Elimina definitivamente il tuo account e tutti i dati associati. Questa azione non può essere annullata.",
|
|
"delete_account": "Elimina account",
|
|
"delete_account_confirm": "Eliminare l'account?",
|
|
"delete_account_text": "Tutti i tuoi dati saranno eliminati definitivamente. Questa azione non può essere annullata.",
|
|
"languages": {
|
|
"de": "Deutsch",
|
|
"fr": "Français",
|
|
"it": "Italiano",
|
|
"en": "English"
|
|
},
|
|
"errors": {
|
|
"password_empty": "La password non può essere vuota.",
|
|
"passwords_mismatch": "Le password non corrispondono.",
|
|
"password_too_short": "La password deve contenere almeno 8 caratteri.",
|
|
"password_failed": "Aggiornamento password fallito."
|
|
}
|
|
}
|
|
}
|