{
  "docs": {
    "gettingStarted": {
      "hero": {
        "badge": "Per Iniziare",
        "title": "Documentazione",
        "subtitle": "Tutto ciò che serve per costruire app web reattive con No.JS"
      },
      "introduction": {
        "title": "Introduzione",
        "text": "No.JS è un framework reattivo HTML-first. Costruisci applicazioni web dinamiche e data-driven usando solo attributi HTML — nessun build step, nessun DOM virtuale, nessun JSX.",
        "callout": "Zero dipendenze · Funziona su tutti i browser moderni · Nessun build step richiesto"
      },
      "installation": {
        "title": "Installazione",
        "cdnSubtitle": "CDN (consigliato)",
        "selfHostedSubtitle": "Auto-ospitato",
        "selfHostedText": "Scarica dist/iife/no.js e includilo con un tag <script>. È un singolo file.",
        "npmSubtitle": "npm / ESM",
        "npmText": "Con npm, devi chiamare NoJS.init() manualmente dopo che il DOM è pronto. Lo script CDN lo fa automaticamente."
      },
      "quickStart": {
        "title": "Avvio Rapido",
        "text": "Crea un file index.html: includi lo script, aggiungi qualche attributo e il gioco è fatto. Nessun app.mount(), nessun createApp(), nessun NgModule. Funziona e basta."
      },
      "howItWorks": {
        "title": "Come Funziona",
        "text": "Al DOMContentLoaded, No.JS attraversa il DOM cercando elementi con attributi noti. Ogni attributo corrisponde a una direttiva eseguita per priorità.",
        "card1Title": "1. Analisi",
        "card1Desc": "Attraversa il DOM cercando elementi con attributi noti.",
        "card2Title": "2. Risoluzione",
        "card2Desc": "Ogni attributo corrisponde a una direttiva eseguita per priorità (prima il recupero dati, poi i condizionali, poi il rendering).",
        "card3Title": "3. Reazione",
        "card3Desc": "Tutti i dati vivono in contesti reattivi (basati su Proxy). Quando i dati cambiano, ogni elemento collegato si aggiorna automaticamente.",
        "card4Title": "4. Ambito",
        "card4Desc": "I contesti ereditano dagli elementi padre, come lo scoping lessicale. Un bind dentro un ciclo each può accedere sia all'elemento del ciclo che ai dati degli antenati."
      },
      "coreConcepts": {
        "title": "Concetti Fondamentali",
        "reactiveContextSubtitle": "Contesto Reattivo",
        "reactiveContextText": "Ogni elemento può avere un contesto — un oggetto dati reattivo. I contesti vengono creati da state, get, store, ecc. Gli elementi figli ereditano automaticamente il contesto del padre.",
        "directivePrioritySubtitle": "Priorità delle Direttive",
        "tableCol1": "Priorità",
        "tableCol2": "Direttive",
        "tableCol3": "Descrizione",
        "tableRow1": "Inizializza lo stato locale/globale",
        "tableRow4": "Strutturale (aggiunge/rimuove DOM)",
        "tableRow5": "Rendering (aggiorna il DOM esistente)",
        "tableRow7": "Effetti collaterali",
        "expressionSubtitle": "Sintassi delle Espressioni",
        "expressionText": "La maggior parte dei valori delle direttive accetta espressioni JavaScript valutate rispetto al contesto corrente:",
        "tableRow1b": "Recuperare dati, error boundaries, namespace i18n",
        "tableRow2b": "Valori derivati e watcher di effetti collaterali",
        "tableRow5b": "Riferimenti agli elementi",
        "tableRow15": "Configurazione drag and drop (Ora in NoJS Elements)"
      }
    },
    "cheatsheet": {
      "hero": {
        "badge": "Riferimento API",
        "title": "Cheatsheet delle Direttive",
        "subtitle": "Riferimento completo di ogni direttiva No.JS"
      },
      "data": {
        "title": "Dati",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "base": "Imposta l'URL base dell'API per i discendenti",
        "get": "Recupera i dati (GET)",
        "post": "Invia dati (POST)",
        "put": "Aggiorna i dati (PUT)",
        "patch": "Aggiornamento parziale (PATCH)",
        "delete": "Elimina i dati (DELETE)",
        "as": "Nome per i dati recuperati nel contesto",
        "body": "Corpo della richiesta",
        "headers": "Header della richiesta",
        "params": "Parametri della query",
        "cached": "Cache delle risposte (memory/local/session)",
        "into": "Scrive la risposta in uno store globale con nome",
        "debounce": "Debounce sui refetch degli URL reattivi (ms)",
        "retry": "Override per elemento del numero di tentativi",
        "refresh": "Intervallo di polling in ms",
        "success": "ID del template da mostrare in caso di successo",
        "then": "Espressione da eseguire in caso di successo",
        "redirect": "Percorso verso cui navigare dopo il successo",
        "confirm": "Messaggio di conferma prima della richiesta",
        "skeleton": "Mostrare/nascondere un placeholder durante il caricamento",
        "retryDelay": "Ritardo tra i tentativi in ms"
      },
      "state": {
        "title": "Stato",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "state": "Crea uno stato locale reattivo",
        "store": "Definisce/accede a uno store globale",
        "computed": "Valore derivato reattivo",
        "watch": "Reagisce ai cambiamenti di valore",
        "persist": "Attributo della direttiva state — persiste lo stato nello storage",
        "model": "Binding bidirezionale per gli input",
        "persistKey": "Chiave di archiviazione per la persistenza",
        "persistFields": "Campi separati da virgola da persistere",
        "persistSchema": "Validare le chiavi ripristinate rispetto allo stato iniziale"
      },
      "rendering": {
        "title": "Renderizzazione",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "bind": "Imposta il contenuto testuale",
        "bindHtml": "Imposta innerHTML (sanitizzato)",
        "bindStar": "Collega qualsiasi attributo",
        "if": "Rendering condizionale",
        "elseIf": "Condizionale concatenato",
        "then": "Template per il vero",
        "else": "Template per il falso",
        "show": "Alterna la visibilità (CSS)",
        "hide": "Inverso di show",
        "switch": "Rendering switch/case",
        "case": "Corrispondenza caso",
        "default": "Caso predefinito"
      },
      "loops": {
        "title": "Cicli",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "foreach": "Direttiva di ciclo primaria",
        "each": "Alias di foreach",
        "for": "Alias di foreach",
        "from": "Array sorgente (DEPRECATED — usa la sintassi \"item in array\")",
        "template": "Template da clonare",
        "index": "Nome della variabile indice",
        "key": "Chiave univoca per il diffing",
        "filter": "Espressione di filtro",
        "sort": "Proprietà di ordinamento (solo nome, senza prefisso della variabile elemento)",
        "limit": "Numero massimo di elementi",
        "offset": "Salta elementi"
      },
      "events": {
        "title": "Eventi",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "onClick": "Gestore del click",
        "onSubmit": "Gestore dell'invio",
        "onInput": "Gestore dell'input",
        "onKeydown": "Gestore dei tasti",
        "onInit": "Si attiva immediatamente durante l'inizializzazione",
        "onMounted": "Ciclo di vita: montato",
        "onUnmounted": "Ciclo di vita: smontato",
        "throttle": "Limita l'esecuzione del gestore (ms)",
        "self": "Si attiva solo se il target dell'evento è l'elemento stesso",
        "backspace": "Modificatore tasto per il tasto Backspace",
        "onUpdated": "Lifecycle: mutazione del DOM osservata",
        "onError": "Lifecycle: errore nel sottoalbero"
      },
      "styling": {
        "title": "Stile",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "classStar": "Alterna classe CSS",
        "classMap": "Classe da oggetto",
        "styleStar": "Imposta stile inline",
        "styleMap": "Stile da oggetto"
      },
      "forms": {
        "title": "Form",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "validate": "Abilita la validazione del form/campo (Ora in NoJS Elements)",
        "error": "Template di errore per il campo",
        "success": "Template di successo",
        "loading": "Template di caricamento",
        "confirm": "Dialogo di conferma",
        "redirect": "Reindirizza in caso di successo"
      },
      "routing": {
        "title": "Instradamento",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "route": "Definisce una route o un link",
        "routeView": "Outlet della route",
        "routeViewNamed": "Outlet della route con nome",
        "outlet": "Punta a un outlet con nome",
        "routeActive": "Classe per il link attivo",
        "guard": "Condizione di guardia della route",
        "routeActiveExact": "Classe attiva con corrispondenza esatta per i link delle route",
        "redirect": "Percorso di reindirizzamento quando la guardia fallisce",
        "lazyPriority": "Carica il template remoto prima di tutti gli altri (Fase 0)",
        "lazyOnDemand": "Recupera il template della route solo alla prima visita (solo template di route)",
        "routerForward": "Naviga avanti nella cronologia",
        "routerOn": "Sottoscrivi ai cambiamenti di route",
        "routeWildcard": "Route wildcard catch-all 404",
        "routerCurrent": "Oggetto della route corrente",
        "routeMatched": "<code>true</code> se una route esplicita ha corrisposto, <code>false</code> per wildcard/fallback",
        "i18nNs": "Auto-derivazione del namespace i18n dal nome del file di rotta",
        "routeViewSrc": "Outlet di routing basato su file",
        "routeIndex": "Nome del file per la radice <code>/</code> (predefinito <code>\"index\"</code>)",
        "routeExt": "Estensione file (predefinito <code>\".tpl\"</code>, fallback <code>\".html\"</code>)",
        "transitionVT": "Preset View Transition API su route-view (slide, fade, scale, none)"
      },
      "animation": {
        "title": "Animazione",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "animate": "Animazione di entrata",
        "animateEnter": "Animazione di entrata",
        "animateLeave": "Animazione di uscita",
        "animateDuration": "Durata in ms",
        "animateStagger": "Ritardo scaglionato",
        "transition": "Transizione CSS (basata su classi, per elementi regolari)",
        "transitionVT": "Preset View Transition API su route-view (slide, fade, scale, none)"
      },
      "dnd": {
        "title": "Drag and Drop (Ora in NoJS Elements)",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "drag": "Rendere un elemento trascinabile",
        "dragType": "Identificatore del tipo di dati",
        "dragEffect": "Effetto consentito (move/copy/link/all)",
        "dragHandle": "Limitare il trascinamento al selettore maniglia",
        "dragDisabled": "Disabilitare il trascinamento condizionalmente",
        "dragClass": "Classe aggiunta durante il trascinamento",
        "dragGroup": "Limitare il trascinamento a un gruppo nominato",
        "drop": "Definire una zona di rilascio",
        "dropAccept": "Tipo/i di trascinamento accettati",
        "dropEffect": "Effetto di feedback visivo",
        "dropClass": "Classe aggiunta al passaggio",
        "dropDisabled": "Disabilitare il rilascio condizionalmente",
        "dropMax": "Numero massimo di elementi nella zona",
        "dropSort": "Abilitare l'ordinamento posizionale",
        "dropPlaceholder": "Template segnaposto durante il passaggio",
        "dropSettleClass": "Classe CSS personalizzata per l'animazione di assestamento",
        "dropEmptyClass": "Classe CSS personalizzata per lo stato vuoto su drag-list",
        "dragList": "Lista ordinabile collegata a un array di stato",
        "dragListKey": "Chiave unica per ogni elemento",
        "dragListItem": "Selettore del template dell'elemento",
        "dragListCopy": "Copiare invece di spostare durante il trasferimento",
        "dragListRemove": "Rimuovere gli elementi dalla sorgente durante il trasferimento",
        "dragMultiple": "Lazo / selezione multipla sui figli",
        "dragMultipleClass": "Classe aggiunta agli elementi selezionati",
        "dropRejectClass": "Classe aggiunta al rifiuto del trascinamento"
      },
      "i18n": {
        "title": "i18n",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "t": "Traduci chiave",
        "tStar": "Parametro di traduzione",
        "tHtml": "Renderizzare la traduzione come HTML sanitizzato"
      },
      "misc": {
        "title": "Varie",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "ref": "Riferimento nominato all'elemento",
        "call": "Attiva una chiamata API",
        "trigger": "Emette un evento personalizzato",
        "use": "Istanzia un template",
        "src": "Template remoto (vedi anche: lazy)",
        "loading": "Placeholder mostrato durante il caricamento del template remoto; rimosso all'arrivo",
        "include": "Clona sincronamente un template inline nella posizione corrente",
        "errorBoundary": "Confine di errore",
        "var": "Nome variabile del template"
      },
      "headManagement": {
        "title": "Head Management",
        "col1": "Direttiva",
        "col2": "Esempio",
        "col3": "Descrizione",
        "pageTitle": "Impostare document.title in modo reattivo",
        "pageDescription": "Impostare <meta name=\"description\">",
        "pageCanonical": "Impostare <link rel=\"canonical\">",
        "pageJsonld": "Impostare <script type=\"application/ld+json\">"
      }
    },
    "stateManagement": {
      "hero": {
        "badge": "Guide",
        "title": "Gestione dello Stato",
        "subtitle": "Stato locale, store globali, proprietà calcolate e watcher"
      },
      "state": {
        "title": "state — Stato Locale",
        "text": "Crea un contesto reattivo con scope limitato all'elemento e ai suoi figli.",
        "preview": "Anteprima",
        "helloLabel": "Ciao,",
        "countLabel": "Conteggio:",
        "resetBtn": "Reimposta"
      },
      "store": {
        "title": "store — Store Globale",
        "text": "Uno store reattivo globale accessibile ovunque. Ideale per stato di autenticazione, tema, dati condivisi."
      },
      "configStores": {
        "title": "Pre-inizializzazione degli Store tramite config()",
        "text": "Puoi pre-creare store con dati iniziali all'interno di NoJS.config(). Ogni chiave nell'oggetto stores diventa uno store globale con nome, accessibile immediatamente tramite $store.nome.",
        "callout": "Se uno store esiste già (es. creato tramite un attributo store), config() non lo sovrascriverà — lo store esistente viene preservato."
      },
      "into": {
        "title": "into — Scrivere i Risultati del Fetch in uno Store",
        "text": "L'attributo into su qualsiasi direttiva HTTP scrive la risposta direttamente in uno store globale con nome.",
        "callout": "Lo store non deve essere predefinito — into lo creerà se non esiste."
      },
      "computed": {
        "title": "computed — Stato Derivato",
        "text": "Valori che vengono ricalcolati automaticamente quando le dipendenze cambiano.",
        "preview": "Anteprima",
        "priceLabel": "Prezzo:",
        "qtyLabel": "Qtà:",
        "subtotalLabel": "Subtotale:",
        "totalLabel": "Totale:"
      },
      "watch": {
        "title": "watch — Effetti Collaterali",
        "text": "Esegui un'azione ogni volta che un valore cambia."
      },
      "persistence": {
        "title": "Persistenza dello Stato",
        "text": "Persisti lo stato tra i ricaricamenti della pagina usando localStorage o sessionStorage."
      },
      "notify": {
        "title": "NoJS.notify() — Aggiornare lo Store",
        "text": "Quando JavaScript esterno modifica uno store tramite NoJS.store, chiamare NoJS.notify() per aggiornare tutti i binding del DOM.",
        "callout": "Necessario solo quando si modifica NoJS.store da JavaScript puro — al di fuori delle espressioni HTML. Le modifiche dentro on:click o bind vengono gestite automaticamente."
      },
      "persistSchema": {
        "title": "persist-schema — Validazione dello Schema",
        "text": "Durante il ripristino dello stato persistito, persist-schema valida che le chiavi ripristinate corrispondano alla forma dello stato iniziale. Le chiavi non presenti nello stato iniziale vengono scartate. Questo impedisce che dati obsoleti o corrotti rompano la tua app dopo modifiche allo schema."
      },
      "scoping": {
        "title": "Scope del Contesto & Shadowing",
        "text": "I contesti ereditano dagli elementi padre come lo scope lessicale. Uno state figlio può sovrascrivere una proprietà del padre — il figlio vede il proprio valore, mentre i fratelli vedono quello del padre.",
        "callout": "Lo shadowing è intenzionale e segue le regole di scope di JavaScript. Se hai bisogno di stato condiviso tra fratelli, usa uno store."
      }
    },
    "dataBinding": {
      "hero": {
        "badge": "Guide",
        "title": "Binding dei Dati",
        "subtitle": "Binding unidirezionale e bidirezionale con bind e model"
      },
      "bind": {
        "title": "bind — Contenuto Testuale",
        "text": "Sostituisce il textContent dell'elemento con l'espressione valutata."
      },
      "bindHtml": {
        "title": "bind-html — HTML Interno",
        "text": "Renderizza l'espressione valutata come HTML. Sanitizzato per impostazione predefinita.",
        "callout": "⚠️ Utilizza una sanitizzazione strutturale integrata basata su DOMParser: rimuove i tag <script>, blocca i gestori di eventi on* e rimuove gli URI javascript:."
      },
      "bindAttr": {
        "title": "bind-* — Binding degli Attributi",
        "text": "Collega dinamicamente qualsiasi attributo HTML."
      },
      "model": {
        "title": "model — Binding Bidirezionale",
        "text": "Per gli input dei form, model crea automaticamente un binding bidirezionale dei dati.",
        "preview": "Anteprima",
        "nameLabel": "Nome",
        "placeholder": "Digita il tuo nome...",
        "checkbox": "Accetto",
        "agreedLabel": "Accettato:",
        "helloPrefix": "Ciao,"
      },
      "radioSelect": {
        "title": "Radio Button & Multi-Select",
        "text": "model funziona con tutti i tipi di input. Per i radio button, associa lo stesso nome model a un gruppo — il valore si aggiorna al value del radio selezionato. Per il multi-select, il valore del model diventa un array delle opzioni selezionate."
      },
      "commonMistakes": {
        "title": "Errori Comuni",
        "text": "Evita queste insidie comuni del data binding:",
        "mistake1": "Usare bind-html senza comprendere la sanitizzazione — tutto il contenuto è sanitizzato per impostazione predefinita, ma sii consapevole di cosa viene rimosso.",
        "mistake2": "Dimenticare che bind sostituisce textContent — qualsiasi elemento figlio dentro un bind viene rimosso.",
        "mistake3": "Usare model su elementi non-form — model funziona solo su input, textarea e select."
      }
    },
    "events": {
      "hero": {
        "badge": "Guide",
        "title": "Gestione Eventi",
        "subtitle": "Collega gli eventi DOM direttamente in HTML con la sintassi on:event"
      },
      "handlers": {
        "title": "on:* — Gestori di Eventi",
        "text": "Collega qualsiasi evento DOM direttamente in HTML. Accedi allo stato e alle variabili di contesto direttamente nell'espressione del gestore.",
        "preview": "Anteprima",
        "inputPlaceholder": "Digita qualcosa...",
        "youTyped": "Hai digitato:",
        "countLabel": "Conteggio:"
      },
      "modifiers": {
        "title": "Modificatori di Evento",
        "text": "I modificatori permettono di controllare il comportamento degli eventi direttamente nell'attributo:"
      },
      "eventAndEl": {
        "title": "$event & $el",
        "text": "$event è l'evento DOM nativo. $el si riferisce all'elemento corrente."
      },
      "lifecycle": {
        "title": "Hook del Ciclo di Vita",
        "col1": "Hook",
        "col2": "Quando",
        "onInit": "Direttiva processata per la prima volta",
        "onMounted": "Elemento inserito nel DOM visibile",
        "onUpdated": "Mutazione del DOM osservata (via MutationObserver)",
        "onUnmounted": "Elemento rimosso dal DOM",
        "onError": "Errore nel sottoalbero di questo elemento"
      },
      "keyModifiers": {
        "title": "Modificatori di Tasto",
        "text": "Usa i modificatori di tasto sugli eventi tastiera per filtrare per tasti specifici. Combina con Ctrl, Alt, Shift o Meta per le scorciatoie.",
        "col1": "Modificatore",
        "col2": "Tasto",
        "enter": "Invio / Return",
        "escape": "Escape",
        "space": "Spazio",
        "tab": "Tab",
        "backspace": "Backspace",
        "arrowUp": "Freccia Su",
        "arrowDown": "Freccia Giù",
        "arrowLeft": "Freccia Sinistra",
        "arrowRight": "Freccia Destra",
        "ctrl": "Ctrl (Control)",
        "alt": "Alt (Option su Mac)",
        "shift": "Shift",
        "meta": "Meta (Cmd su Mac, Win su Windows)",
        "delete": "Canc"
      }
    },
    "conditionals": {
      "hero": {
        "badge": "Guide",
        "title": "Condizionali",
        "subtitle": "Controlla il rendering con if, show, hide e switch"
      },
      "ifThenElse": {
        "title": "if / then / else",
        "text": "Renderizza condizionalmente elementi o template basati su espressioni.",
        "preview": "Anteprima",
        "checkbox": "Autenticato",
        "welcome": "✅ Bentornato!",
        "login": "Effettua il login."
      },
      "elseIf": {
        "title": "else-if — Condizionali Concatenati"
      },
      "showHide": {
        "title": "show / hide",
        "text": "Alterna display: none senza aggiungere/rimuovere elementi DOM. Migliore per elementi che vengono alternati frequentemente.",
        "comparisonTitle": "if vs show",
        "colIf": "if",
        "colShow": "show",
        "mechanism": "Meccanismo",
        "mechanismIf": "Aggiunge/rimuove elementi DOM",
        "mechanismShow": "Alterna il display CSS",
        "bestFor": "Ideale per",
        "bestForIf": "Contenuto alternato raramente",
        "bestForShow": "Contenuto alternato frequentemente",
        "preservesState": "Preserva lo stato",
        "preservesIf": "No (ricrea)",
        "preservesShow": "Sì"
      },
      "switchCase": {
        "title": "switch / case",
        "text": "Renderizza uno tra molti template in base a un valore.",
        "inlineSubtitle": "Contenuto Inline (senza template)",
        "multiValueSubtitle": "Case Multi-Valore"
      }
    },
    "loops": {
      "hero": {
        "badge": "Guide",
        "title": "Direttive di iterazione",
        "subtitle": "Itera sugli array con foreach, each e for"
      },
      "foreach": {
        "title": "foreach — Itera sugli array",
        "text": "La direttiva di iterazione principale. Usa foreach=\"item in array\" per iterare sugli array. each e for sono alias con comportamento identico.",
        "col1": "Attributo",
        "col2": "Descrizione",
        "foreach": "Espressione: item in array",
        "from": "Array sorgente (DEPRECATED — usa la sintassi item in array)",
        "index": "Nome della variabile per l'indice (default: $index)",
        "key": "Espressione chiave univoca per l'identificazione e il tracciamento degli elementi",
        "else": "ID del template da renderizzare quando l'array è vuoto",
        "filter": "Espressione per filtrare gli elementi",
        "sort": "Percorso della proprietà per l'ordinamento (prefisso - per ordine decrescente)",
        "limit": "Numero massimo di elementi da renderizzare",
        "offset": "Numero di elementi da saltare",
        "preview": "Anteprima",
        "template": "ID di template esterno (opzionale — i figli diventano il template se omesso)"
      },
      "fullExample": {
        "title": "Esempio completo con tutti gli attributi",
        "text": "Un esempio completo che mostra foreach con filtraggio, ordinamento, paginazione e un template di fallback per lo stato vuoto."
      },
      "aliases": {
        "title": "Alias: each e for",
        "text": "each e for sono alias di foreach — condividono lo stesso handler e supportano tutti gli stessi attributi."
      },
      "inline": {
        "title": "Template figli inline",
        "text": "Quando nessun attributo template è specificato, i figli dell'elemento diventano il template ripetuto."
      },
      "deprecated": {
        "title": "Deprecato: attributo from",
        "text": "L'attributo from funziona ancora ma è deprecato. Usa la sintassi \"item in array\" al suo posto. L'uso di from emetterà un avviso nella console."
      },
      "contextVars": {
        "title": "Variabili di contesto del ciclo",
        "col1": "Variabile",
        "col2": "Descrizione",
        "index": "Indice corrente (base 0)",
        "count": "Numero totale di elementi",
        "first": "true se è il primo elemento",
        "last": "true se è l'ultimo elemento",
        "even": "true se l'indice è pari",
        "odd": "true se l'indice è dispari"
      },
      "nested": {
        "title": "Cicli annidati",
        "text": "I cicli figli (foreach, each o for) possono accedere alle variabili dello scope genitore."
      },
      "reactivity": {
        "title": "Reattività",
        "text": "Le direttive di loop sono completamente reattive. Quando l'array sorgente cambia (elementi aggiunti, rimossi o riordinati), il DOM si aggiorna automaticamente. Usa l'attributo key per un diffing efficiente — senza, l'intera lista viene ri-renderizzata ad ogni modifica."
      },
      "objectIteration": {
        "title": "Iterazione di Oggetti",
        "text": "Per iterare sulle voci di un oggetto, usa il filtro keys o values per convertirlo in array prima.",
        "callout": "L'iterazione diretta di oggetti non è supportata — converti sempre in array con keys, values o Object.entries() in un'espressione computed."
      }
    },
    "templates": {
      "hero": {
        "badge": "Guide",
        "title": "Template",
        "subtitle": "Frammenti HTML riutilizzabili con variabili, slot e caricamento remoto"
      },
      "basic": {
        "title": "Template Base",
        "text": "I template sono frammenti HTML riutilizzabili che non vengono mai renderizzati direttamente. Vengono clonati quando referenziati da direttive come then, else, template, loading, error, ecc."
      },
      "var": {
        "title": "Variabili dei Template (var)",
        "text": "I template possono dichiarare quale variabile si aspettano dal contesto chiamante."
      },
      "slots": {
        "title": "Slot dei Template",
        "text": "Permettono ai template di accettare contenuto proiettato."
      },
      "remote": {
        "title": "Template Remoti (src)",
        "text": "Carica template da file HTML esterni."
      },
      "recursive": {
        "subtitle": "Caricamento Ricorsivo",
        "text": "I template remoti vengono caricati ricorsivamente — se un template remoto contiene a sua volta elementi <template src=\"...\">, questi vengono risolti automaticamente:"
      },
      "remoteRoutes": {
        "subtitle": "Template Remoti nelle Route",
        "text": "Anche i template remoti all'interno del contenuto delle route vengono risolti automaticamente prima che la route venga renderizzata. Consulta Routing per i dettagli."
      },
      "lazy": {
        "title": "Caricamento Lazy (lazy)",
        "text": "Controlla quando i template remoti vengono recuperati utilizzando l'attributo lazy sugli elementi <template src=\"...\">. NoJS carica i template in fasi per ottimizzare il time-to-first-render.",
        "col1": "Valore",
        "col2": "Comportamento",
        "absent": "(assente)",
        "absentDesc": "Auto-prioritizzazione predefinita: i template content-include e il template della route corrente vengono caricati prima del primo render; gli altri template di route vengono precaricati in background dopo il primo render.",
        "priorityDesc": "Forza il caricamento prima di tutto il resto — anche prima dei normali content include. Utile per template di layout condivisi critici.",
        "ondemandDesc": "Valido solo per i template di route. Mai precaricato — recuperato in modo lazy la prima volta che l'utente naviga verso quella route. Ideale per pagine pesanti o poco visitate."
      },
      "phases": {
        "subtitle": "Fasi di Caricamento",
        "text": "I template vengono risolti in quattro fasi ordinate: la Fase 0 recupera per primi i template lazy=\"priority\"; la Fase 1 recupera tutti gli altri template non-route più il template della route attiva (bloccante prima del primo render); la Fase 2 precarica i template di route rimanenti in background dopo il primo render; e on-demand recupera i template di route lazy=\"ondemand\" solo quando l'utente naviga per la prima volta verso di essi."
      },
      "loading": {
        "title": "Placeholder di Caricamento (loading)",
        "text1": "Mostra un template placeholder mentre un template remoto viene recuperato. Il placeholder viene inserito in modo sincrono — prima di qualsiasi richiesta di rete — e rimosso automaticamente quando il contenuto reale arriva. Funziona sia per i content-include statici che per i template annidati all'interno delle pagine di route.",
        "text2": "Sono accettati sia ID semplici che la sintassi #id. Il template placeholder viene clonato ogni volta, quindi può essere riutilizzato su più template remoti:"
      },
      "include": {
        "title": "Include di Template Inline (include)",
        "text1": "Clona un template inline nella posizione corrente in modo sincrono, prima di qualsiasi fetch. Utile per iniettare markup riutilizzabile (ad es. set di icone, frammenti comuni) senza effettuare una richiesta di rete.",
        "text2": "include e loading hanno scopi diversi: include clona contenuto inline in modo permanente; loading inserisce un placeholder temporaneo che scompare quando il template remoto termina il caricamento."
      }
    },
    "dataFetching": {
      "hero": {
        "badge": "Guide",
        "title": "Recupero Dati",
        "subtitle": "Richieste HTTP dichiarative — basta aggiungere attributi agli elementi HTML"
      },
      "baseUrl": {
        "title": "URL Base",
        "text1": "Impostalo una volta su qualsiasi elemento antenato. Tutti i get, post, ecc. discendenti risolvono gli URL relativi rispetto ad esso.",
        "text2": "Override per sezioni specifiche:",
        "text3": "Gli URL assoluti saltano la risoluzione base:"
      },
      "config": {
        "title": "Configurazione Programmatica"
      },
      "headers": {
        "title": "Header per Richiesta"
      },
      "get": {
        "title": "get — Recupera e Renderizza i Dati",
        "attributesTitle": "Attributi",
        "col1": "Attributo",
        "col2": "Tipo",
        "col3": "Descrizione",
        "get": "URL da cui recuperare (richiesta GET)",
        "as": "Nome da assegnare alla risposta nel contesto. Default: \"data\"",
        "loading": "ID del template da mostrare durante il caricamento (es. \"#skeleton\")",
        "error": "ID del template da mostrare in caso di errore nel fetch",
        "empty": "ID del template da mostrare quando la risposta è un array vuoto/null",
        "refresh": "Intervallo di auto-refresh in ms (polling)",
        "cached": "Cache delle risposte. cached = memory, cached=\"local\" = localStorage, cached=\"session\" = sessionStorage",
        "into": "Scrive la risposta in uno store globale con nome",
        "debounce": "Debounce in ms (utile con URL reattivi)",
        "headers": "Stringa JSON di header aggiuntivi",
        "params": "Espressione che si risolve in un oggetto parametri query"
      },
      "fullExample": {
        "title": "Esempio Completo"
      },
      "reactiveUrls": {
        "title": "URL Reattivi",
        "text": "Gli URL che referenziano variabili di stato vengono recuperati automaticamente quando quei valori cambiano."
      },
      "mutations": {
        "title": "post, put, patch, delete — Richieste di Mutazione",
        "text": "Usati nei form o attivati tramite call.",
        "formSubmissionTitle": "Invio del Form",
        "putPatchDeleteTitle": "PUT / PATCH / DELETE"
      },
      "mutationAttrs": {
        "title": "Attributi di Mutazione",
        "col1": "Attributo",
        "col2": "Descrizione",
        "method": "URL per la richiesta",
        "body": "Corpo della richiesta (stringa JSON con interpolazione). Per i form, serializza automaticamente i campi",
        "success": "ID del template da renderizzare in caso di successo. Riceve la risposta come var",
        "error": "ID del template da renderizzare in caso di errore. Riceve l'errore come var",
        "loading": "ID del template da mostrare durante la richiesta",
        "confirm": "Mostra il dialogo browser confirm() prima dell'invio",
        "redirect": "URL verso cui navigare in caso di successo (route SPA)",
        "then": "Espressione da eseguire in caso di successo (es. \"users.push(result)\")",
        "into": "Scrive la risposta in uno store globale con nome",
        "cached": "Cache delle risposte (memory/local/session). Nota: il caching si applica solo alle richieste GET."
      },
      "lifecycle": {
        "title": "Ciclo di Vita della Richiesta"
      },
      "liveDemo": {
        "title": "Demo Live — Fetch API",
        "label": "Risultato"
      }
    },
    "routing": {
      "hero": {
        "badge": "Guide",
        "title": "Instradamento",
        "subtitle": "Navigazione SPA lato client completa senza ricaricamenti della pagina"
      },
      "definition": {
        "title": "Definizione della Route"
      },
      "params": {
        "title": "Parametri della Route & Query"
      },
      "context": {
        "title": "$route — Contesto della Route",
        "col1": "Proprietà",
        "col2": "Descrizione",
        "path": "Percorso corrente (es. \"/users/42\")",
        "params": "Parametri della route (es. { id: \"42\" })",
        "query": "Parametri della query string (es. { q: \"hello\" })",
        "hash": "Hash dell'URL (es. \"#section\")",
        "matched": "Se una route esplicita ha corrisposto (true) o se un wildcard/fallback è in fase di rendering (false)"
      },
      "activeStyle": {
        "title": "Stile della Route Attiva"
      },
      "guards": {
        "title": "Guardie della Route"
      },
      "programmatic": {
        "title": "Navigazione Programmatica",
        "callout": "$router.push() e $router.replace() restituiscono Promise — la navigazione (incluso il caricamento dei template remoti) è completamente asincrona. Nei gestori on:click il valore di ritorno viene ignorato, ma negli script è possibile usare await:"
      },
      "nested": {
        "title": "Route Annidate"
      },
      "remoteTemplates": {
        "title": "Template Remoti nelle Route",
        "text1": "I template di route possono includere <template src=\"...\"> per caricare contenuto da file esterni. Vengono risolti automaticamente prima che la route venga renderizzata:",
        "text2": "I template remoti annidati (un template remoto che a sua volta contiene altri <template src>) vengono caricati ricorsivamente."
      },
      "fileBased": {
        "title": "Routing Basato su File",
        "text": "Invece di dichiarare ogni template di route manualmente, punta la tua uscita <code>route-view</code> a una cartella. No.JS risolverà automaticamente i percorsi delle route ai file template all'interno di quella cartella.",
        "howItWorks": "Come funziona",
        "list1": "Aggiungi <code>route-view</code> al tuo elemento di uscita — il routing basato su file è abilitato per impostazione predefinita (config <code>router.templates: \"pages\"</code>). Sovrascrivi per uscita con <code>src=\"folder/\"</code>.",
        "list2": "Quando un utente naviga a <code>/analytics</code>, No.JS lo risolve in <code>pages/analytics.tpl</code>",
        "list3": "Il template viene recuperato, memorizzato nella cache e renderizzato — automaticamente",
        "attributesTitle": "Attributi",
        "colAttr": "Attributo",
        "colDefault": "Predefinito",
        "colDesc": "Descrizione",
        "srcDesc": "Cartella base per la risoluzione dei template (sovrascrittura per uscita; config: <code>router.templates</code>)",
        "routeIndexDesc": "Nome del file per la route radice <code>/</code>",
        "extDesc": "Estensione di file aggiunta ai segmenti di route (fallback: <code>\".html\"</code>)",
        "i18nNsDesc": "Quando presente, auto-deriva il namespace i18n dal nome del file",
        "callout": "<strong>Config predefinita:</strong> Il valore predefinito di <code>router.templates</code> è <code>\"pages\"</code>, quindi il routing basato su file funziona immediatamente — aggiungi semplicemente <code>route-view</code> alla tua uscita. Sovrascrivi con <code>NoJS.config({ router: { templates: 'views' } })</code> o per uscita tramite <code>src=\"./custom/\"</code>.",
        "exampleTitle": "Esempio — Dashboard SaaS",
        "exampleText": "Ecco fatto — <strong>due righe</strong> per una SPA completa con sei route.",
        "mixingTitle": "Mescolare Route Esplicite e Basate su File",
        "mixingText": "Le dichiarazioni esplicite <code>&lt;template route=\"...\"&gt;</code> <strong>hanno sempre la priorità</strong>. Questo ti permette di combinare entrambi gli approcci — usa il routing basato su file per le pagine semplici e template espliciti per le route che necessitano di guard, parametri o uscite con nome:",
        "autoI18nTitle": "Namespace i18n Automatico",
        "autoI18nText": "Quando l'elemento <code>route-view</code> ha un attributo <code>i18n-ns</code> (anche senza valore), No.JS carica automaticamente il namespace i18n corrispondente al nome del file:",
        "autoI18nText2": "Questo sostituisce la necessità di aggiungere <code>i18n-ns=\"...\"</code> su ogni template di route individualmente."
      },
      "lazyLoading": {
        "title": "Caricamento Lazy dei Template",
        "text": "L'attributo lazy su <template src=\"...\"> controlla quando un template remoto viene recuperato rispetto al primo render. Usalo per dare priorità ai template critici e posticipare le pagine pesanti o poco visitate.",
        "col1": "Valore",
        "col2": "Fase",
        "col3": "Comportamento",
        "absent": "(assente)",
        "absentPhase": "1 o 2",
        "absentDesc": "Auto: i template non-route e il template della route attiva vengono caricati prima del primo render (Fase 1); gli altri template di route vengono precaricati in background dopo il primo render (Fase 2).",
        "priorityPhase": "0",
        "priorityDesc": "Carica prima di tutto il resto — anche prima dei normali content include. Usalo per template di layout condivisi critici.",
        "ondemandPhase": "su richiesta",
        "ondemandDesc": "Valido solo per i template di route. Mai precaricato — recuperato la prima volta che l'utente naviga verso quella route. Ideale per pagine pesanti o poco visitate."
      },
      "anchor": {
        "title": "Link Ancora",
        "text1": "Quando si usa useHash: true, l'hash dell'URL (#) viene usato per il routing (es. #/docs). Questo normalmente confligge con i link ancora standard come <a href=\"#section\"> — ma No.JS lo gestisce automaticamente in entrambe le modalità (hash e history).",
        "text2": "I link ancora che puntano a un id di elemento nella pagina vengono intercettati dal router: l'elemento target viene portato in vista con scroll fluido, e il link cliccato riceve una classe active. La route stessa non viene influenzata.",
        "howItWorks": "Come funziona:",
        "list1": "Cliccando <a href=\"#introduction\"> si scorre verso <div id=\"introduction\"> con comportamento fluido",
        "list2": "La classe .active viene alternata sul link cliccato (e rimossa dai fratelli)",
        "list3": "Il percorso della route corrente viene preservato — nessuna navigazione avviene",
        "list4": "I link con un attributo route vengono sempre trattati come navigazione di route, non come ancore",
        "tip": "Suggerimento: Stilizza il link ancora attivo con .active nel tuo CSS — il router gestisce la classe per te."
      },
      "namedOutlets": {
        "title": "Outlet con Nome (route-view)",
        "text": "Più outlet route-view possono coesistere nella stessa pagina. Dai a ogni outlet un nome tramite il valore dell'attributo, e punta i template di route verso outlet specifici usando l'attributo outlet.",
        "callout": "Gli outlet senza un template corrispondente per la route corrente vengono sempre svuotati alla navigazione."
      },
      "catchAll": {
        "title": "404 / Route Catch-All",
        "text": "Usa <code>route=\"*\"</code> per definire un template <strong>wildcard catch-all</strong> che viene renderizzato quando nessuna route esplicita corrisponde al percorso corrente. Il wildcard viene sempre valutato per ultimo, indipendentemente dall'ordine nel DOM.",
        "text2": "Le route esplicite <strong>hanno sempre la priorità</strong> — il wildcard si attiva solo quando <code>matchRoute()</code> non restituisce alcuna corrispondenza.",
        "fallbackTitle": "Fallback 404 Automatico",
        "fallbackText": "Se non definisci un template <code>route=\"*\"</code>, No.JS mostra automaticamente una pagina 404 minimale integrata quando nessuna route corrisponde. Questo garantisce che gli utenti vedano sempre qualcosa di significativo invece di un outlet vuoto.",
        "fallbackTip": "Il fallback integrato è volutamente minimale e senza stili. Definisci il tuo template <code>route=\"*\"</code> per le applicazioni in produzione.",
        "namedTitle": "Wildcard negli Outlet con Nome",
        "namedText": "Ogni outlet con nome può avere il proprio fallback wildcard. Quando nessuna route corrisponde per un outlet, il framework risolve i fallback in questo ordine:",
        "namedList1": "<strong>Wildcard locale</strong> — <code>&lt;template route=\"*\" outlet=\"{name}\"&gt;</code> per quell'outlet specifico",
        "namedList2": "<strong>Wildcard globale</strong> — <code>&lt;template route=\"*\"&gt;</code> (il wildcard dell'outlet predefinito), usato solo per gli outlet non predefiniti",
        "namedList3": "<strong>404 integrato</strong> — la pagina di fallback minimale del framework",
        "namedText2": "Se la barra laterale non ha un wildcard locale, ricorre al <code>route=\"*\"</code> globale. Se nessuno esiste, viene usato il 404 integrato.",
        "matchedTitle": "$route.matched",
        "matchedText": "Il booleano <code>$route.matched</code> indica se il percorso corrente ha trovato una route esplicita (<code>true</code>) o un wildcard/fallback (<code>false</code>). Usalo per il rendering condizionale nei tuoi template:",
        "matchedText2": "<code>$route.matched</code> viene impostato <strong>prima</strong> del rendering del template, quindi è sempre disponibile durante l'elaborazione.",
        "remoteTitle": "Template 404 Remoto",
        "remoteText": "Le route wildcard supportano tutti gli stessi attributi dei template di route regolari, incluso <code>src</code> per il caricamento remoto:",
        "remoteText2": "Il template remoto viene recuperato, memorizzato nella cache e renderizzato come qualsiasi altro template di route — e ha accesso completo a <code>$route.path</code>, <code>$route.matched</code> e tutte le altre funzionalità del framework.",
        "fileBasedTitle": "404 nel Routing Basato su File",
        "fileBasedText": "Quando si usa il routing basato su file, navigare verso un percorso il cui file <code>.tpl</code> non esiste sul server (HTTP 404 o altro errore) attiva automaticamente la catena di fallback wildcard.",
        "fileBasedText2": "La risposta HTTP fallita <strong>non</strong> viene memorizzata nella cache — le navigazioni successive verso altri percorsi non vengono influenzate."
      },
      "headAttributes": {
        "title": "Attributi Head delle Route",
        "text": "I template di route possono dichiarare <code>page-title</code> e <code>page-description</code> direttamente sul tag <code>&lt;template&gt;</code>. Quando la route viene attivata, i tag <code>&lt;head&gt;</code> corrispondenti vengono aggiornati automaticamente.",
        "text2": "Sono supportate sia stringhe statiche che espressioni dinamiche:",
        "colAttr": "Attributo",
        "colDesc": "Descrizione",
        "pageTitleDesc": "Imposta <code>document.title</code> quando la route è attiva",
        "pageDescriptionDesc": "Imposta il contenuto di <code>&lt;meta name=\"description\"&gt;</code> quando la route è attiva",
        "callout": "Per una gestione completa dell'head (URL canonici, JSON-LD, Open Graph), consulta la guida <a href=\"/docs/head-management\">Gestione dell'Head</a>."
      },
      "focusBehavior": {
        "title": "Accessibilità — Gestione del Focus",
        "text": "Dopo ogni navigazione, No.JS sposta il focus su un elemento prevedibile all'interno del contenuto della nuova route. Questo garantisce che i lettori di schermo annuncino il cambio di pagina e che gli utenti da tastiera arrivino in un punto utile.",
        "text2": "Quando focusBehavior è 'auto' (il default), il framework percorre una lista di priorità:",
        "priority1": "<code>[autofocus]</code> — un elemento con l'attributo <code>autofocus</code> all'interno del template di route",
        "priority2": "<code>h1</code> — il primo <code>&lt;h1&gt;</code> all'interno del contenuto della route",
        "priority3": "<code>[tabindex=\"-1\"]</code> — un contenitore focalizzabile manualmente",
        "priority4": "L'elemento route-view stesso (ultima risorsa)",
        "defaultTitle": "Comportamento Predefinito",
        "defaultText": "La gestione del focus è <strong>abilitata di default</strong> — non è necessario configurare nulla. La strategia <code>'auto'</code> funziona immediatamente.",
        "timingTitle": "Timing",
        "timingText": "Il focus viene spostato <strong>dopo</strong> che il template di route è stato completamente renderizzato e tutti i template remoti al suo interno sono stati risolti. Questo garantisce che l'elemento target esista nel DOM.",
        "sideEffectsTitle": "Effetti Collaterali",
        "sideEffectsText": "L'elemento focalizzato riceve <code>tabindex=\"-1\"</code> se non ha già un tabindex, e la pagina scorre per renderlo visibile tramite <code>scrollIntoView({ block: 'nearest' })</code>.",
        "futureTitle": "Valori Futuri",
        "futureText": "Attualmente è supportato solo <code>'auto'</code>. Le versioni future potrebbero aggiungere <code>'none'</code> (disabilitare) e <code>'target'</code> (focalizzare un selettore specifico).",
        "ariaLiveTitle": "Regione ARIA Live",
        "ariaLiveText": "Per i lettori di schermo che non rispondono ai cambiamenti di focus, aggiungi <code>aria-live=\"polite\"</code> al tuo <code>route-view</code>. Il browser annuncerà il nuovo contenuto quando appare:"
      },
      "viewTransitions": {
        "title": "View Transitions",
        "text": "L'attributo <code>transition</code> su <code>route-view</code> ora utilizza la <strong>View Transition API</strong> per impostazione predefinita. Basta scegliere un nome di preset e i cambiamenti di rotta vengono animati nativamente dal browser — senza CSS manuale.",
        "presetsTitle": "Preset Integrati",
        "presetsText": "No.JS include quattro preset di transizione integrati:",
        "colPreset": "Preset",
        "colEffect": "Effetto",
        "presetSlide": "Slide direzionale — il contenuto scorre sinistra/destra in base alla direzione di navigazione (forward/backward)",
        "presetFade": "Crossfade — il vecchio contenuto svanisce mentre il nuovo appare",
        "presetScale": "Scale zoom — il vecchio contenuto si riduce mentre il nuovo si ingrandisce",
        "presetNone": "Cambio istantaneo — senza animazione, il contenuto viene sostituito immediatamente",
        "configTitle": "Configurazione",
        "configText": "La View Transition API è <strong>abilitata per impostazione predefinita</strong> tramite <code>router.viewTransition: true</code>. Impostala su <code>false</code> per tornare al sistema legacy di transizioni basato su classi CSS.",
        "customCssTitle": "CSS Personalizzato",
        "customCssText": "Per animazioni personalizzate, punta ai pseudo-elementi <code>::view-transition-old(route-content)</code> e <code>::view-transition-new(route-content)</code>. Il <code>view-transition-name: route-content</code> viene impostato automaticamente su qualsiasi outlet con attributo <code>transition</code>.",
        "howItWorksTitle": "Come Funziona",
        "howItWorksText": "Quando avviene un cambio di rotta con un preset <code>transition</code>:",
        "howStep1": "Il router rileva la direzione di navigazione (<strong>forward</strong> o <strong>backward</strong>) dallo stack della cronologia",
        "howStep2": "<code>document.startViewTransition()</code> viene invocato, catturando lo stato attuale dell'outlet",
        "howStep3": "Il nuovo contenuto della rotta viene renderizzato all'interno dell'outlet",
        "howStep4": "Il browser anima tra i snapshot vecchio e nuovo utilizzando le regole CSS del preset",
        "deprecationTitle": "Migrazione dalle Transizioni Basate su Classi",
        "deprecationText": "Il vecchio sistema di transizioni basato su classi (<code>*-enter</code>, <code>*-enter-active</code>, <code>*-leave</code>, ecc.) su <code>route-view</code> è <strong>deprecated</strong>. Funziona ancora quando <code>router.viewTransition</code> è impostato su <code>false</code>, ma la View Transition API è l'approccio consigliato.",
        "deprecationCallout": "<strong>La migrazione è praticamente automatica.</strong> Se stai già usando <code>transition=\"fade\"</code> su un <code>route-view</code>, ora utilizza la View Transition API per impostazione predefinita — nessuna modifica al codice necessaria. Il tuo CSS personalizzato <code>.fade-enter</code> / <code>.fade-leave</code> viene semplicemente ignorato (a meno che non imposti <code>viewTransition: false</code>)."
      }
    },
    "formsValidation": {
      "hero": {
        "badge": "Guide",
        "title": "Form & Validazione",
        "subtitle": "Invio dichiarativo dei form con regole di validazione integrate e personalizzate"
      },
      "submission": {
        "title": "Invio Dichiarativo del Form"
      },
      "rules": {
        "title": "Regole di Validazione"
      },
      "perRuleErrors": {
        "title": "Messaggi di Errore per Regola",
        "text": "Usa gli attributi error-{regola} per impostare un messaggio personalizzato per una regola specifica, o error come fallback generico."
      },
      "errorTemplates": {
        "title": "Template di Errore",
        "text": "Punta un attributo error a un <template> usando il prefisso # per renderizzare UI di errore avanzata. All'interno del template, $error contiene il messaggio e $rule il nome della regola fallita."
      },
      "errorClass": {
        "title": "Classe CSS di Errore",
        "text": "Usa error-class sul form o su campi individuali per alternare una classe CSS quando un campo è invalido e toccato."
      },
      "formContext": {
        "title": "$form — Contesto del Form",
        "text": "All'interno di qualsiasi <form> con l'attributo validate, $form fornisce:",
        "col1": "Proprietà",
        "col2": "Tipo",
        "col3": "Descrizione",
        "valid": "true se tutti i campi superano la validazione",
        "dirty": "true se un campo è stato modificato",
        "touched": "true se un campo ha ricevuto e perso il focus",
        "submitting": "true mentre la richiesta è in corso",
        "pending": "true mentre i validatori asincroni sono in esecuzione",
        "errors": "Mappa dei nomi dei campi → messaggi di errore",
        "values": "Valori correnti del form",
        "firstError": "Messaggio di errore del primo campo invalido (ordine del DOM)",
        "errorCount": "Numero di campi attualmente in errore di validazione",
        "fields": "Oggetto di stato per campo (valid, error, dirty, touched)",
        "reset": "Ripristina il form ai valori iniziali, cancella errori e classi"
      },
      "formFields": {
        "title": "$form.fields — Stato per Campo",
        "text": "$form.fields espone lo stato individuale di ogni campo indicizzato per nome.",
        "asTitle": "Alias di Campo con as",
        "asText": "Usa l'attributo as per esporre lo stato di un campo sotto un nome personalizzato nel contesto."
      },
      "validateOn": {
        "title": "Trigger di Validazione (validate-on)",
        "text": "Per impostazione predefinita, la validazione viene eseguita su input e focusout. Usa validate-on per cambiare quando appare il feedback visivo.",
        "note": "Internamente, i dati di $form sono sempre aggiornati indipendentemente da validate-on. Il trigger controlla solo quando viene mostrato il feedback visivo."
      },
      "validateIf": {
        "title": "Validazione Condizionale (validate-if)",
        "text": "Salta la validazione di un campo in base a una condizione. Quando validate-if valuta a false, il campo viene trattato come valido."
      },
      "autoDisable": {
        "title": "Disabilita Automatica dei Pulsanti di Invio",
        "text": "I pulsanti di invio vengono automaticamente disabilitati quando il form è invalido. I pulsanti con type=\"button\" non vengono influenzati."
      },
      "customValidators": {
        "title": "Validatori Personalizzati"
      },
      "liveDemo": {
        "title": "Demo Live — Form di Registrazione",
        "label": "Risultato",
        "usernameLabel": "Nome utente",
        "usernamePlaceholder": "Scegli un nome utente",
        "emailLabel": "Email",
        "emailPlaceholder": "tu@esempio.com",
        "ageLabel": "Età",
        "agePlaceholder": "La tua età",
        "roleLabel": "Ruolo",
        "roleDefault": "Seleziona un ruolo",
        "roleDev": "Sviluppatore",
        "roleDesign": "Designer",
        "roleMgr": "Manager",
        "termsLabel": "Accetto i termini",
        "registerButton": "Registrati",
        "successMessage": "Registrazione completata! Benvenuto."
      }
    },
    "styling": {
      "hero": {
        "badge": "Guide",
        "title": "Stile Dinamico",
        "subtitle": "Alterna classi CSS e stili inline in modo reattivo"
      },
      "classToggle": {
        "title": "class-* — Alterna Classi",
        "text": "Aggiungi o rimuovi classi CSS in modo reattivo in base a espressioni. Usa class-{name} per toggle individuali o class-map per classi multiple.",
        "multiObject": "Classi Multiple da Oggetto",
        "multiObjectText": "Usa class-map con un'espressione oggetto per attivare/disattivare più classi. Le chiavi sono nomi di classi, i valori sono espressioni booleane.",
        "fromArray": "Da Array"
      },
      "inlineStyles": {
        "title": "style-* — Stili Inline",
        "text": "Imposta proprietà CSS inline in modo reattivo usando attributi style-{property}. I nomi delle proprietà usano il kebab-case (es: style-font-size, style-background-color).",
        "fromObject": "Da Oggetto",
        "fromObjectText": "Usa style-map con un'espressione oggetto per impostare più stili inline contemporaneamente."
      },
      "liveDemo": {
        "title": "Demo Live — Stile Dinamico",
        "label": "Risultato",
        "toggleButton": "Alterna Attivo"
      },
      "classStatic": {
        "title": "Interazione con class Statica",
        "text": "Le direttive class-* funzionano insieme agli attributi class statici. No.JS alterna solo le classi gestite dalla direttiva — le classi statiche non vengono mai rimosse.",
        "callout": "Puoi combinare class=\"card\" con class-active=\"isActive\" in sicurezza. La classe card è sempre presente; active viene alternata."
      },
      "cssCustomProperties": {
        "title": "CSS Custom Properties",
        "text": "Usa style-* con le CSS custom properties (variabili) per stili reattivi con temi. I nomi delle proprietà seguono la stessa convenzione kebab-case.",
        "callout": "Le CSS custom properties impostate via style-* hanno scope sull'elemento e sono ereditate dai figli — come le CSS custom properties regolari."
      }
    },
    "animations": {
      "hero": {
        "badge": "Guide",
        "title": "Animazioni & Transizioni",
        "subtitle": "Animazioni dichiarative di entrata/uscita e transizioni CSS"
      },
      "enterLeave": {
        "title": "animate — Animazioni di Entrata/Uscita",
        "attrsTitle": "Attributi di Animazione",
        "col1": "Attributo",
        "col2": "Descrizione",
        "row1": "Classe di animazione CSS aggiunta quando l'elemento entra",
        "row2": "Classe di animazione CSS aggiunta quando l'elemento esce",
        "row3": "Durata in millisecondi passata a animationDuration e usata come timeout di fallback. Se omesso, il fallback scatta al prossimo tick dell'event-loop (0 ms)",
        "row4": "Ritardo in millisecondi tra ogni elemento in un ciclo (each / foreach)",
        "fallbackCallout": "Timeout di fallback — No.JS ascolta animationend / transitionend per rimuovere le classi e attivare i re-render dopo le animazioni di uscita. Se l'evento non scatta mai (es. CSS assente, elemento disconnesso) un setTimeout di sicurezza garantisce che la pipeline non si blocchi permanentemente. Se animate-duration è omesso, il timeout è 0 ms — scatta al prossimo tick dell'event-loop senza attese artificiali. Passare un animate-duration=\"300\" esplicito imposta sia animation-duration sull'elemento target sia il timeout di sicurezza a 300 ms."
      },
      "transition": {
        "title": "transition — Classi di Transizione CSS",
        "viewTransitionNote": "<strong>Nota:</strong> Le transizioni di rotta su <code>route-view</code> ora utilizzano la <a href=\"/docs/routing#view-transitions\">View Transition API</a> per impostazione predefinita. L'attributo <code>transition</code> basato su classi descritto di seguito si applica ancora agli <strong>elementi regolari</strong> (es: <code>if</code>, <code>show</code>).",
        "text1": "Segue una convenzione simile al sistema di transizioni di Vue.",
        "text2": "No.JS aggiunge/rimuove classi durante la transizione:",
        "col1": "Classe",
        "col2": "Quando",
        "row1": "Stato iniziale dell'entrata",
        "row2": "Stato attivo dell'entrata",
        "row3": "Stato finale dell'entrata",
        "row4": "Stato iniziale dell'uscita",
        "row5": "Stato attivo dell'uscita",
        "row6": "Stato finale dell'uscita"
      },
      "loopAnimations": {
        "title": "Animazioni nei cicli",
        "text": "Tutte le direttive di ciclo (foreach, each, for) supportano animazioni di entrata/uscita e stagger."
      },
      "builtIn": {
        "title": "Nomi di Animazione Integrati",
        "text": "No.JS include queste animazioni CSS:"
      },
      "liveDemo": {
        "title": "Demo Live — Animazione Toggle",
        "label": "Risultato",
        "toggleButton": "Alterna",
        "demoText": "Ciao, Mondo Animato! ✨"
      },
      "a11y": {
        "title": "Accessibilità — Movimento Ridotto",
        "text": "No.JS rispetta automaticamente la media query prefers-reduced-motion. Quando l'utente preferisce il movimento ridotto, tutte le animazioni CSS vengono disabilitate tramite una regola CSS integrata che imposta animation-duration e transition-duration a 0.01ms.",
        "callout": "Questo si applica globalmente — nessuna configurazione per elemento necessaria. Gli utenti che preferiscono il movimento ridotto vedono cambi di stato istantanei senza animazione."
      }
    },
    "dnd": {
      "hero": {
        "badge": "Guide",
        "title": "Drag and Drop",
        "subtitle": "Trascinamento, liste ordinabili e selezione multipla dichiarativi — zero JavaScript"
      },
      "drag": {
        "title": "drag — Rendere un Elemento Trascinabile",
        "preview": "Anteprima",
        "demoText": "Trascina la frutta nel cestino:",
        "fruitsLabel": "Frutta",
        "basketLabel": "Cestino",
        "col1": "Attributo",
        "col2": "Tipo",
        "col3": "Predefinito",
        "col4": "Descrizione",
        "dragDesc": "Il valore trascinato",
        "dragTypeDesc": "Tipo nominato — rispondono solo le zone <code>drop-accept</code> corrispondenti",
        "dragEffectDesc": "Corrisponde a <code>dataTransfer.effectAllowed</code>",
        "dragHandleDesc": "Limita l'area di presa a un elemento figlio",
        "dragImageDesc": "Elemento fantasma di trascinamento personalizzato",
        "dragImageOffsetDesc": "Offset in pixel per l'immagine di trascinamento personalizzata",
        "dragDisabledDesc": "Quando vero, disabilita il trascinamento",
        "dragClassDesc": "Classe aggiunta durante il trascinamento",
        "dragGhostClassDesc": "Classe aggiunta all'elemento immagine di trascinamento",
        "dragGroupDesc": "Nome del gruppo per la selezione multipla"
      },
      "drop": {
        "title": "drop — Definire una Zona di Rilascio",
        "preview": "Anteprima",
        "demoText": "Trascina gli elementi tra le zone:",
        "zoneALabel": "Zona A",
        "zoneBLabel": "Zona B",
        "col1": "Attributo",
        "col2": "Tipo",
        "col3": "Predefinito",
        "col4": "Descrizione",
        "dropDesc": "Espressione eseguita al rilascio",
        "dropAcceptDesc": "Tipo/i <code>drag-type</code> accettati. Usa <code>\"*\"</code> per qualsiasi",
        "dropEffectDesc": "Corrisponde a <code>dataTransfer.dropEffect</code>",
        "dropClassDesc": "Classe aggiunta quando un elemento valido sorvola",
        "dropRejectClassDesc": "Classe aggiunta quando l'elemento è rifiutato (tipo errato o massimo superato)",
        "dropDisabledDesc": "Quando vero, disabilita il rilascio",
        "dropMaxDesc": "Numero massimo di elementi accettati dalla zona",
        "dropSortDesc": "Abilita il riordino per posizione",
        "dropPlaceholderDesc": "Mostra segnaposto nel punto di inserimento",
        "dropPlaceholderClassDesc": "Classe per il segnaposto",
        "dropSettleClassDesc": "Classe CSS personalizzata per l'animazione di assestamento",
        "dropEmptyClassDesc": "Classe CSS personalizzata per lo stato vuoto della zona di rilascio"
      },
      "dragList": {
        "title": "drag-list — Lista Ordinabile",
        "text": "Una direttiva di alto livello che combina <code>drag</code> e <code>drop</code> in una lista ordinabile collegata a un array di stato.",
        "preview": "Anteprima",
        "todoLabel": "Da Fare",
        "doneLabel": "Fatto",
        "col1": "Attributo",
        "col2": "Tipo",
        "col3": "Predefinito",
        "col4": "Descrizione",
        "dragListDesc": "Percorso all'array nello stato",
        "templateDesc": "Template per ogni elemento",
        "dragListKeyDesc": "Chiave unica per elemento per identità stabile",
        "dragListItemDesc": "Nome della variabile del loop nel template",
        "dropSortDesc": "Direzione del layout",
        "dropAcceptDesc": "Tipi accettati (predefinito: stessa lista)",
        "dragListCopyDesc": "Copia gli elementi invece di spostarli",
        "dragListRemoveDesc": "Rimuovi gli elementi quando trascinati fuori",
        "dragDisabledDesc": "Disabilita il trascinamento da questa lista",
        "dropDisabledDesc": "Disabilita il rilascio in questa lista",
        "dropMaxDesc": "Numero massimo di elementi consentiti",
        "dropSettleClassDesc": "Classe CSS personalizzata per l'animazione di assestamento",
        "dropEmptyClassDesc": "Classe CSS personalizzata per lo stato vuoto della drag-list",
        "dropPlaceholderDesc": "Mostra un segnaposto dove l'elemento verrà rilasciato"
      },
      "dragListEvents": {
        "title": "Eventi di Drag-List",
        "col1": "Evento",
        "col3": "Descrizione",
        "reorderDesc": "Elemento riordinato nella stessa lista",
        "receiveDesc": "Elemento ricevuto da un'altra lista",
        "removeDesc": "Elemento rimosso (trascinato fuori)",
        "preview": "Anteprima",
        "inboxLabel": "Posta in Arrivo",
        "archiveLabel": "Archivio",
        "eventLogLabel": "Registro eventi:"
      },
      "dragMultiple": {
        "title": "drag-multiple — Selezione Multipla",
        "text": "Abilita il clic per selezionare sugli elementi figli, poi trascina tutti gli elementi selezionati contemporaneamente.",
        "preview": "Anteprima",
        "demoText": "Clicca per selezionare, <kbd>Ctrl</kbd>+clic per multi, poi trascina nella zona di rilascio:",
        "availableLabel": "Disponibili",
        "collectedLabel": "Raccolti",
        "col1": "Attributo",
        "col2": "Predefinito",
        "col3": "Descrizione",
        "dragMultipleDesc": "Abilita il clic per selezionare",
        "dragMultipleClassDesc": "Classe aggiunta agli elementi selezionati",
        "dragGroupDesc": "Nome del gruppo — tutti gli elementi selezionati si spostano insieme",
        "selectionTitle": "Comportamento di selezione:",
        "selCol1": "Azione",
        "selCol2": "Risultato",
        "selClick": "Clic",
        "selClickResult": "Seleziona un singolo elemento (sostituisce il precedente)",
        "selCtrlClick": "Ctrl/Cmd + Clic",
        "selCtrlClickResult": "Aggiunge alla selezione",
        "selEscape": "Escape",
        "selEscapeResult": "Cancella tutte le selezioni",
        "selDrag": "Trascinare un elemento selezionato",
        "selDragResult": "<code>$drag</code> diventa un array di tutti gli elementi selezionati"
      },
      "implicitVars": {
        "title": "Variabili Implicite",
        "text": "Queste variabili sono disponibili nelle espressioni <code>drop</code> e nei gestori <code>on:drop</code>:",
        "col1": "Variabile",
        "col2": "Tipo",
        "col3": "Descrizione",
        "dragDesc": "Il valore trascinato. Array se selezione multipla",
        "dragTypeDesc": "Il <code>drag-type</code> dell'elemento",
        "dragEffectDesc": "Il <code>drag-effect</code>",
        "dropIndexDesc": "Indice di inserimento nella zona di rilascio",
        "sourceDesc": "<code>{ list, index, el }</code> — info sorgente",
        "targetDesc": "<code>{ list, index, el }</code> — info destinazione",
        "preview": "Anteprima",
        "demoText": "Ogni elemento ha un <code>drag-type</code> diverso:",
        "dropHere": "Rilascia qui per ispezionare"
      },
      "cssClasses": {
        "title": "Classi CSS",
        "text": "Iniettate automaticamente da No.JS:",
        "col1": "Classe",
        "col2": "Quando applicata",
        "draggingDesc": "Sull'elemento sorgente durante il trascinamento",
        "dragOverDesc": "Sulla zona di rilascio mentre un elemento valido sorvola",
        "dropRejectDesc": "Sulla zona di rilascio quando l'elemento è rifiutato (tipo errato o massimo superato)",
        "dropPlaceholderDesc": "Sul segnaposto di inserimento",
        "selectedDesc": "Sugli elementi con selezione multipla",
        "dropSettleDesc": "Breve animazione di assestamento al rilascio",
        "dragListEmptyDesc": "Su una <code>drag-list</code> quando non ha elementi",
        "preview": "Anteprima",
        "demoText": "Trascina un elemento e osserva le classi applicarsi:",
        "dropZoneHint": "Zona di rilascio (max 2) — osserva <code>.nojs-drag-over</code> / <code>.nojs-drop-reject</code>"
      },
      "a11y": {
        "title": "Accessibilità",
        "text": "No.JS aggiunge automaticamente attributi ARIA e supporto tastiera:",
        "col1": "Funzionalità",
        "col2": "Dettagli",
        "draggableDesc": "Impostato sulle sorgenti di trascinamento",
        "ariaGrabbedDesc": "Riflette lo stato di trascinamento (<code>true</code>/<code>false</code>)",
        "ariaDropeffectDesc": "Impostato sulle zone di rilascio",
        "roleListboxDesc": "Sui contenitori <code>drag-list</code>",
        "roleOptionDesc": "Sugli elementi <code>drag-list</code>",
        "tabindexDesc": "Per l'accesso da tastiera",
        "keyboardTitle": "Scorciatoie da tastiera:",
        "keyCol1": "Tasto",
        "keyCol2": "Azione",
        "spaceDesc": "Afferrare l'elemento focalizzato",
        "escapeDesc": "Annullare il trascinamento",
        "arrowDesc": "Navigare tra gli elementi durante il trascinamento",
        "enterDesc": "Rilasciare nella posizione attuale",
        "preview": "Anteprima",
        "demoText": "Usa <kbd>Tab</kbd> per focalizzare, <kbd>Spazio</kbd> per afferrare, <kbd>↑↓</kbd> per spostare, <kbd>Invio</kbd> per rilasciare:"
      }
    },
    "filters": {
      "hero": {
        "badge": "Guide",
        "title": "Filtri & Pipe",
        "subtitle": "Trasforma i valori nelle espressioni bind usando la sintassi pipe |"
      },
      "text": {
        "title": "Filtri di Testo"
      },
      "number": {
        "title": "Filtri Numerici"
      },
      "array": {
        "title": "Filtri per Array"
      },
      "date": {
        "title": "Filtri per Data"
      },
      "utility": {
        "title": "Filtri di Utilità"
      },
      "object": {
        "title": "Filtri per Oggetti"
      },
      "chaining": {
        "title": "Concatenamento dei Filtri"
      },
      "custom": {
        "title": "Filtri Personalizzati"
      },
      "liveDemo": {
        "title": "Demo Live — Filtri",
        "label": "Risultato",
        "uppercaseLabel": "Maiuscolo:",
        "slugifyLabel": "Slugify:"
      },
      "referenceTable": {
        "title": "Riferimento Completo dei Filtri",
        "text": "Tutti i 32 filtri integrati a colpo d'occhio:",
        "col1": "Filtro",
        "col2": "Categoria",
        "col3": "Descrizione",
        "uppercase": "Converte il testo in MAIUSCOLO",
        "lowercase": "Converte il testo in minuscolo",
        "capitalize": "Rende maiuscola la prima lettera di ogni parola",
        "truncate": "Tronca il testo a N caratteri con puntini di sospensione",
        "slugify": "Converte in slug compatibile URL",
        "trim": "Rimuove gli spazi iniziali/finali",
        "encodeUri": "Codifica un componente URI",
        "currency": "Formatta un numero come valuta",
        "number": "Formatta un numero con raggruppamento per località",
        "percent": "Formatta un numero come percentuale",
        "ordinal": "Aggiunge suffisso ordinale (1°, 2°, 3°)",
        "filesize": "Formatta i byte in dimensione leggibile",
        "reverse": "Inverte array o stringa",
        "unique": "Rimuove i valori duplicati",
        "pluck": "Estrae una proprietà da ogni elemento",
        "where": "Filtra array per valore di proprietà",
        "sortBy": "Ordina array per proprietà",
        "first": "Restituisce il primo elemento di un array",
        "last": "Restituisce l'ultimo elemento di un array",
        "date": "Formatta un oggetto Date",
        "datetime": "Formatta una Date con l'ora",
        "relative": "Tempo trascorso dalla data (es: '5 minuti fa')",
        "fromNow": "Tempo fino a una data futura (es: 'tra 3 ore')",
        "json": "Serializza un valore come stringa JSON",
        "default": "Restituisce un fallback se il valore è null/undefined",
        "keys": "Restituisce le chiavi dell'oggetto come array",
        "values": "Restituisce i valori dell'oggetto come array",
        "count": "Restituisce la lunghezza di un array",
        "join": "Unisce gli elementi dell'array con un separatore",
        "stripHtml": "Rimuove i tag HTML da una stringa",
        "nl2br": "Converte le interruzioni di riga in tag <br>",
        "debug": "Mostra il valore nella console e lo restituisce"
      }
    },
    "i18n": {
      "hero": {
        "badge": "Guide",
        "title": "Internazionalizzazione (i18n)",
        "subtitle": "Supporto multilingua con traduzioni, pluralizzazione e formattazione sensibile al locale"
      },
      "setup": {
        "title": "Configurazione"
      },
      "externalFiles": {
        "title": "File di Locale Esterni",
        "text": "Invece di inserire tutte le traduzioni inline in JavaScript, puoi caricarle da file JSON esterni. Ideale per app di grandi dimensioni con molti locale o quando le traduzioni sono gestite da uno strumento separato.",
        "flatSubtitle": "Modalità Flat (un file per locale)",
        "flatText": "Struttura:",
        "nsSubtitle": "Modalità Namespace (suddivisione per funzionalità)",
        "nsText": "Suddividi le traduzioni per funzionalità per il code-splitting e il caricamento on-demand:",
        "nsRouteSubtitle": "Namespace per Rotta",
        "nsRouteText": "Usa i18n-ns su un template di route per caricare un namespace on-demand quando si naviga verso la route:",
        "nsElementSubtitle": "Namespace su Qualsiasi Elemento",
        "nsElementText": "Usa i18n-ns su qualsiasi elemento per caricare un namespace prima che i suoi figli vengano processati:",
        "cachingSubtitle": "Memorizzazione in Cache",
        "cachingText": "I file JSON recuperati vengono memorizzati in cache per impostazione predefinita. Imposta cache: false durante lo sviluppo:"
      },
      "usage": {
        "title": "Utilizzo"
      },
      "formatting": {
        "title": "Formattazione Numeri & Date"
      },
      "liveDemo": {
        "title": "Demo Live — Selettore di Locale",
        "label": "Risultato",
        "localeLabel": "Lingua:"
      },
      "fallback": {
        "title": "Comportamento di Fallback",
        "text": "Quando una chiave di traduzione manca nella località corrente, No.JS ricade sulla fallbackLocale (predefinita: uguale a defaultLocale). Se la chiave manca in entrambe, viene visualizzato il percorso grezzo della chiave.",
        "callout": "Imposta fallbackLocale esplicitamente per garantire che gli utenti vedano sempre testo significativo, anche per località parzialmente tradotte."
      },
      "detection": {
        "title": "Rilevamento della Località del Browser",
        "text": "Abilita il rilevamento automatico della località da navigator.language del browser con detectBrowser: true. La località rilevata viene abbinata alle tue località disponibili.",
        "callout": "Combinato con persist: true, la località rilevata viene salvata in modo che le visite successive usino la stessa lingua senza ri-rilevamento."
      }
    },
    "actionsRefs": {
      "hero": {
        "badge": "Riferimento API",
        "title": "Azioni & Refs",
        "subtitle": "Attiva chiamate API, emetti eventi personalizzati e referenzia elementi DOM"
      },
      "call": {
        "title": "call — Attiva Richieste API da Qualsiasi Elemento"
      },
      "trigger": {
        "title": "trigger — Emetti Eventi Personalizzati"
      },
      "ref": {
        "title": "ref — Riferimenti con Nome",
        "text": "Accedi agli elementi DOM senza querySelector:"
      },
      "refsMap": {
        "title": "$refs — Mappa dei Ref",
        "text": "Tutti gli elementi con ref sono accessibili tramite $refs nello scope corrente:"
      },
      "triggerAttrs": {
        "title": "Attributi del Trigger",
        "text": "Personalizza il comportamento del trigger con attributi aggiuntivi:",
        "col1": "Attributo",
        "col2": "Descrizione",
        "triggerData": "Payload di dati allegato alla proprietà detail del CustomEvent"
      }
    },
    "customDirectives": {
      "hero": {
        "badge": "Riferimento API",
        "title": "Direttive Personalizzate",
        "subtitle": "Estendi No.JS con i tuoi comportamenti guidati da attributi"
      },
      "directive": {
        "title": "NoJS.directive()"
      },
      "usage": {
        "title": "Utilizzo"
      },
      "webComponents": {
        "title": "Compatibilità con i Web Components",
        "text": "Le direttive No.JS funzionano sugli elementi personalizzati:"
      },
      "componentPatterns": {
        "title": "Pattern Simili a Componenti con Template"
      },
      "priority": {
        "title": "Livelli di Priorità",
        "text": "La priorità determina quando la tua direttiva viene eseguita rispetto alle direttive integrate. I numeri più bassi vengono eseguiti per primi.",
        "col1": "Intervallo",
        "col2": "Quando",
        "range0": "Prima di tutto (inizializzazione dello stato)",
        "range1": "Dopo lo stato, con il recupero dati",
        "range10": "Con le direttive strutturali (if, each)",
        "range20": "Con le direttive di rendering (bind, on:*)",
        "range30": "Dopo tutto (validazione, effetti collaterali)"
      },
      "disposal": {
        "title": "Disposal & Cleanup",
        "text": "Le direttive personalizzate devono pulire dopo se stesse. Usa il callback _onDispose per rimuovere event listener, pulire timer e annullare watcher.",
        "callout": "Le direttive registrate dopo init (via plugin) non sono congelate — ma non possono sovrascrivere le direttive integrate."
      }
    },
    "errorHandling": {
      "hero": {
        "badge": "Riferimento API",
        "title": "Gestione Errori",
        "subtitle": "Template di errore per elemento, logica di retry e gestori di errore globali"
      },
      "perElement": {
        "title": "Gestione Errori per Elemento"
      },
      "globalHandler": {
        "title": "Gestore di Errore Globale"
      },
      "errorBoundary": {
        "title": "error-boundary — Cattura Errori nel Sottoalbero"
      },
      "retry": {
        "title": "Comportamento di Retry",
        "text": "Le richieste HTTP fallite (errori 5xx e guasti di rete) vengono automaticamente ritentate. Configura il numero di retry per elemento con l'attributo retry, e il ritardo tra i retry con retry-delay.",
        "callout": "I retry si applicano solo agli errori del server (5xx) e ai guasti di rete. Gli errori del client (4xx) non vengono ritentati."
      },
      "boundaryEvents": {
        "title": "Eventi di Error Boundary",
        "text": "Quando un error boundary cattura un errore, emette un CustomEvent nojs:error sull'elemento boundary. Ascolta con on:error per registrare errori o mostrare notifiche.",
        "callout": "L'oggetto $event.detail contiene: message (string), source (element) ed error (oggetto Error originale)."
      },
      "expressionErrors": {
        "title": "Errori di Espressione",
        "text": "Quando un'espressione non riesce a valutarsi (es: accedere a una proprietà di undefined), No.JS cattura l'errore, registra un avviso via _warn() e restituisce undefined. Un'espressione rotta non fa mai crashare l'intera pagina."
      }
    },
    "configuration": {
      "hero": {
        "badge": "Riferimento API",
        "title": "Configurazione & Sicurezza",
        "subtitle": "Impostazioni globali, interceptor delle richieste e best practice di sicurezza"
      },
      "globalSettings": {
        "title": "Impostazioni Globali"
      },
      "configStores": {
        "title": "Pre-inizializzazione degli Store",
        "text": "Usa la chiave stores in NoJS.config() per pre-creare store globali con nome e dati iniziali. Ogni voce diventa uno store reattivo accessibile tramite $store.nome ovunque nel tuo HTML.",
        "callout": "Gli store creati tramite config() non sovrascriveranno gli store già esistenti — la prima definizione prevale."
      },
      "configOptions": {
        "title": "Dettagli delle Opzioni di Configurazione",
        "sanitizeTitle": "sanitize",
        "sanitizeType": "Tipo: boolean | Default: true",
        "sanitizeText": "Controlla se il contenuto HTML renderizzato tramite bind-html viene sanitizzato attraverso un sanitizer strutturale basato su DOMParser. Quando abilitato, tutti i tag e gli attributi potenzialmente pericolosi (es. <script>, onerror) vengono rimossi prima dell'inserimento nel DOM.",
        "devtoolsTitle": "devtools",
        "devtoolsType": "Tipo: boolean | Default: false",
        "devtoolsText": "Abilita il pannello devtools di No.JS, accessibile tramite window.__NOJS_DEVTOOLS__. Quando attivo, espone lo stato reattivo, le direttive registrate, le route attive e gli alberi dei componenti per l'ispezione nella console del browser.",
        "templatesCacheTitle": "templates.cache",
        "templatesCacheType": "Tipo: boolean | Default: true",
        "templatesCacheText1": "Controlla se il contenuto HTML dei file .tpl recuperati da remoto viene memorizzato in una Map in memoria dopo la prima richiesta. Nelle navigazioni successive verso la stessa route, l'HTML in cache viene usato direttamente senza effettuare richieste HTTP. La cache dura per tutta la sessione della pagina (nessun TTL — le risorse template sono statiche).",
        "templatesCacheText2": "Imposta a false durante lo sviluppo locale se vuoi che le modifiche ai file .tpl vengano riflesse senza un ricaricamento forzato della pagina.",
        "loadPathTitle": "i18n.loadPath",
        "loadPathType": "Tipo: string | null | Default: null",
        "loadPathText": "Template URL per il caricamento dei file JSON di locale tramite fetch. Usa {locale} e opzionalmente {ns} come placeholder. Quando è null, le traduzioni devono essere fornite inline tramite NoJS.i18n({ locales }).",
        "nsTitle": "i18n.ns",
        "nsType": "Tipo: string[] | Default: []",
        "nsText": "Array di identificatori di namespace da precaricare all'init(). Ogni namespace corrisponde a un file JSON separato per locale. Namespace aggiuntivi possono essere caricati on-demand tramite la direttiva i18n-ns o l'attributo di route.",
        "cacheTitle": "i18n.cache",
        "cacheType": "Tipo: boolean | Default: true",
        "cacheText": "Controlla se i file JSON di locale recuperati vengono memorizzati in una Map in memoria dopo la prima richiesta. Imposta a false durante lo sviluppo per il ricaricamento a caldo dei file di traduzione."
      },
      "apiProperties": {
        "title": "Proprietà API",
        "baseApiUrlTitle": "NoJS.baseApiUrl",
        "baseApiUrlText": "Getter/setter per l'URL base dell'API usato da tutte le direttive fetch e le chiamate NoJS.http. Può essere letto o riassegnato a runtime.",
        "versionTitle": "NoJS.version",
        "versionText": "Proprietà in sola lettura che restituisce la stringa della versione corrente del framework No.JS."
      },
      "interceptors": {
        "title": "Interceptor delle Richieste"
      },
      "security": {
        "title": "Sicurezza",
        "xssTitle": "Protezione XSS",
        "xssList1": "bind imposta sempre textContent, mai innerHTML — sicuro per impostazione predefinita.",
        "xssList2": "bind-html sanitizza il contenuto usando un sanitizer strutturale integrato basato su DOMParser (rimuove i tag <script>, blocca i gestori di eventi on*, rimuove gli URI javascript:).",
        "xssList3": "Le espressioni dei template vengono valutate da un parser sandboxed personalizzato — eval() e Function() non vengono usati, e le proprietà pericolose come __proto__ e constructor sono bloccate.",
        "csrfTitle": "Protezione CSRF",
        "cspSecTitle": "Content Security Policy",
        "cspSecText1": "No.JS utilizza un parser di espressioni personalizzato completamente compatibile con CSP — eval() e il costruttore Function() non vengono usati. Nessuna direttiva unsafe-eval è richiesta nella tua Content Security Policy."
      }
    },
    "plugins": {
      "hero": {
        "badge": "Riferimento API",
        "title": "Plugin",
        "subtitle": "Estendi No.JS con pacchetti riutilizzabili — analytics, autenticazione, feature flag e altro"
      },
      "use": {
        "title": "NoJS.use()",
        "text": "Registra un plugin prima o dopo NoJS.init(). Se l'app è già inizializzata, l'hook init del plugin viene eseguito immediatamente.",
        "objectFormTitle": "Forma Oggetto",
        "objectFormText": "Il modo standard per definire un plugin. Fornisci un nome, una funzione install e hook di ciclo di vita opzionali.",
        "functionTitle": "Scorciatoia Funzione",
        "functionText": "Per i plugin semplici, passa una funzione con nome. Il nome della funzione diventa il nome del plugin.",
        "functionCallout": "Le funzioni anonime e le arrow function vengono rifiutate — il plugin deve avere un nome.",
        "optionsTitle": "Opzioni",
        "optionsText": "Il secondo argomento di NoJS.use() viene passato alla funzione install del plugin.",
        "optionsTrustedNote": "L'opzione trusted è speciale — vedi Interceptor Fidati qui sotto."
      },
      "interface": {
        "title": "Interfaccia del Plugin",
        "thProperty": "Proprietà",
        "thType": "Tipo",
        "thRequired": "Obbligatorio",
        "thDescription": "Descrizione",
        "yes": "Sì",
        "no": "No",
        "nameDesc": "Identificatore univoco. I nomi duplicati vengono rifiutati.",
        "versionDesc": "Stringa semver per il debug.",
        "capabilitiesDesc": "Capacità dichiarate (registrate in modalità debug).",
        "installDesc": "Chiamato in modo sincrono da NoJS.use().",
        "initDesc": "Chiamato dopo il completamento di NoJS.init() (il DOM è pronto).",
        "disposeDesc": "Chiamato durante NoJS.dispose() per la pulizia.",
        "lifecycleTitle": "Ciclo di Vita",
        "lifecycleInstall": "install viene eseguito immediatamente e in modo sincrono. Usalo per registrare interceptor, globali, direttive, listener di eventi e store.",
        "lifecycleInit": "init viene eseguito dopo che il DOM è stato elaborato e il router è attivo. Usalo per operazioni che dipendono da elementi renderizzati o dallo stato della rotta.",
        "lifecycleDispose": "dispose viene eseguito durante la distruzione dell'app. Usalo per chiudere connessioni WebSocket, cancellare intervalli, inviare analytics in sospeso, ecc.",
        "duplicateTitle": "Rilevamento Duplicati",
        "duplicateText": "Un nome di plugin può essere registrato una sola volta. Se NoJS.use() viene chiamato di nuovo con lo stesso nome ma un oggetto diverso, viene registrato un avviso e la chiamata viene ignorata.",
        "freezingTitle": "Congelamento del Registro delle Direttive",
        "freezingText": "Le direttive principali (state, bind, get, on:*, ecc.) vengono congelate dopo il caricamento del framework. I plugin possono registrare nuove direttive ma non possono sovrascrivere quelle integrate."
      },
      "globals": {
        "title": "NoJS.global()",
        "text": "Inietta una variabile reattiva accessibile come $name in qualsiasi espressione di template.",
        "namingTitle": "Convenzioni di Denominazione",
        "namingPrefix": "I nomi globali sono accessibili con un prefisso $ nei template: NoJS.global('foo', ...) diventa $foo.",
        "namingNamespace": "Usa il nome del tuo plugin come namespace per evitare collisioni: $analytics, $auth, $featureFlags.",
        "reservedTitle": "Nomi Riservati",
        "reservedText": "I seguenti nomi non possono essere usati con NoJS.global():",
        "reservedProto": "I vettori di inquinamento del prototipo (__proto__, constructor, prototype) sono anch'essi bloccati.",
        "reactivityTitle": "Reattività",
        "reactivityText": "I valori oggetto passati a NoJS.global() vengono automaticamente avvolti in un contesto reattivo. Le mutazioni attivano aggiornamenti del DOM proprio come le modifiche a store o state.",
        "ownershipTitle": "Tracciamento della Proprietà",
        "ownershipText": "Quando un plugin registra un globale durante la sua fase install, ne diventa il proprietario. Se un plugin diverso sovrascrive quel globale, viene registrato un avviso."
      },
      "sentinels": {
        "title": "Sentinelle degli Interceptor",
        "text": "Gli interceptor di richiesta possono restituire oggetti speciali con chiave di Symbol sentinella per controllare il pipeline di fetch.",
        "cancelTitle": "NoJS.CANCEL — Annullare la Richiesta",
        "cancelText": "Restituisci un oggetto con [NoJS.CANCEL]: true per impedire l'invio della richiesta. Il fetch lancia un AbortError.",
        "respondTitle": "NoJS.RESPOND — Servire una Risposta dalla Cache",
        "respondText": "Restituisci un oggetto con [NoJS.RESPOND]: data per cortocircuitare la richiesta e restituire data direttamente come risposta. Nessuna richiesta HTTP viene effettuata.",
        "replaceTitle": "NoJS.REPLACE — Sostituire i Dati della Risposta",
        "replaceText": "Restituisci un oggetto con [NoJS.REPLACE]: data da un interceptor di risposta per sostituire il corpo della risposta analizzato con dati personalizzati.",
        "summaryTitle": "Riepilogo",
        "thSentinel": "Sentinella",
        "thUsedIn": "Usato In",
        "thEffect": "Effetto",
        "cancelUsedIn": "Interceptor di richiesta",
        "respondUsedIn": "Interceptor di richiesta",
        "replaceUsedIn": "Interceptor di risposta",
        "cancelEffect": "Annulla la richiesta (lancia AbortError)",
        "respondEffect": "Restituisce i dati direttamente, salta la chiamata HTTP",
        "replaceEffect": "Sostituisce il corpo della risposta analizzato"
      },
      "trusted": {
        "title": "Interceptor Fidati",
        "text": "Per impostazione predefinita, gli interceptor ricevono copie censurate delle richieste e risposte — gli header sensibili e i parametri URL vengono rimossi o sostituiti con [REDACTED].",
        "fullAccess": "I plugin di autenticazione che necessitano di accesso agli header reali possono essere installati con { trusted: true }.",
        "callout": "Un avviso nella console viene registrato quando un plugin viene installato con accesso fidato. Concedi trusted solo ai plugin che controlli o hai verificato.",
        "redactedTitle": "Header Censurati",
        "requestLabel": "Header di richiesta rimossi prima del passaggio agli interceptor non fidati:",
        "responseLabel": "Header di risposta rimossi dal proxy di risposta:"
      },
      "dispose": {
        "title": "NoJS.dispose()",
        "text": "Distrugge l'intera applicazione: dispone i plugin, cancella i globali e rimuove gli interceptor.",
        "orderTitle": "Ordine di Distruzione",
        "orderStep1": "I plugin vengono distrutti in ordine inverso di installazione (l'ultimo installato viene distrutto per primo).",
        "orderStep2": "La funzione dispose di ogni plugin ha un timeout di 3 secondi. Se lo supera, viene registrato un errore e la distruzione continua con il plugin successivo.",
        "orderStep3": "Dopo che tutti i plugin sono stati distrutti, i globali e gli interceptor vengono cancellati.",
        "asyncTitle": "Dispose Asincrono",
        "asyncText": "Le funzioni dispose dei plugin possono essere asincrone. Il framework attende ciascuna (soggetta al timeout di 3 secondi).",
        "callout": "I plugin non possono essere installati durante la distruzione. Le chiamate a NoJS.use() mentre dispose() è in esecuzione vengono ignorate con un avviso."
      },
      "security": {
        "title": "Linee Guida di Sicurezza",
        "text": "Quando crei plugin, segui queste pratiche per mantenere la tua applicazione sicura.",
        "namespaceTitle": "Usa il Namespace per Tutto",
        "namespaceText": "Aggiungi il prefisso del nome del tuo plugin a globali, store e nomi di eventi per evitare collisioni.",
        "evalTitle": "Non Usare Mai eval o Function",
        "evalText": "I valori passati a NoJS.global() vengono controllati per riferimenti pericolosi. eval e Function sono bloccati.",
        "cleanupTitle": "Pulisci in dispose",
        "cleanupText": "Fornisci sempre un hook dispose che cancelli gli intervalli, chiuda le connessioni e rimuova i listener di eventi.",
        "overwriteTitle": "Evita di Sovrascrivere i Globali Altrui",
        "overwriteText": "Se il tuo plugin rileva che un globale appartiene già a un altro plugin, considera di usare un nome diverso piuttosto che sovrascrivere silenziosamente.",
        "validateTitle": "Valida le Opzioni",
        "validateText": "Verifica le opzioni obbligatorie in install e avvisa subito."
      },
      "example": {
        "title": "Esempio Completo",
        "text": "Un plugin di analytics completo che dimostra il ciclo di vita del plugin, globali, interceptor e distruzione."
      }
    },
    "headManagement": {
      "hero": {
        "badge": "Guide",
        "title": "Gestione dell'Head",
        "subtitle": "Gestisci il titolo del documento, la meta description, l'URL canonico e il JSON-LD da qualsiasi elemento"
      },
      "intro": {
        "text": "No.JS ti permette di controllare i metadati dell'<head> in modo dichiarativo da qualsiasi punto del tuo markup. Usa elementi nascosti con gli attributi page-title, page-description, page-canonical e page-jsonld — vengono valutati in modo reattivo e aggiornano l'head del documento automaticamente.",
        "routingTip": "Per la gestione dell'head a livello di route, puoi anche usare <code>page-title</code> e <code>page-description</code> direttamente sui tag <code>&lt;template route=\"...\"&gt;</code>. Vedi <a href=\"/docs/routing#route-head-attributes\">Attributi Head delle Route</a>."
      },
      "placement": {
        "title": "Posizionamento",
        "text": "Posiziona gli elementi di gestione dell'head all'interno di qualsiasi scope di state. Devono avere l'attributo hidden — non vengono mai renderizzati visivamente.",
        "reactive": "Tutti i valori sono reattivi — quando lo state sottostante cambia, l'head del documento viene aggiornato immediatamente."
      },
      "pageTitle": {
        "title": "page-title",
        "text": "Imposta document.title con il valore dell'espressione valutata.",
        "expression": "Il valore è un'espressione standard di No.JS valutata nel contesto dell'elemento."
      },
      "pageDescription": {
        "title": "page-description",
        "text": "Imposta l'attributo content del tag <meta name=\"description\">. Se il tag non esiste, viene creato.",
        "duplicate": "Un solo page-description dovrebbe essere attivo alla volta. Se ne sono presenti multipli, l'ultimo processato vince."
      },
      "pageCanonical": {
        "title": "page-canonical",
        "text": "Imposta l'attributo href del tag <link rel=\"canonical\">. Se il tag non esiste, viene creato.",
        "existing": "Se un link canonico esiste già nel tuo HTML, il valore dell'attributo viene aggiornato sul posto."
      },
      "pageJsonld": {
        "title": "page-jsonld",
        "text": "Inietta un blocco <script type=\"application/ld+json\"> nell'head del documento. Il testo interno dell'elemento viene usato come payload JSON-LD.",
        "scriptNote": "Il contenuto viene inserito così com'è — assicurati che sia JSON valido. Usa l'interpolazione <code>{variable}</code> per iniettare valori dinamici.",
        "marker": "Il tag script generato è contrassegnato con <code>data-nojs-jsonld</code> per poterlo identificare e pulire allo smontaggio.",
        "fullExampleTitle": "Esempio Completo di Pagina Prodotto"
      },
      "notes": {
        "title": "Note e Casi Particolari",
        "competingTitle": "Direttive Multiple in Competizione",
        "competingText": "Se più elementi impostano lo stesso attributo head (es. due elementi page-title), l'ultimo processato vince. Quando un elemento viene smontato, il suo contributo all'head viene ripristinato al valore precedente.",
        "cleanupTitle": "Pulizia allo Smontaggio",
        "cleanupText": "Quando un elemento con una direttiva head viene rimosso dal DOM (es. all'interno di un blocco if o durante un cambio di route), il suo contributo all'head viene pulito automaticamente.",
        "captureTitle": "Cattura del Template JSON-LD",
        "captureText": "L'innerHTML dell'elemento page-jsonld viene catturato al momento dell'elaborazione. Se hai bisogno di JSON-LD reattivo, posiziona l'elemento all'interno di uno scope di state e usa l'interpolazione {espressione}."
      }
    }
  }
}
