From ba3cc2c5418ff406b1fec79913eb2aecf3e9bc24 Mon Sep 17 00:00:00 2001 From: Samuel Gudi Date: Mon, 11 May 2026 11:03:59 +0200 Subject: [PATCH] feat(i18n): add Italian (it) locale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds complete Italian translation for all ~280 UI strings in static/i18n.js and the login page strings in api/routes.py (_LOGIN_LOCALE). Ordered alphabetically: en → it → ja in both files. Preserves all JS function templates, template literals, and plural forms. (cherry picked from commit c66e04b190e960de2a2902157261a5e407501054) --- api/routes.py | 9 + static/i18n.js | 1090 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1099 insertions(+) diff --git a/api/routes.py b/api/routes.py index 1e8bd106..5d88ea2d 100644 --- a/api/routes.py +++ b/api/routes.py @@ -1944,6 +1944,15 @@ _LOGIN_LOCALE = { # Strings mirror static/i18n.js login_* keys for the corresponding locale. # See issue #1442. When adding a new locale to LOCALES in i18n.js, also add # the matching entry here — tests/test_login_locale_parity.py enforces this. + "it": { + "lang": "it-IT", + "title": "Accedi", + "subtitle": "Inserisci la password per continuare", + "placeholder": "Password", + "btn": "Accedi", + "invalid_pw": "Password non valida", + "conn_failed": "Connessione fallita", + }, "ja": { "lang": "ja-JP", "title": "\u30b5\u30a4\u30f3\u30a4\u30f3", diff --git a/static/i18n.js b/static/i18n.js index 14a6f863..3afecaaf 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -1103,6 +1103,1096 @@ const LOCALES = { checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, }, + it: { + offline_title: 'Connessione persa', + offline_browser_detail: 'Il browser segnala che questo dispositivo è offline.', + offline_network_detail: 'Hermes non è raggiungibile da questo browser al momento.', + offline_autorefresh: 'Aggiornerò automaticamente la pagina quando Hermes sarà di nuovo raggiungibile.', + offline_check_now: 'Verifica ora', + offline_checking: 'Verifica in corso…', + offline_stream_waiting: 'Connessione persa. In attesa di aggiornare…', + _lang: 'it', + _label: 'Italiano', + _speech: 'it-IT', + // boot.js + cancelling: 'Annullamento\u2026', + cancel_failed: 'Annullamento fallito: ', + mic_denied: 'Accesso al microfono negato. Controlla i permessi del browser.', + mic_no_speech: 'Nessuna voce rilevata. Riprova.', + mic_network: 'Riconoscimento vocale non disponibile.', + mic_error: 'Errore input vocale: ', + // Composer voice buttons (#1488 — distinct labels for dictation vs voice mode) + voice_dictate: 'Detta', + voice_dictate_active: 'Interrompi dettatura', + voice_mode_toggle: 'Modalità vocale', + voice_mode_toggle_active: 'Esci dalla modalità vocale', + // Turn-based voice mode (#1333) + voice_listening: 'In ascolto…', + voice_speaking: 'Sto parlando…', + voice_thinking: 'Pensando…', + voice_error: 'Voce non supportata in questo browser', + voice_mode_active: 'Modalità vocale attiva', + voice_mode_off: 'Modalità vocale disattiva', + session_imported: 'Sessione importata', + import_failed: 'Importazione fallita: ', + import_invalid_json: 'JSON non valido', + image_pasted: 'Immagine incollata: ', + // messages.js + edit_message: 'Modifica messaggio', + regenerate: 'Rigenera risposta', + copy: 'Copia', + copied: 'Copiato!', + copy_failed: 'Copia fallita', + + diff_loading: 'Caricamento diff', + diff_error: 'Impossibile caricare il file patch', + diff_too_large: 'File patch troppo grande per la visualizzazione inline', + tree_view: 'Albero', + raw_view: 'Raw', + parse_failed_note: 'parsing fallito', + you: 'Tu', + mcp_servers_title: 'Server MCP', + mcp_servers_desc: 'Visualizza i server MCP configurati in config.yaml.', + mcp_no_servers: 'Nessun server MCP configurato.', + mcp_add_server: '+ Aggiungi Server', + mcp_field_name: 'Nome Server', + mcp_transport_label: 'Tipo Trasporto', + mcp_field_command: 'Comando', + mcp_field_args: 'Argomenti (separati da virgola)', + mcp_field_url: 'URL', + mcp_field_timeout: 'Timeout (secondi)', + mcp_save: 'Salva', + mcp_cancel: 'Annulla', + mcp_name_required: 'Il nome del server è obbligatorio.', + mcp_url_required: "L'URL è obbligatorio per il trasporto HTTP.", + mcp_command_required: 'Il comando è obbligatorio per il trasporto stdio.', + mcp_saved: 'Server MCP salvato.', + mcp_save_failed: 'Salvataggio server MCP fallito.', + mcp_delete_confirm_title: 'Elimina Server MCP', + mcp_delete_confirm_message: 'Eliminare il server MCP "{0}"? Questa azione non può essere annullata.', + mcp_deleted: 'Server MCP eliminato.', + mcp_delete_failed: 'Eliminazione server MCP fallita.', + mcp_load_failed: 'Caricamento server MCP fallito.', + mcp_restart_hint: 'Le modifiche ai server sono in sola lettura qui. Modifica config.yaml e riavvia Hermes per applicare le modifiche.', + mcp_toggle_followup: 'I controlli abilita/disabilita sono rinviati finché la semantica di ricaricamento MCP non sarà esplicita.', + mcp_status_active: 'Attivo', + mcp_status_configured: 'Configurato', + mcp_status_disabled: 'Disabilitato', + mcp_status_invalid_config: 'Configurazione non valida', + mcp_status_unknown: 'Sconosciuto', + mcp_tool_count: '{0} strumenti', + mcp_enabled_yes: 'Abilitato', + mcp_enabled_no: 'Disabilitato', + mcp_tools_title: 'Strumenti MCP', + mcp_tools_desc: 'Cerca strumenti noti tra i server MCP attivi.', + mcp_tools_search_placeholder: 'Cerca strumenti per nome, server o descrizione…', + mcp_tools_no_tools: "Nessuno strumento MCP disponibile dall'inventario runtime attivo.", + mcp_tools_no_matches: 'Nessuno strumento MCP corrisponde alla ricerca.', + mcp_tools_load_failed: 'Caricamento strumenti MCP fallito.', + mcp_tools_schema_empty: 'Nessun parametro schema.', + mcp_tools_runtime_note: "L'inventario strumenti usa solo dati runtime MCP già noti; la WebUI non avvia né interroga i server.", + // PDF preview (#480) + pdf_loading: 'Caricamento PDF {0}…', + pdf_too_large: "PDF troppo grande per l'anteprima inline", + pdf_no_pages: 'Il PDF non ha pagine', + pdf_error: 'Rendering anteprima PDF fallito', + pdf_download: 'Scarica PDF', + // HTML sandbox preview (#482) + html_loading: 'Caricamento anteprima HTML…', + html_too_large: "HTML troppo grande per l'anteprima inline", + html_error: 'Rendering anteprima HTML fallito', + html_open_full: 'Apri pagina intera', + html_sandbox_label: 'Anteprima HTML (sandbox)', + thinking: 'Pensando', + expand_all: 'Espandi tutto', + collapse_all: 'Comprimi tutto', + edit_failed: 'Modifica fallita: ', + regen_failed: 'Rigenerazione fallita: ', + reconnect_active: 'Una risposta è ancora in generazione. Ricaricare quando pronta?', + reconnect_finished: 'Una risposta era in corso quando hai lasciato. I messaggi potrebbero essere aggiornati.', + // approval card + approval_heading: 'Approvazione richiesta', + approval_desc_prefix: 'Comando pericoloso rilevato', + approval_btn_once: 'Consenti una volta', + approval_btn_once_title: 'Consenti questo comando (Invio)', + approval_btn_session: 'Consenti sessione', + approval_btn_session_title: 'Consenti per questa sessione di conversazione', + approval_btn_always: 'Consenti sempre', + approval_btn_always_title: 'Consenti sempre questo tipo di comando', + approval_btn_deny: 'Nega', + approval_btn_deny_title: 'Nega — non eseguire questo comando', + approval_responding: 'Rispondendo\u2026', + clarify_heading: 'Chiarimento necessario', + clarify_hint: "Scegli un'opzione o scrivi la tua risposta qui sotto.", + clarify_other: 'Altro', + clarify_send: 'Invia', + clarify_input_placeholder: 'Scrivi la tua risposta…', + clarify_responding: 'Rispondendo\u2026', + untitled: 'Senza titolo', + n_messages: (n) => n === 1 ? `${n} messaggio` : `${n} messaggi`, + load_older_messages: '↑ Scorri in alto o clicca per caricare i messaggi precedenti', + session_jump_start: 'Inizio', + session_jump_start_label: "Vai all'inizio della sessione", + session_jump_end: 'Fine', + session_jump_end_label: 'Vai alla fine della sessione', + queued_label: 'Inviato dopo la risposta', + queued_count: (n) => n === 1 ? '1 in coda' : `${n} in coda`, + queued_cancel: 'Annulla messaggio in coda', + model_unavailable: ' (non disponibile)', + model_unavailable_title: 'Questo modello non è più nella lista provider attuale', + provider_mismatch_warning: (m,p)=>`"${m}" potrebbe non funzionare con il provider configurato (${p}). Invia comunque, o esegui \`hermes model\` nel terminale per cambiare.`, + provider_mismatch_label: 'Provider non corrispondente', + model_not_found_label: 'Modello non trovato', + model_custom_label: 'ID modello personalizzato', + model_custom_placeholder: 'es. openai/gpt-5.4', + model_search_placeholder: 'Cerca modelli…', + model_search_no_results: 'Nessun modello trovato', + model_group_configured: 'Configurato', + ws_search_placeholder: 'Cerca workspace…', + ws_no_results: 'Nessun workspace trovato', + workspace_new_worktree_conversation: 'Nuova conversazione in worktree', + workspace_new_worktree_conversation_meta: 'Crea un worktree git isolato per questo workspace.', + workspace_worktree_created: 'Conversazione worktree creata', + workspace_worktree_failed: 'Creazione worktree fallita: ', + session_worktree_badge: 'Worktree', + model_scope_advisory: 'Si applica a questa conversazione dal prossimo messaggio.', + model_scope_toast: 'Si applica a questa conversazione dal prossimo messaggio.', + // commands.js + cmd_clear: 'Cancella i messaggi della conversazione', + cmd_compress: 'Comprimi manualmente il contesto della conversazione (uso: /compress [argomento])', + ctx_compress_hint: 'Comprimi il contesto per liberare spazio →', + ctx_compress_action: '⚠ Comprimi ora per liberare contesto', + cmd_compact_alias: 'Alias legacy per /compress', + cmd_model: 'Cambia modello (es. /model gpt-4o)', + cmd_workspace: 'Cambia workspace per nome', + cmd_terminal: 'Apri il terminale del workspace', + cmd_new: 'Avvia una nuova sessione di chat', + cmd_usage: 'Attiva/disattiva visualizzazione uso token', + cmd_theme: 'Cambia aspetto (tema: system/dark/light, skin: default/ares/mono/slate/poseidon/sisyphus/charizard)', + cmd_personality: "Cambia personalità dell'agente", + cmd_skills: 'Elenca le skill Hermes disponibili', + available_commands: 'Comandi disponibili:', + type_slash: 'Digita / per vedere i comandi', + conversation_cleared: 'Conversazione cancellata', + command_label: 'Comando', + context_compaction_label: 'Compattazione contesto', + preserved_task_list_label: 'Lista task preservata', + reference_only_label: 'Solo riferimento', + model_usage: 'Uso: /model ', + no_model_match: 'Nessun modello corrispondente a "', + switched_to: 'Passato a ', + workspace_usage: 'Uso: /workspace ', + no_workspace_match: 'Nessun workspace corrispondente a "', + switched_workspace: 'Passato al workspace: ', + workspace_switch_failed: 'Cambio workspace fallito: ', + new_session: 'Nuova sessione creata', + compressing: 'Richiesta compressione contesto...', + compress_running_label: 'Compressione in corso', + compress_complete_label: 'Compressione completata', + auto_compress_label: 'Compressione automatica', + compress_failed_label: 'Compressione fallita', + focus_label: 'Focus', + token_usage_on: 'Uso token attivo', + token_usage_off: 'Uso token disattivo', + theme_usage: 'Uso: /theme ', + theme_set: 'Tema: ', + no_active_session: 'Nessuna sessione attiva', + cmd_queue: 'Metti in coda un messaggio per il prossimo turno', + cmd_goal: 'Imposta o controlla un obiettivo persistente', + goal_evaluating_progress: 'Valutazione progresso obiettivo…', + goal_working_toward: "Lavorando verso l'obiettivo…", + goal_continuing_toast: "Proseguendo verso l'obiettivo…", + goal_status_none: 'Nessun obiettivo attivo. Impostane uno con /goal .', + goal_status_active: (turns, max_turns, goal) => `⊙ Obiettivo (attivo, ${turns}/${max_turns} turni): ${goal}`, + goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Obiettivo (in pausa, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`, + goal_status_done: (turns, max_turns, goal) => `✓ Obiettivo completato (${turns}/${max_turns}): ${goal}`, + goal_set: (turns, goal) => `⊙ Obiettivo impostato (budget ${turns} turni): ${goal}`, + goal_paused: (goal) => `⏸ Obiettivo in pausa: ${goal}`, + goal_resumed: (goal) => `▶ Obiettivo ripreso: ${goal}`, + goal_cleared: 'Obiettivo rimosso.', + goal_no_goal: 'Nessun obiettivo attivo.', + goal_achieved: (reason) => `✓ Obiettivo raggiunto: ${reason}`, + goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Obiettivo in pausa — ${turns}/${max_turns} turni usati. Usa /goal resume per continuare, o /goal clear per fermarti.`, + goal_continuing: (turns, max_turns, reason) => `↻ Proseguendo verso l'obiettivo (${turns}/${max_turns}): ${reason}`, + cmd_interrupt: 'Annulla il turno corrente e invia un nuovo messaggio', + cmd_steer: "Inietta una correzione a metà turno senza interrompere l'agente", + cmd_queue_no_msg: 'Uso: /queue ', + cmd_queue_not_busy: 'Nessun task attivo — invia normalmente', + cmd_queue_confirm: 'Messaggio in coda', + cmd_interrupt_no_msg: 'Uso: /interrupt ', + cmd_interrupt_confirm: 'Interrotto — invio nuovo messaggio', + cmd_steer_no_msg: 'Uso: /steer ', + cmd_steer_fallback: 'Steer non disponibile — messaggio in coda per il prossimo turno', + cmd_steer_delivered: "Steer consegnato — l'agente lo vedrà al prossimo risultato strumento", + steer_leftover_queued: 'Steer in coda per il prossimo turno', + busy_steer_fallback: 'Steer non disponibile — messaggio in coda per il prossimo turno', + busy_interrupt_confirm: 'Interrotto — invio nuovo messaggio', + settings_label_busy_input_mode: 'Modalità input occupato', + settings_desc_busy_input_mode: "Controlla cosa succede quando invii un messaggio mentre l'agente è in esecuzione. Coda attende; Interrompi annulla e ricomincia; Steer inietta una correzione a metà turno senza interrompere (fallback a coda se agente o stream non disponibili).", + settings_busy_input_mode_queue: 'Accoda follow-up', + settings_busy_input_mode_interrupt: 'Interrompi turno corrente', + settings_busy_input_mode_steer: 'Steer (correzione a metà turno)', + + slash_skill_badge:'Skill', + slash_skill_desc:'Invoca questa skill', + cmd_stop:'Ferma la risposta corrente', + cmd_title:'Mostra o imposta il titolo della sessione', + cmd_retry:"Reinvia l'ultimo messaggio", + cmd_undo:"Rimuovi l'ultimo scambio", + cmd_btw:'Fai una domanda laterale (effimera)', + cmd_btw_usage:'/btw — fai una domanda laterale usando il contesto della sessione', + cmd_background:'Esegui un prompt in background', + cmd_background_usage:'/background — esegui in parallelo senza bloccare', + cmd_branch:'Dirama questa conversazione in una nuova sessione', + cmd_branch_usage:'/branch [nome] — dirama la conversazione (opzionalmente con un nome)', + branch_forked:'Diramata in nuova sessione', + branch_failed:'Diramazione fallita: ', + fork_from_here:'Dirama da qui', + forked_from:'Diramata da', + subagent_children:'Sessioni subagente', + btw_asking:'Domanda laterale in corso...', + btw_label:'Domanda laterale — non nella cronologia', + btw_done:'Domanda laterale risposta', + btw_no_answer:'Nessuna risposta ricevuta.', + btw_failed:'Domanda laterale fallita: ', + bg_running:'In esecuzione in background...', + bg_complete:'Task in background completato', + bg_label:'Risultato background:', + bg_no_answer:'(nessuna risposta)', + bg_failed:'Task in background fallito: ', + undo_exchange:'Annulla ultimo scambio', + cmd_status:'Mostra info sessione', + cmd_voice:'Attiva/disattiva input microfono', + stream_stopped:'Risposta fermata.', + no_active_task:'Nessun task attivo da fermare.', + cancel_unavailable:'Annullamento non disponibile.', + retry_failed:'Riprova fallito: ', + undo_failed:'Annulla fallito: ', + undid_n_messages:'Rimossi', + undid_messages_suffix:'messaggio/i.', + status_heading:'Stato Sessione', + status_session_id:'ID Sessione', + status_title:'Titolo', + status_model:'Modello', + status_provider:'Provider', + status_workspace:'Workspace', + status_personality:'Personalità', + status_messages:'Messaggi', + status_agent_running:'Agente in esecuzione', + status_profile: 'Profilo', + status_hermes_home: 'Home Hermes', + status_started: 'Avviato', + status_updated: 'Aggiornato', + status_tokens: 'Token', + status_ephemeral: 'Snapshot effimero — non salvato nella cronologia trascrizioni.', + status_no_tokens: 'Nessun token usato', + status_unknown: 'Sconosciuto', + status_yes:'Sì', + status_no:'No', + status_load_failed:'Caricamento stato fallito: ', + title_current:'Titolo attuale', + title_change_hint:'Usa `/title ` per rinominare.', + title_set:'Titolo impostato a', + cmd_webui_only_session:'Questo comando non è disponibile per sessioni importate da CLI.', + cmd_voice_use_mic:'Clicca il pulsante microfono nel compositore.', + usage_heading:'Uso Token', + usage_default_model:'predefinito', + usage_unknown:'sconosciuto', + usage_input_tokens:'Token input', + usage_output_tokens:'Token output', + usage_total:'Token totali', + usage_estimated_cost:'Costo stimato', + usage_settings_tip:'Nota: le stime dei costi sono approssimative.', + usage_load_failed:'Caricamento uso fallito: ', + usage_personality_none:'nessuna', + // Session toolsets (#493) + session_toolsets:'Strumenti Sessione', + session_toolsets_desc:'Limita gli strumenti disponibili per questa sessione (vuoto = usa config globale)', + session_toolsets_global:'Globale (predefinito)', + session_toolsets_custom:'Personalizzato', + session_toolsets_placeholder:'strumento1, strumento2, …', + session_toolsets_apply:'Applica', + session_toolsets_clear:'Pulisci (usa globale)', + session_toolsets_applied:'Strumenti aggiornati', + session_toolsets_cleared:'Strumenti azzerati — uso config globale', + session_toolsets_failed:'Aggiornamento strumenti fallito: ', + untitled:'Senza titolo', + no_personalities: 'Nessuna personalità trovata (aggiungile in ~/.hermes/personalities/)', + available_personalities: 'Personalità disponibili:', + personality_switch_hint: '\\n\\nUsa `/personality ` per cambiare, o `/personality none` per rimuovere.', + personalities_load_failed: 'Caricamento personalità fallito', + personality_cleared: 'Personalità rimossa', + personality_set: 'Personalità: ', + failed_colon: 'Fallito: ', + // ui.js + no_workspace: 'Nessun workspace', + terminal_open_title: 'Apri terminale workspace', + terminal_no_workspace_title: 'Seleziona un workspace per aprire il terminale', + terminal_title: 'Terminale', + terminal_clear: 'Pulisci', + terminal_copy_output: 'Copia output', + terminal_restart: 'Riavvia', + terminal_collapse: 'Comprimi', + terminal_expand: 'Espandi', + terminal_close: 'Chiudi', + terminal_input_placeholder: 'Esegui un comando...', + terminal_start_failed: 'Avvio terminale fallito: ', + terminal_input_failed: 'Input terminale fallito: ', + terminal_copy_failed: 'Copia fallita: ', + terminal_error: 'Errore terminale', + workspace_empty_no_path: 'Nessun workspace selezionato. Imposta un workspace in Impostazioni \u2192 Workspace per esplorare i file.', + workspace_empty_dir: 'Questo workspace è vuoto.', + workspace_show_hidden_files: 'Mostra file nascosti', + workspace_show_hidden_files_desc: "Includi .DS_Store, .git, node_modules e altri file nascosti/di sistema nell'albero dei file.", + workspace_hidden_files_visible: 'nascosti visibili', + workspace_hidden_files_visible_title: 'I file nascosti sono visibili — clicca per opzioni', + workspace_options: 'Opzioni workspace', + dialog_confirm_title: 'Conferma azione', + dialog_prompt_title: 'Inserisci un valore', + dialog_confirm_btn: 'Conferma', + // workspace.js + unsaved_confirm: "Hai modifiche non salvate nell'anteprima. Scartare e navigare?", + discard: 'Scarta', + save: 'Salva', + edit: 'Modifica', + clear: 'Pulisci', + create: 'Crea', + remove: 'Rimuovi', + save_title: 'Salva modifiche', + edit_title: 'Modifica questo file', + saved: 'Salvato', + save_failed: 'Salvataggio fallito: ', + image_load_failed: "Impossibile caricare l'immagine", + file_open_failed: 'Impossibile aprire il file', + downloading: (name) => `Scaricamento ${name}\u2026`, + double_click_rename: 'Doppio clic per rinominare', + renamed_to: 'Rinominato in ', + rename_failed: 'Rinomina fallita: ', + delete_title: 'Elimina', + delete_confirm: (name) => `Eliminare ${name}?`, + delete_dir_confirm: (name) => `Eliminare la cartella "${name}" e tutto il suo contenuto?`, + rename_title: 'Rinomina', + rename_prompt: 'Nuovo nome:', + deleted: 'Eliminato ', + delete_failed: 'Eliminazione fallita: ', + reveal_in_finder: 'Mostra nel File Manager', + reveal_failed: 'Mostra fallito: ', + copy_file_path: 'Copia percorso file', + path_copied: 'Percorso file copiato negli appunti', + path_copy_failed: 'Copia percorso fallita: ', + session_rename: 'Rinomina conversazione', + session_rename_desc: 'Modifica il titolo di questa conversazione', + new_file_prompt: 'Nuovo nome file (es. note.md):', + project_name_prompt: 'Nome progetto:', + created: 'Creato ', + create_failed: 'Creazione fallita: ', + new_folder_prompt: 'Nuovo nome cartella:', + folder_created: 'Cartella creata ', + folder_create_failed: 'Creazione cartella fallita: ', + workspace_auto_create_folder: 'Crea cartella se non esiste', + folder_add_as_space_btn: 'Aggiungi come Spazio', + folder_add_as_space_msg: 'Aggiungere questa cartella come nuovo spazio nella lista workspace?', + folder_add_as_space_title: 'Aggiungere come Spazio?', + remove_title: 'Rimuovi', + empty_dir: '(vuota)', + upload_failed: 'Upload fallito: ', + upload_too_large: (maxMb, fileMb) => `File troppo grande (${fileMb} MB). La dimensione massima è ${maxMb} MB.`, + all_uploads_failed: (n) => `Tutti gli ${n} upload sono falliti`, + archive_extracted: (n, c) => `Estratti ${n} file da ${c} archivio/i`, + session_pin: 'Fissa conversazione', + session_unpin: 'Sblocca conversazione', + session_pin_desc: 'Mantieni questa conversazione in cima', + session_unpin_desc: 'Rimuovi dalle fissate', + session_pin_failed: 'Fissa fallito: ', + session_move_project: 'Sposta nel progetto', + session_move_project_desc_has: 'Cambia il progetto per questa conversazione', + session_move_project_desc_none: 'Assegna un progetto a questa conversazione', + session_archive: 'Archivia conversazione', + session_restore: 'Ripristina conversazione', + session_archive_desc: 'Nascondi questa conversazione fino a mostrare archiviate', + session_restore_desc: 'Riporta questa conversazione nella lista principale', + session_archived: 'Sessione archiviata', + session_restored: 'Sessione ripristinata', + session_archive_failed: 'Archiviazione fallita: ', + session_duplicate: 'Duplica conversazione', + session_duplicate_desc: 'Crea una copia con lo stesso workspace e modello', + session_duplicated: 'Sessione duplicata', + session_duplicate_failed: 'Duplicazione fallita: ', + session_stop_response: 'Ferma risposta', + session_stop_response_desc: 'Annulla la risposta in corso per questa conversazione', + session_delete: 'Elimina conversazione', + session_delete_desc: 'Rimuovi permanentemente questa conversazione', + session_select_mode: 'Seleziona', + session_select_mode_desc: 'Seleziona conversazioni per gestione in blocco', + session_select_all: 'Seleziona tutto', + session_deselect_all: 'Deseleziona tutto', + session_selected_count: '{0} selezionate', + session_batch_archive: 'Archivia', + session_batch_delete: 'Elimina', + session_batch_move: 'Sposta nel progetto', + session_batch_delete_confirm: 'Eliminare {0} conversazioni?', + session_batch_archive_confirm: 'Archiviare {0} conversazioni?', + session_no_selection: 'Nessuna conversazione selezionata', + // settings panel + settings_heading_title: 'Pannello di Controllo', + settings_heading_subtitle: 'Preferenze, strumenti di conversazione e controlli di sistema.', + settings_section_conversation_title: 'Conversazione', + settings_section_appearance_title: 'Aspetto', + settings_section_appearance_meta: 'Tema, colori accento e stile visivo.', + settings_section_preferences_title: 'Preferenze', + settings_section_preferences_meta: 'Predefiniti e comportamento UI per Hermes Web UI.', + settings_section_system_title: 'Sistema', + settings_section_system_meta: 'Versione istanza e controlli di accesso.', + settings_check_now: 'Verifica ora', + settings_checking: 'Verifica in corso\u2026', + settings_up_to_date: 'Aggiornato \u2713', + settings_updates_available: '{count} aggiornamento/i disponibile/i', + settings_updates_disabled: 'Verifica aggiornamenti disabilitata', + settings_update_check_failed: 'Verifica aggiornamenti fallita', + settings_label_workspace_panel_open: 'Mantieni il pannello workspace aperto per impostazione predefinita', + settings_desc_workspace_panel_open: 'Se abilitato, il pannello workspace/esplora file si apre automaticamente a ogni nuova sessione. Puoi comunque chiuderlo manualmente in qualsiasi momento.', + settings_label_session_jump_buttons: 'Mostra pulsanti salto sessione', + settings_desc_session_jump_buttons: 'Mostra pulsanti fluttuanti Inizio e Fine durante la lettura di sessioni lunghe.', + + settings_label_session_endless_scroll: 'Carica messaggi precedenti scorrendo in alto', + + settings_desc_session_endless_scroll: 'Se abilitato, i messaggi precedenti si caricano automaticamente scorrendo in alto. Se disabilitato, usa il pulsante messaggi precedenti.', + open_in_browser: 'Apri nel browser', + settings_dropdown_conversation: 'Conversazione', + settings_dropdown_appearance: 'Aspetto', + settings_dropdown_preferences: 'Preferenze', + settings_dropdown_providers: 'Provider', + settings_dropdown_system: 'Sistema', + settings_tab_conversation: 'Conversazione', + settings_tab_appearance: 'Aspetto', + settings_tab_preferences: 'Preferenze', + settings_tab_system: 'Sistema', + settings_title: 'Impostazioni', + settings_save_btn: 'Salva Impostazioni', + settings_label_model: 'Modello Predefinito', + settings_desc_model: 'Usato per le nuove conversazioni. Le conversazioni esistenti mantengono il modello selezionato.', + settings_label_send_key: 'Tasto Invio', + settings_label_theme: 'Tema', + settings_label_skin: 'Skin', + settings_label_font_size: 'Dimensione font', + font_size_small: 'Piccolo', + font_size_default: 'Predefinito', + font_size_large: 'Grande', + settings_autosave_saving: 'Salvataggio…', + settings_autosave_saved: 'Salvato', + settings_autosave_failed: 'Salvataggio fallito', + settings_autosave_retry: 'Riprova', + settings_label_language: 'Lingua', + settings_label_token_usage: 'Mostra uso token', + settings_label_sidebar_density: 'Densità sidebar', + cmd_reasoning: 'Mostra/nascondi ragionamento, imposta livello sforzo o controlla stato attuale', + settings_label_external_sessions: 'Mostra sessioni non-WebUI', + settings_label_sync_insights: 'Sincronizza con insights', + settings_label_check_updates: 'Verifica aggiornamenti', + settings_label_bot_name: 'Nome Assistente', + settings_label_password: 'Password di Accesso', + settings_saved: 'Impostazioni salvate', + settings_save_failed: 'Salvataggio fallito: ', + settings_load_failed: 'Caricamento impostazioni fallito: ', + settings_saved_pw: 'Impostazioni salvate — protezione password abilitata e questo browser rimane autenticato', + settings_saved_pw_updated: 'Impostazioni salvate — password aggiornata', + // login page (used server-side via /api/i18n/login endpoint) + login_title: 'Accedi', + login_subtitle: 'Inserisci la password per continuare', + login_placeholder: 'Password', + login_btn: 'Accedi', + login_invalid_pw: 'Password non valida', + login_conn_failed: 'Connessione fallita', + dialog_confirm_title: 'Conferma azione', + dialog_prompt_title: 'Inserisci un valore', + dialog_confirm_btn: 'Conferma', + discard: 'Scarta', + clear: 'Pulisci', + create: 'Crea', + remove: 'Rimuovi', + project_name_prompt: 'Nome progetto:', + // Sidebar & Tabs + tab_chat: 'Chat', + tab_tasks: 'Task', + tab_skills: 'Skill', + tab_memory: 'Memoria', + tab_workspaces: 'Spazi', + tab_profiles: 'Profili', + tab_kanban: 'Kanban', + kanban_board: 'Bacheca', + kanban_visible_tasks: '{0} task visibili', + kanban_search_tasks: 'Cerca task', + kanban_all_assignees: 'Tutti gli assegnatari', + kanban_all_tenants: 'Tutti i tenant', + kanban_include_archived: 'Includi archiviati', + kanban_no_matching_tasks: 'Nessun task corrispondente', + kanban_no_data: 'Nessun dato Kanban', + kanban_work_queue_hint: 'Questa è la coda di lavoro di Hermes Agent. Crea o classifica un task, assegnalo, spostalo in Pronto, poi lascia che il dispatcher lo reclami.', + kanban_unavailable: 'Kanban non disponibile', + kanban_read_only: 'Vista sola lettura', + kanban_empty: 'Vuoto', + kanban_task: 'Task', + kanban_no_description: 'Nessuna descrizione', + kanban_refresh: 'Aggiorna', + kanban_status_triage: 'Triage', + kanban_status_todo: 'Da fare', + kanban_status_ready: 'Pronto', + kanban_status_running: 'In esecuzione', + kanban_status_blocked: 'Bloccato', + kanban_status_done: 'Completato', + kanban_comments_count: 'Commenti ({0})', + kanban_events_count: 'Eventi ({0})', + kanban_links: 'Link', + kanban_parents: 'Genitori', + kanban_children: 'Figli', + kanban_runs_count: 'Esecuzioni ({0})', + kanban_no_comments: 'Nessun commento', + kanban_no_events: 'Nessun evento', + kanban_no_runs: 'Nessuna esecuzione', + kanban_title: 'Titolo', + kanban_description: 'Descrizione', + kanban_description_placeholder: 'Opzionale — cosa deve succedere, criteri di accettazione, link', + kanban_status: 'Stato', + kanban_assignee: 'Assegnatario', + kanban_assignee_placeholder: 'Opzionale — lascia vuoto per qualsiasi worker', + kanban_tenant: 'Tenant', + kanban_tenant_placeholder: 'Opzionale — slug progetto o team', + kanban_priority: 'Priorità', + kanban_priority_hint: 'I numeri più alti vengono eseguiti prima. Predefinito 0.', + kanban_title_required: 'Il titolo è obbligatorio.', + kanban_new_task: 'Nuovo task', + kanban_edit_task: 'Modifica task', + kanban_status_original_hint: 'Stato effettivo: {0}. Questa finestra supporta solo modifiche Triage/Da fare/Pronto.', + kanban_run_dispatcher: 'Avvia dispatcher', + kanban_run_dispatcher_confirm: 'Questo reclamerà i task Pronti su questa bacheca e avvierà sottoprocessi worker (uno per task, fino a 8 per clic). Continuare?', + kanban_assignee_profiles_label: 'Profili Hermes', + kanban_assignee_other_label: 'Altro (canali CLI / profili rimossi)', + kanban_assignee_unassigned: '— Non assegnato (non verrà eseguito automaticamente) —', + kanban_ready_needs_assignee: 'Hai scelto Non assegnato + Pronto. Il dispatcher salterà questo task. Invia di nuovo per confermare, o scegli un profilo.', + kanban_dispatch_preview_prefix: 'Anteprima:', + kanban_dispatch_run_prefix: 'Smistato:', + kanban_dispatch_spawned: 'avviato', + kanban_dispatch_promoted: 'promosso', + kanban_dispatch_reclaimed: 'reclamato', + kanban_dispatch_skipped_unassigned: 'saltato (nessun assegnatario)', + kanban_dispatch_skipped_nonspawnable: 'saltato (profilo sconosciuto)', + kanban_dispatch_auto_blocked: 'auto-bloccato', + kanban_dispatch_timed_out: 'scaduto', + kanban_dispatch_crashed: 'crash', + kanban_add_comment: 'Aggiungi commento', + kanban_only_mine: 'Solo miei', + kanban_bulk_action: 'Azione in blocco', + kanban_nudge_dispatcher: 'Anteprima dispatcher', + kanban_stats: 'Statistiche', + kanban_worker_log: 'Log worker', + kanban_block: 'Blocca', + kanban_unblock: 'Sblocca', + kanban_back_to_board: 'Torna alla bacheca', + kanban_lanes_by_profile: 'Corsie per profilo', + kanban_new_board: 'Nuova bacheca…', + kanban_rename_board: 'Rinomina bacheca attuale…', + kanban_archive_board: 'Archivia bacheca attuale…', + kanban_archive_board_confirm: 'Archiviare la bacheca "{name}"? I task rimangono su disco e la bacheca può essere ripristinata da kanban/boards/_archived/.', + kanban_board_archived: 'Bacheca archiviata', + kanban_board_name: 'Nome', + kanban_board_slug: 'Slug (minuscole, trattini)', + kanban_board_description: 'Descrizione (opzionale)', + kanban_board_icon: 'Icona (emoji, opzionale)', + kanban_board_color: 'Colore (opzionale)', + kanban_board_name_required: 'Il nome è obbligatorio', + kanban_board_slug_required: 'Lo slug è obbligatorio', + kanban_card_complete: 'completato', + kanban_card_archive: 'archivia', + kanban_unassigned: 'non assegnato', + kanban_status_archived: 'Archiviato', + tab_todos: 'Todos', + tab_insights: 'Insights', + tab_dashboard: 'Dashboard Hermes', + dashboard_loopback_warning: 'La dashboard è solo loopback sul server. Naviga dal server stesso o riavvialo con --host 0.0.0.0 (non sicuro).', + tab_logs: 'Log', + tab_settings: 'Impostazioni', + new_conversation: 'Nuova conversazione', + filter_conversations: 'Filtra conversazioni...', + session_time_unknown: 'Sconosciuto', + session_time_minutes_ago: (n) => `${n}m`, + session_time_hours_ago: (n) => `${n}h`, + session_time_days_ago: (n) => `${n}g`, + session_time_last_week: '1sett', + session_time_bucket_today: 'Oggi', + session_time_bucket_yesterday: 'Ieri', + session_time_bucket_this_week: 'Questa settimana', + session_time_bucket_last_week: 'Settimana scorsa', + session_time_bucket_older: 'Precedenti', + scheduled_jobs: 'Job pianificati', + new_job: 'Nuovo job', + loading: 'Caricamento...', + search_skills: 'Cerca skill...', + new_skill: 'Nuova skill', + personal_memory: 'Memoria personale', + current_task_list: 'Lista task corrente', + // Logs + logs_title: 'Log', + logs_file: 'File', + logs_tail: 'Coda', + logs_auto_refresh: 'Aggiornamento automatico (5s)', + logs_wrap: 'A capo automatico', + logs_copy_all: 'Copia tutto', + logs_empty: 'Nessuna riga di log.', + logs_loading: 'Caricamento log…', + logs_load_failed: 'Caricamento log fallito', + logs_status_idle: 'Scegli un file di log per vedere le righe recenti.', + logs_no_mtime: 'non ancora scritto', + logs_truncated_hint: 'Visualizzazione della coda di un file di log grande; i byte precedenti sono stati saltati per contenere la memoria.', + logs_copied: 'Log copiati', + + // Insights + insights_title: 'Analitiche di Utilizzo', + insights_sessions: 'Sessioni', + insights_messages: 'Messaggi', + insights_tokens: 'Token', + insights_cost: 'Costo Stimato', + insights_no_cost: 'N/D', + insights_models: 'Modelli', + insights_activity_by_day: 'Attività per Giorno', + insights_activity_by_hour: 'Attività per Ora', + insights_peak_hour: 'Picco: {hour}', + insights_token_breakdown: 'Ripartizione Token', + insights_input_tokens: 'Input', + insights_output_tokens: 'Output', + insights_total: 'Totale', + insights_daily_tokens: 'Token Giornalieri', + insights_model_name: 'Modello', + insights_model_sessions: 'Sessioni', + insights_model_tokens: 'Token', + insights_model_cost: 'Costo', + insights_model_share: 'Quota', + insights_no_usage_data: 'Nessun dato di utilizzo', + insights_footer: 'Dati mostrati dagli ultimi {days} giorni', + workspace_desc: 'Aggiungi e cambia workspace per le tue sessioni.', + session_meta_messages: (n) => `${n} msg`, + session_meta_children: (n) => `${n} figli${n === 1 ? 'o' : ''}`, + session_meta_segments: (n) => `${n} segment${n === 1 ? 'o' : 'i'}`, + session_lineage_segment_untitled: 'Segmento senza titolo', + session_lineage_segment_open: 'Apri segmento genealogia', + new_profile: 'Nuovo profilo', + transcript: 'Trascrizione', + download_transcript: 'Scarica come Markdown', + import: 'Importa', + // Settings detail + settings_label_sound: 'Suono notifica', + settings_desc_sound: 'Riproduci un suono quando l\'assistente termina una risposta.', + // TTS (#499) + tts_listen: 'Ascolta', + tts_not_supported: 'Sintesi vocale non supportata in questo browser.', + settings_label_tts: 'Sintesi vocale per le risposte', + settings_desc_tts: 'Mostra un pulsante altoparlante su ogni messaggio dell\'assistente per leggerlo ad alta voce usando la sintesi vocale del browser.', + settings_label_tts_auto_read: 'Leggi automaticamente le risposte ad alta voce', + settings_desc_tts_auto_read: 'Leggi automaticamente ogni nuova risposta dell\'assistente quando termina. In pausa quando inizi a scrivere.', + // Composer voice-mode pref (#1488) + settings_label_voice_mode: 'Pulsante modalità vocale a mani libere', + settings_desc_voice_mode: 'Mostra il pulsante modalità vocale (forma d\'onda audio) accanto al microfono di dettatura. Ti permette di parlare naturalmente — Hermes invia automaticamente dopo una pausa e legge le risposte ad alta voce. Richiede un browser che supporti sia il riconoscimento vocale che la sintesi vocale.', + settings_label_tts_voice: 'Voce', + settings_desc_tts_voice: 'Voce preferita. Popolata dalle voci disponibili nel browser.', + settings_label_tts_rate: 'Velocità voce', + settings_label_tts_pitch: 'Tono voce', + settings_label_notifications: 'Notifiche browser', + settings_desc_notifications: 'Mostra una notifica di sistema quando una risposta termina mentre l\'app è in background.', + settings_desc_token_usage: 'Mostra il conteggio token input/output sotto ogni risposta dell\'assistente. Attivabile anche con /usage.', + settings_label_api_redact: 'Oscura dati sensibili nelle risposte API', + settings_desc_api_redact: 'Gli utenti self-hosted possono disabilitare per trasparenza (sconsigliato per istanze condivise).', + settings_sidebar_density_compact: 'Compatta', + settings_sidebar_density_detailed: 'Dettagliata', + settings_desc_sidebar_density: 'Controlla quanti metadati mostra la lista sessioni nella sidebar sinistra.', + settings_label_auto_title_refresh: 'Aggiornamento adattivo titolo', + settings_auto_title_refresh_off: 'Off', + settings_auto_title_refresh_5: 'Ogni 5 scambi', + settings_auto_title_refresh_10: 'Ogni 10 scambi', + settings_auto_title_refresh_20: 'Ogni 20 scambi', + settings_desc_auto_title_refresh: 'Rigenera automaticamente il titolo della sessione in base all\'ultimo scambio, mantenendolo pertinente mentre la conversazione evolve. Richiede un modello LLM per la generazione titoli.', + settings_desc_external_sessions: 'Mostra conversazioni da CLI, Telegram, Discord, Slack e altri canali nella lista sessioni. Clicca per importare e continuare.', + settings_desc_sync_insights: 'Rispecchia l\'uso token WebUI su state.db così hermes /insights include i dati delle sessioni browser. Disattivato per impostazione predefinita.', + settings_desc_check_updates: 'Mostra un banner quando sono disponibili versioni più recenti della WebUI o dell\'Agente. Esegue un git fetch in background periodicamente.', + settings_desc_bot_name: 'Nome visualizzato per l\'assistente in tutta l\'interfaccia. Predefinito: Hermes.', + settings_desc_password: 'Inserisci una nuova password per impostarla o cambiarla. Lascia vuoto per mantenere l\'impostazione attuale.', + password_placeholder: 'Inserisci nuova password…', + password_env_var_locked: 'La variabile d\'ambiente HERMES_WEBUI_PASSWORD è attualmente impostata e ha la precedenza. Rimuovila e riavvia il server per gestire la password da qui.', + password_env_var_locked_placeholder: 'Bloccato: variabile d\'ambiente HERMES_WEBUI_PASSWORD impostata', + disable_auth: 'Disabilita Auth', + sign_out: 'Esci', + // Providers panel + providers_tab_title: 'Provider', + providers_section_title: 'Provider', + providers_section_meta: 'Gestisci le chiavi API per i provider AI. Le modifiche hanno effetto immediato.', + providers_status_configured: 'Chiave API configurata', + providers_status_not_configured: 'Nessuna chiave API', + providers_status_oauth: 'OAuth', + providers_status_api_key: 'Chiave API', + providers_status_not_configured_label: 'Non configurato', + providers_oauth_hint: 'Autenticato via OAuth. Nessuna chiave API necessaria.', + providers_oauth_config_yaml_hint: 'Token configurato via config.yaml. Per aggiornare, modifica la sezione providers in config.yaml o esegui hermes auth.', + providers_oauth_not_configured_hint: 'Non autenticato. Esegui hermes auth nel terminale per configurare questo provider.', + providers_save: 'Salva', + providers_remove: 'Rimuovi', + providers_saving: 'Salvataggio…', + providers_removing: 'Rimozione…', + providers_enter_key: 'Inserisci una chiave API', + providers_empty: 'Nessun provider configurabile trovato.', + providers_key_updated: 'Chiave API salvata', + providers_key_removed: 'Chiave API rimossa', + providers_key_placeholder_new: 'sk-...', + providers_key_placeholder_replace: 'Inserisci nuova chiave da sostituire…', + cancel: 'Annulla', + create_job: 'Crea job', + save_skill: 'Salva skill', + editing: 'Modifica in corso', + // Empty state + empty_title: 'Cosa posso fare per te?', + empty_subtitle: 'Chiedi qualsiasi cosa, esegui comandi, esplora file o gestisci i tuoi task pianificati.', + suggest_files: 'Quali file ci sono in questo workspace?', + suggest_schedule: 'Cosa ho in programma oggi?', + suggest_plan: 'Aiutami a pianificare un piccolo progetto.', + // onboarding + onboarding_badge: 'PRIMO AVVIO', + onboarding_title: 'Benvenuto in Hermes Web UI', + onboarding_lead: 'Una configurazione guidata rapida verificherà Hermes, salverà una configurazione provider reale, sceglierà un workspace e un modello e opzionalmente proteggerà l\'app con una password.', + onboarding_back: 'Indietro', + onboarding_continue: 'Continua', + onboarding_skip: 'Salta configurazione', + onboarding_skipped: 'Configurazione saltata — uso configurazione esistente.', + onboarding_open: 'Apri Hermes', + onboarding_step_system_title: 'Verifica sistema', + onboarding_step_system_desc: 'Verifica Hermes Agent e visibilità configurazione.', + onboarding_step_setup_title: 'Configurazione provider', + onboarding_step_setup_desc: 'Salva la configurazione minima provider Hermes.', + onboarding_step_workspace_title: 'Workspace + modello', + onboarding_step_workspace_desc: 'Scegli le impostazioni predefinite per nuove sessioni e chat.', + onboarding_step_password_title: 'Password opzionale', + onboarding_step_password_desc: 'Proteggi la Web UI prima di condividerla.', + onboarding_step_finish_title: 'Fine', + onboarding_step_finish_desc: 'Rivedi e accedi all\'app.', + onboarding_notice_system_ready: 'Hermes Agent sembra raggiungibile dalla Web UI.', + onboarding_notice_system_unavailable: 'Hermes Agent non è ancora completamente disponibile. Bootstrap può installarlo, ma la configurazione provider potrebbe richiedere un terminale.', + onboarding_check_agent: 'Hermes Agent', + onboarding_check_agent_ready: 'Rilevato e importabile', + onboarding_check_agent_missing: 'Mancante o parzialmente importabile', + onboarding_check_password: 'Password', + onboarding_check_password_enabled: 'Già abilitata', + onboarding_check_password_disabled: 'Non ancora abilitata', + onboarding_check_provider: 'Configurazione provider', + onboarding_check_provider_ready: 'Pronto per chattare', + onboarding_check_provider_partial: 'Salvata ma incompleta', + onboarding_check_provider_pending: 'Necessita verifica', + onboarding_config_file: 'File config:', + onboarding_env_file: 'File .env:', + onboarding_unknown: 'Sconosciuto', + onboarding_current_provider: 'Configurazione attuale:', + onboarding_missing_imports: 'Import mancanti:', + onboarding_notice_setup_required: 'Scegli un percorso provider semplice qui. I flussi OAuth avanzati rimangono nella CLI di Hermes per ora.', + onboarding_notice_setup_already_ready: 'Una configurazione provider Hermes funzionante è già stata rilevata. Puoi mantenerla o sostituirla qui.', + onboarding_oauth_provider_ready_title: 'Provider già autenticato', + onboarding_oauth_provider_ready_body: 'Questa istanza è configurata per usare un provider OAuth ({provider}) impostato tramite la CLI di Hermes. Nessuna chiave API necessaria — clicca Continua per finire.', + onboarding_oauth_provider_not_ready_title: 'Provider OAuth non ancora autenticato', + onboarding_oauth_provider_not_ready_body: 'Questa istanza è configurata per usare {provider}, che usa OAuth invece di una chiave API. Esegui hermes auth o hermes model in un terminale per autenticarti, poi ricarica la Web UI.', + onboarding_oauth_switch_hint: 'Oppure scegli un provider diverso qui sotto per passare a una configurazione con chiave API:', + oauth_login_codex: 'Accedi con Codex (ChatGPT)', + oauth_codex_step1: 'Passo 1: Visita questo URL e inserisci il codice', + oauth_codex_step2: 'Passo 2: Inserisci questo codice nella pagina', + oauth_codex_polling: 'In attesa di autorizzazione...', + oauth_codex_success: 'Accesso Codex OAuth riuscito!', + oauth_codex_error: 'Accesso OAuth fallito', + oauth_codex_expired: 'Codice scaduto, riprova', + onboarding_notice_workspace: 'Questi valori usano le stesse API di impostazioni dell\'app normale.', + onboarding_workspace_label: 'Workspace', + onboarding_workspace_or_path: 'Oppure inserisci un percorso workspace', + onboarding_workspace_placeholder: '/home/tu/workspace', + onboarding_provider_label: 'Modalità configurazione', + onboarding_quick_setup_badge: 'configurazione rapida', + provider_category_easy_start: 'Avvio facile', + provider_category_self_hosted: 'Open / self-hosted', + provider_category_specialized: 'Specializzato', + onboarding_api_key_label: 'Chiave API', + onboarding_api_key_placeholder: 'Lascia vuoto per mantenere una chiave salvata esistente', + onboarding_api_key_label_optional: 'Chiave API (opzionale)', + onboarding_api_key_placeholder_optional: 'Lascia vuoto per server senza chiave', + onboarding_api_key_help_keyless: 'La maggior parte delle installazioni LM Studio / Ollama / vLLM funzionano senza chiave — lascia vuoto se il tuo server non richiede autenticazione. Usa il pulsante Test connessione per verificare.', + onboarding_api_key_help_prefix: 'Salvato come segreto nel tuo file .env di Hermes usando', + onboarding_base_url_label: 'URL Base', + onboarding_base_url_placeholder: 'https://tuo-endpoint.example/v1', + onboarding_base_url_help: 'Usa questo per router compatibili OpenAI, server self-hosted, LiteLLM, Ollama, LM Studio, vLLM o endpoint simili.', + onboarding_model_label: 'Modello predefinito', + onboarding_workspace_help: 'Scegli il modello che Hermes userà per le nuove chat dopo la configurazione.', + onboarding_custom_model_placeholder: 'nome-tuo-modello', + onboarding_custom_model_help: 'Per endpoint personalizzati, inserisci l\'ID esatto del modello che il tuo server si aspetta.', + onboarding_notice_password_enabled: 'Una password è già configurata. Inseriscine una nuova solo se vuoi sostituirla.', + onboarding_notice_password_recommended: 'Opzionale ma consigliato se esporrai l\'interfaccia oltre localhost.', + onboarding_password_label: 'Password (opzionale)', + onboarding_password_placeholder: 'Lascia vuoto per saltare', + onboarding_password_help: 'Le password sono salvate tramite le API impostazioni esistenti e hashate lato server.', + onboarding_notice_finish: 'Puoi riaprire le Impostazioni più tardi per modificare tutto questo.', + onboarding_not_set: 'Non impostato', + onboarding_password_will_enable: 'Sarà abilitata', + onboarding_password_will_replace: 'Sarà sostituita', + onboarding_password_keep_existing: 'Mantieni password attuale', + onboarding_password_remains_disabled: 'Rimarrà disabilitata', + onboarding_password_skipped: 'Saltata per ora', + onboarding_finish_help: 'Completare salva onboarding_completed nelle impostazioni e ti porta nell\'app normale.', + onboarding_error_choose_workspace: 'Scegli un workspace prima di continuare.', + onboarding_error_choose_model: 'Scegli un modello prima di continuare.', + onboarding_error_provider_required: 'Scegli una modalità di configurazione prima di continuare.', + onboarding_error_base_url_required: 'L\'URL Base è obbligatorio per endpoint personalizzati.', + onboarding_probe_test_button: 'Test connessione', + onboarding_probe_probing: 'Test connessione in corso…', + onboarding_probe_ok: 'Connesso. {n} modello/i disponibile/i.', + onboarding_probe_error_generic: 'Impossibile raggiungere l\'URL base configurato.', + onboarding_probe_error_invalid_url: 'L\'URL base deve iniziare con http:// o https://.', + onboarding_probe_error_dns: 'Impossibile risolvere l\'host. Controlla l\'URL o usa l\'indirizzo IP dell\'host.', + onboarding_probe_error_connect_refused: 'Connessione rifiutata — il server potrebbe non essere in esecuzione su quell\'indirizzo. Da dentro Docker, prova l\'IP host invece di localhost.', + onboarding_probe_error_timeout: 'L\'endpoint non ha risposto in tempo. Verifica che il server sia in esecuzione e che l\'URL sia corretto.', + onboarding_probe_error_http_4xx: 'L\'endpoint ha restituito un errore client. Controlla l\'autenticazione e il percorso URL (tipicamente termina in /v1).', + onboarding_probe_error_http_5xx: 'L\'endpoint ha restituito un errore server. Controlla i log del server LM Studio / Ollama.', + onboarding_probe_error_parse: 'L\'endpoint non ha restituito una lista modelli nel formato atteso. Verifica che l\'URL punti alla root API compatibile OpenAI.', + onboarding_probe_error_unreachable: 'Impossibile raggiungere l\'URL base configurato.', + onboarding_error_probe_failed: 'Impossibile validare l\'URL base configurato.', + onboarding_error_workspace_required: 'Il workspace è obbligatorio.', + onboarding_error_model_required: 'Il modello è obbligatorio.', + onboarding_complete: 'Configurazione completata', + + // panel/runtime i18n + error_prefix: 'Errore: ', + not_available: 'N/D', + never: 'mai', + add: 'Aggiungi', + add_failed: 'Aggiunta fallita: ', + remove_failed: 'Rimozione fallita: ', + switch_failed: 'Cambio fallito: ', + name_required: 'Il nome è obbligatorio', + content_required: 'Il contenuto è obbligatorio', + view: 'Visualizza', + dismiss: 'Ignora', + disable: 'Disabilita', + cron_no_jobs: 'Nessun job pianificato trovato.', + cron_status_off: 'spento', + cron_status_paused: 'in pausa', + cron_status_error: 'errore', + cron_status_active: 'attivo', + cron_status_running: 'in esecuzione\u2026', + cron_status_needs_attention: 'richiede attenzione', + cron_attention_desc: 'Questo job ricorrente non ha una prossima esecuzione. Lo scheduler potrebbe non essere riuscito a calcolare la prossima esecuzione.', + cron_attention_croniter_hint: 'Il runtime Gateway potrebbe non avere il pacchetto croniter. Riavvia il Gateway con supporto cron, poi riprendi questo job.', + cron_attention_resume: 'Riprendi e ricalcola', + cron_jobs_project: 'Job Pianificati', + cron_attention_run_once: 'Esegui una volta ora', + cron_attention_copy_diagnostics: 'Copia diagnostica', + cron_diagnostics_copied: 'Diagnostica copiata', + cron_next: 'Prossimo', + cron_last: 'Ultimo', + cron_run_now: 'Esegui ora', + cron_pause: 'Pausa', + cron_resume: 'Riprendi', + cron_job_name_placeholder: 'Nome job', + cron_schedule_placeholder: 'Pianificazione', + cron_prompt_placeholder: 'Prompt', + cron_last_output: 'Ultimo output', + cron_all_runs: 'Tutte le esecuzioni', + cron_hide_runs: 'Nascondi esecuzioni', + cron_no_runs_yet: '(nessuna esecuzione)', + cron_schedule_required_example: 'La pianificazione è obbligatoria (es. "0 9 * * *" o "every 1h")', + cron_schedule_required: 'La pianificazione è obbligatoria', + cron_prompt_required: 'Il prompt è obbligatorio', + cron_job_created: 'Job creato', + cron_duplicate: 'Duplica', + cron_duplicated: 'Job duplicato (in pausa)', + cron_job_triggered: 'Job avviato', + cron_job_paused: 'Job in pausa', + cron_job_resumed: 'Job ripreso', + cron_job_updated: 'Job aggiornato', + cron_delete_confirm_title: 'Elimina job pianificato', + cron_delete_confirm_message: 'Questa azione non può essere annullata.', + cron_job_deleted: 'Job eliminato', + cron_completion_status: (name, status) => `Cron "${name}" ${status}`, + status_failed: 'fallito', + status_completed: 'completato', + todos_no_active: 'Nessuna lista task attiva in questa sessione.', + clear_conversation_title: 'Cancella conversazione', + clear_conversation_message: 'Cancellare tutti i messaggi? Questa azione non può essere annullata.', + clear_failed: 'Cancellazione fallita: ', + skills_no_match: 'Nessuna skill corrispondente.', + linked_files: 'File Collegati', + skill_load_failed: 'Impossibile caricare la skill: ', + skill_file_load_failed: 'Impossibile caricare il file: ', + skill_name_required: 'Il nome della skill è obbligatorio', + skill_updated: 'Skill aggiornata', + skill_created: 'Skill creata', + skill_deleted: 'Skill eliminata', + skill_delete_confirm: 'Eliminare la skill "{0}"?', + skills_empty_title: 'Seleziona una skill', + skills_empty_sub: 'Scegli una skill dalla sidebar per vederne i contenuti, o creane una nuova.', + skills_edit: 'Modifica', + skills_delete: 'Elimina', + skills_back_to: 'Torna a {0}', + tasks_empty_title: 'Seleziona un job pianificato', + tasks_empty_sub: 'Scegli un job dalla sidebar per vederne dettagli ed esecuzioni, o creane uno nuovo.', + workspaces_empty_title: 'Seleziona uno spazio', + workspaces_empty_sub: 'Scegli uno spazio dalla sidebar per vederne file e impostazioni, o aggiungine uno nuovo.', + profiles_empty_title: 'Seleziona un profilo', + profiles_empty_sub: 'Scegli un profilo agente dalla sidebar per vedere e modificare le sue impostazioni, o creane uno nuovo.', + memory_notes_label: 'memoria (note)', + memory_saved: 'Memoria salvata', + my_notes: 'Le Mie Note', + user_profile: 'Profilo Utente', + no_notes_yet: 'Ancora nessuna nota.', + no_profile_yet: 'Ancora nessun profilo.', + workspace_choose_path: 'Scegli percorso workspace', + workspace_choose_path_meta: 'Aggiungi un percorso validato e cambia questa conversazione', + workspace_manage: 'Gestisci workspace', + workspace_manage_meta: 'Apri il pannello Spazi', + workspace_use_title: 'Usa nella sessione corrente', + workspace_use: 'Usa', + workspace_add_path_placeholder: 'Aggiungi percorso workspace (es. /home/utente/mio-progetto)', + workspace_paths_validated_hint: 'I percorsi sono validati come directory esistenti prima del salvataggio.', + + workspace_drag_hint: 'Trascina per riordinare', + workspace_reorder_failed: 'Riordino fallito', + workspace_added: 'Workspace aggiunto', + workspace_renamed: 'Workspace rinominato', + workspace_remove_confirm_title: 'Rimuovi workspace', + workspace_remove_confirm_message: (path) => `Rimuovere "${path}"?`, + workspace_removed: 'Workspace rimosso', + workspace_switch_prompt_title: 'Cambia workspace', + workspace_switch_prompt_message: 'Inserisci un percorso workspace assoluto da aggiungere e a cui passare questa conversazione.', + workspace_switch_prompt_confirm: 'Cambia', + workspace_switch_prompt_placeholder: '/Users/tu/progetto', + workspace_not_added: 'Workspace non aggiunto', + workspace_already_saved: 'Workspace già salvato — sceglilo dalla lista', + workspace_busy_switch: 'Impossibile cambiare workspace mentre l\'agente è in esecuzione', + discard_file_edits_title: 'Scartare le modifiche ai file?', + discard_file_edits_message: 'Cambiare workspace scarterà le modifiche non salvate nell\'anteprima.', + workspace_switched_to: (name) => `Passato a ${name}`, + profiles_no_profiles: 'Nessun profilo trovato.', + profile_api_keys_configured: 'Chiavi API configurate', + profile_gateway_running: 'Gateway in esecuzione', + profile_gateway_stopped: 'Gateway fermo', + profile_active: 'ATTIVO', + profile_no_configuration: 'Nessuna configurazione', + profile_skill_count: (count) => `${count} skill`, + profile_use: 'Usa', + profile_switch_title: 'Passa a questo profilo', + profile_delete_title: 'Elimina questo profilo', + profile_default_label: '(predefinito)', + profile_name_placeholder: 'Nome profilo (minuscole, a-z 0-9 trattini)', + profile_clone_label: 'Clona config dal profilo attivo', + profile_base_url_placeholder: 'Base URL (opzionale, es. http://localhost:11434)', + profile_api_key_placeholder: 'Chiave API (opzionale)', + manage_profiles: 'Gestisci profili', + profiles_load_failed: 'Caricamento profili fallito', + profile_switched_new_conversation: (name) => `Passato al profilo: ${name} — nuova conversazione avviata`, + profile_switched: (name) => `Passato al profilo: ${name}`, + profile_name_rule: 'Solo lettere minuscole, numeri, trattini, underscore', + profile_base_url_rule: 'L\'URL Base deve iniziare con http:// o https://', + profile_created: (name) => `Profilo creato: ${name}`, + profile_delete_confirm_title: (name) => `Eliminare il profilo "${name}"?`, + profile_delete_confirm_message: 'Tutte le sessioni, configurazioni, skill e memoria per questo profilo saranno eliminate permanentemente. Questa azione non può essere annullata.', + profile_deleted: (name) => `Profilo eliminato: ${name}`, + active_conversation_none: 'Nessuna conversazione attiva selezionata.', + active_conversation_meta: (title, count) => `${title} · ${count} messaggi${count === 1 ? 'o' : ''}`, + settings_unsaved_changes: 'Hai modifiche non salvate.', + sign_out_failed: 'Disconnessione fallita: ', + disable_auth_confirm_title: 'Disabilita protezione password', + disable_auth_confirm_message: 'Chiunque potrà accedere a questa istanza.', + auth_disabled: 'Auth disabilitata — protezione password rimossa', + disable_auth_failed: 'Disabilitazione auth fallita: ', + bg_error_single: (title) => `"${title}" ha incontrato un errore`, + bg_error_multi: (count) => `${count} sessioni hanno incontrato un errore`, + // skill form + skill_name: 'Nome', + skill_category: 'Categoria', + skill_category_placeholder: 'Opzionale, es. devops', + skill_content: 'Contenuto SKILL.md', + skill_content_placeholder: 'Frontmatter YAML + corpo markdown', + skill_rename_not_supported: 'Rinominare una skill non è supportato. Crea una nuova skill ed elimina la vecchia per rinominare.', + skill_metadata: 'Metadati', + // cron form + cron_name_label: 'Nome', + cron_name_placeholder: 'Opzionale', + cron_schedule_label: 'Pianificazione', + cron_schedule_hint: 'Usa \'every 1h\' o un\'espressione cron per job ricorrenti. Durate semplici come \'30m\' vengono eseguite una volta sola.', + cron_schedule_once_warning: 'Forme di durata come \'30m\' vengono eseguite una volta e rimosse dopo l\'esecuzione. Usa \'every 30m\' per mantenere un job ricorrente.', + cron_prompt_label: 'Prompt', + cron_deliver_label: 'Recapita output a', + cron_deliver_local: 'Locale (solo salva output)', + cron_profile_label: 'Profilo', + cron_profile_server_default: 'predefinito server', + cron_profile_server_default_hint: 'Usa il profilo predefinito del server WebUI a runtime. I job esistenti senza profilo mantengono questo comportamento legacy.', + cron_skills_label: 'Skill', + cron_skills_placeholder: 'Aggiungi skill (opzionale)…', + cron_skills_edit_hint: 'La lista skill non è modificabile dopo la creazione.', + // workspace form + workspace_name_label: 'Nome', + workspace_name_placeholder: 'Nome descrittivo opzionale', + workspace_path_label: 'Percorso', + workspace_path_required: 'Il percorso è obbligatorio', + workspace_path_readonly: 'Il percorso non può essere cambiato. Solo rinomina.', + workspace_new_title: 'Nuovo spazio', + // profile form + profile_name_label: 'Nome', + profile_base_url_label: 'URL Base', + profile_api_key_label: 'Chiave API', + cmd_yolo: 'Attiva/disattiva modalità YOLO (salta approvazioni)', + yolo_no_session: 'Nessuna sessione attiva', + yolo_enabled: '⚡ Modalità YOLO ON — approvazioni saltate questa sessione', + yolo_disabled: 'Modalità YOLO OFF', + yolo_pill_label: 'YOLO', + yolo_pill_title_active: 'Modalità YOLO attiva — clicca per disabilitare', + approval_skip_all: '⚡ Salta tutto questa sessione', + approval_skip_all_title: 'Salta tutte le richieste di approvazione per questa sessione', + // composer action tooltips + composer_send: 'Invia messaggio', + composer_queue: 'Accoda messaggio', + composer_interrupt: 'Interrompi e invia', + composer_steer: 'Correggi risposta in corso', + composer_stop: 'Ferma generazione', + composer_disabled_clarify: 'Rispondi alla richiesta di chiarimento', + composer_disabled_compression: 'In attesa del completamento della compressione', + composer_disabled_empty: 'Scrivi un messaggio da inviare', + composer_mobile_workspace: 'Workspace', + composer_mobile_model: 'Modello', + composer_mobile_reasoning: 'Ragionamento', + composer_mobile_context: 'Contesto', + media_audio_label: 'Audio', + media_svg_label: 'Diagramma', + media_video_label: 'Video', + csv_loading: 'Caricamento CSV', + csv_too_large: 'File CSV troppo grande per il rendering inline', + csv_no_data: 'Il file CSV ha dati insufficienti per il rendering come tabella', + csv_error: 'Caricamento file CSV fallito', + csv_header_note: 'Prima riga mostrata come intestazione tabella', + excalidraw_loading: 'Caricamento diagramma', + excalidraw_too_large: 'File Excalidraw troppo grande per il rendering inline', + excalidraw_invalid: 'Formato file Excalidraw non valido', + excalidraw_error: 'Caricamento file Excalidraw fallito', + excalidraw_label: 'Diagramma', + excalidraw_download: 'Scarica', + excalidraw_empty: 'Diagramma vuoto', + excalidraw_render_error: 'Rendering diagramma fallito', + excalidraw_simplified: 'Anteprima SVG semplificata — non identica al canvas Excalidraw', + // ── Checkpoints / Rollback ── + checkpoint_title: 'Checkpoint', + checkpoint_empty: 'Nessun checkpoint trovato per questo workspace.', + checkpoint_loading: 'Caricamento checkpoint…', + checkpoint_error: 'Caricamento checkpoint fallito', + checkpoint_date: 'Data', + checkpoint_message: 'Messaggio', + checkpoint_files: 'File', + checkpoint_view_diff: 'Vedi diff', + checkpoint_restore: 'Ripristina', + checkpoint_restore_confirm_title: 'Ripristinare checkpoint?', + checkpoint_restore_confirm_message: (ckpt) => `Ripristinare il workspace al checkpoint "${ckpt}"? Questo sovrascriverà i file con le versioni salvate. I file aggiunti dopo questo checkpoint non saranno eliminati.`, + checkpoint_restored: 'Checkpoint ripristinato', + checkpoint_diff_title: 'Modifiche nel checkpoint', + checkpoint_diff_no_changes: 'Nessuna differenza trovata tra questo checkpoint e il workspace attuale.', + checkpoint_diff_files_changed: (n) => `${n} file modificat${n === 1 ? 'o' : 'i'}`, + }, + ja: { offline_title: '接続が切断されました', offline_browser_detail: 'ブラウザはこのデバイスがオフラインだと報告しています。',