{
  "docs": {
    "gettingStarted": {
      "hero": {
        "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."
      },
      "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": {
      "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)",
        "query": "Lettura con corpo (QUERY, RFC 10008)",
        "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",
        "sse": "Apre uno stream SSE (EventSource)",
        "sseEvent": "Tipo di evento con nome da ascoltare",
        "sseInsert": "Come i messaggi aggiornano la variabile (replace, append, prepend)",
        "sseLimit": "Lunghezza massima dell'array in modalità append/prepend",
        "sseCredentials": "Invia cookie agli endpoint cross-origin"
      },
      "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",
        "else": "Template renderizzato quando l'array è vuoto o null/undefined"
      },
      "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": {
      "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."
      },
      "persistFields": {
        "title": "persist-fields — Persistenza Selettiva",
        "text": "Usa persist-fields per controllare esattamente quali campi vengono salvati e ripristinati. I campi non elencati non vengono mai scritti nello storage, il che è utile per mantenere valori sensibili (token, password) fuori da localStorage/sessionStorage.",
        "text2": "persist-fields accetta una lista di nomi di campi separati da virgola. Gli spazi attorno a ogni nome vengono rimossi, quindi \"theme, sidebar\" e \"theme,sidebar\" sono equivalenti.",
        "callout": "Ometti persist-fields per persistere tutti i campi. Quando presente, solo i campi elencati vengono salvati — tutti gli altri campi usano i loro valori iniziali al ripristino."
      },
      "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": {
      "bind": {
        "title": "bind — Contenuto Testuale",
        "text": "Sostituisce il textContent dell'elemento con l'espressione valutata.",
        "filtersNote": "Le espressioni dentro <code>bind</code> supportano i <a href=\"/docs/filters\">pipe filter</a> per trasformare i valori nella visualizzazione:"
      },
      "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:.",
        "sanitizerTip": "<strong>Suggerimento:</strong> Puoi fornire un sanitizer personalizzato tramite <code>NoJS.config({ sanitizeHtml: fn })</code>. Vedi <a href=\"/docs/configuration#security\">Configurazione &rarr; Sicurezza</a> per i dettagli."
      },
      "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.",
        "multiSelectWarning": "⚠️ Il binding model con multi-select non è ancora implementato. La direttiva model attuale usa el.value per gli elementi <select> e non legge selectedOptions né gestisce l'attributo multiple. Un model basato su array restituirà un singolo valore string, non un array dei valori selezionati. Questa funzionalità è prevista per una versione futura. L'esempio qui sotto è mostrato solo come riferimento."
      },
      "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": {
      "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",
        "youTyped": "Hai digitato:",
        "countLabel": "Conteggio:"
      },
      "modifiers": {
        "title": "Modificatori di Evento",
        "text": "I modificatori permettono di controllare il comportamento degli eventi direttamente nell'attributo:",
        "col1": "Modificatore",
        "col2": "Descrizione",
        "prevent": "Chiama preventDefault() sull'evento",
        "stop": "Chiama stopPropagation() sull'evento",
        "once": "L'handler viene eseguito una sola volta e poi rimosso automaticamente",
        "self": "Si attiva solo se event.target è l'elemento stesso",
        "debounce": "Applica il debounce all'esecuzione dell'handler (aggiungere il ritardo in ms, es. .debounce.300)",
        "throttle": "Applica il throttle all'esecuzione dell'handler (aggiungere l'intervallo in ms, es. .throttle.200)"
      },
      "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": {
      "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"
      },
      "elseOnLoops": {
        "title": "else sugli Elementi di Ciclo",
        "text": "Le direttive di ciclo (foreach, each, for) supportano else=\"templateId\" per referenziare un <template> come fallback di stato vuoto. Il template viene renderizzato quando la lista è vuota ([]) o null/undefined/non-array — ad esempio lo stato dell'API prima del primo fetch.",
        "callout": "Il pattern else fratello per i cicli è stato rimosso nella v1.15. Usa else=\"templateId\" sull'elemento del ciclo stesso. Consulta la pagina Cicli per i dettagli."
      }
    },
    "loops": {
      "foreach": {
        "title": "foreach — Itera sugli array",
        "text": "La direttiva di iterazione principale. Posiziona foreach=\"item in array\" sull'elemento che si ripete (self-repeating pattern). L'elemento e i suoi figli vengono clonati per ogni item. 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",
        "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)",
        "elseTpl": "ID del template renderizzato quando l'array è vuoto o null/undefined (es: else=\"noItemsTpl\")"
      },
      "fullExample": {
        "title": "Esempio completo con tutti gli attributi",
        "text": "Un esempio completo che mostra foreach con filtraggio, ordinamento, paginazione e un template else per il fallback di 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": "Self-Repeating Pattern",
        "text": "Posiziona la direttiva del loop sull'elemento ripetuto stesso. L'elemento viene clonato per ogni item dell'array. Usa else=\"templateId\" per referenziare un template per lo stato vuoto."
      },
      "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."
      },
      "elseTpl": {
        "title": "Else con Riferimento al Template",
        "text": "Inserisci else=\"templateId\" direttamente sull'elemento del loop. Quando la lista è vuota ([]) o null/undefined, il contenuto del template referenziato sostituisce l'output del loop.",
        "callout": "L'attributo else sull'elemento del loop si attiva per array vuoti ([]) e anche per sorgenti null, undefined o non-array — ad esempio lo stato dell'API prima che il primo fetch si risolva.",
        "breaking": "Breaking change (v1.15): il pattern else fratello per i loop è stato rimosso. Usa else=\"templateId\" sull'elemento del loop."
      },
      "keyReconciliation": {
        "title": "Riconciliazione basata su chiave",
        "text": "Per impostazione predefinita, quando l'array sorgente cambia, la direttiva di loop effettua una ricostruzione completa — tutti i nodi figli vengono eliminati e ricreati da zero. Quando fornisci un attributo key, la direttiva passa alla riconciliazione basata su chiave: i nodi DOM esistenti per gli elementi la cui chiave è ancora nella lista vengono riutilizzati e il loro contesto viene aggiornato sul posto. Solo gli elementi che sono realmente apparsi o scomparsi generano mutazioni del DOM.",
        "callout": "Il valore di key deve essere unico e stabile tra i render — tipicamente un ID del database o un UUID. Usare una chiave non unica (es: $index) vanifica la riconciliazione poiché gli elementi sembreranno sempre corrispondere.",
        "whenTitle": "Quando usare key",
        "colUseCase": "Caso d'uso",
        "colRecommendation": "Raccomandazione",
        "staticLists": "Liste statiche, renderizzate una volta",
        "smallLists": "Liste con < ~10 elementi, aggiornamenti infrequenti",
        "noKeyNeeded": "Nessuna key necessaria",
        "largeLists": "Liste grandi (50+ elementi) con aggiornamenti frequenti",
        "useKey": "Usare key",
        "mutatingArrays": "push / splice / sort su array reattivi",
        "useKeyPreserve": "Usare key per preservare focus, scroll e stato degli input",
        "embeddedInputs": "Elementi con input, video, canvas incorporati",
        "useKeyReset": "Usare key — la ricostruzione completa resetta lo stato",
        "positionalTitle": "Metadati posizionali dopo il riordino",
        "positionalText": "Dopo un riordino (es: sort), il riconciliatore chiama $notify() sul contesto di ogni clone mantenuto. Questo propaga i valori aggiornati di $index, $first, $last, $even, $odd e $count a tutti i watcher figli, inclusi binding annidati ed espressioni di classe che dipendono dalla posizione."
      },
      "externalTemplate": {
        "title": "Template esterno",
        "text": "Usa l'attributo template per referenziare un elemento <template> tramite ID. L'elemento del loop rimane l'unità ripetuta — i cloni del template referenziato vengono inseriti come fratelli."
      },
      "animationAttrs": {
        "title": "Attributi di animazione nei cicli",
        "text": "Tutte le direttive di ciclo (foreach, each, for) supportano animazioni di entrata/uscita e stagger tramite questi attributi:",
        "col1": "Attributo",
        "col2": "Descrizione",
        "enter": "Classe CSS aggiunta a ogni nuovo elemento durante l'inserimento",
        "leave": "Classe CSS aggiunta agli elementi prima della rimozione",
        "stagger": "Ritardo (ms) tra l'animazione di entrata di ogni elemento",
        "duration": "Durata massima (ms) prima del completamento forzato dell'animazione di uscita"
      }
    },
    "templates": {
      "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": {
      "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"
      },
      "query": {
        "title": "query — Richieste di Lettura con Corpo (RFC 10008)",
        "text": "La direttiva <code>query</code> emette una richiesta HTTP QUERY — una lettura sicura, idempotente e cacheable che trasporta un corpo di richiesta. Rende, mette in cache e si attiva automaticamente come <code>get</code>, ma invia un corpo come <code>post</code>. Usala quando una ricerca o un filtro è troppo complesso per una query string dell'URL ma resta una lettura, non una mutazione. Nessun token CSRF viene iniettato, poiché QUERY è un metodo sicuro.",
        "formTitle": "Query da Form",
        "cacheNote": "Quando è in cache, la chiave di cache include il corpo della richiesta — quindi due richieste QUERY allo stesso URL con corpi diversi vengono memorizzate separatamente. La paginazione (get-cursor / get-page / get-insert) resta riservata a GET."
      },
      "liveDemo": {
        "title": "Demo Live — Fetch API",
        "label": "Risultato"
      },
      "urlEncoding": {
        "title": "Interpolazione URL e Encoding",
        "text": "Dalla v1.10, tutti i valori <code>{placeholder}</code> negli attributi URL vengono automaticamente passati attraverso <code>encodeURIComponent()</code>. Questo è sicuro per i parametri di query e i segmenti di percorso a singolo livello, ma romperà i percorsi multi-segmento che contengono barre — perché <code>/</code> diventa <code>%2F</code>. Se il tuo valore contiene separatori di percorso, concatena al di fuori delle parentesi graffe."
      },
      "skeleton": {
        "title": "Skeleton Placeholder",
        "text": "L'attributo <code>skeleton</code> referenzia un elemento DOM (tramite il suo <code>id</code>) che funge da placeholder mentre la richiesta è in corso. A differenza di <code>loading=</code>, l'elemento skeleton esiste nel markup della pagina fin dall'inizio — rendendolo compatibile con SSG e prevenendo il Cumulative Layout Shift (CLS).",
        "hiddenWhen": "Lo skeleton viene automaticamente nascosto (tramite <code>display: none</code>) quando la risposta arriva, quando viene usato un metodo diverso da <code>GET</code>, o quando la risposta è servita dalla cache.",
        "combinedTitle": "Skeleton vs. Loading",
        "combinedText": "Puoi usare sia <code>skeleton=</code> che <code>loading=</code> sullo stesso elemento. Lo skeleton si mostra per primo (pre-renderizzato), poi si nasconde quando la richiesta inizia e il template di loading prende il controllo fino all'arrivo della risposta.",
        "colContent": "Contenuto",
        "skeletonContent": "Elemento HTML pre-renderizzato nella pagina",
        "loadingContent": "Template iniettato da No.JS a runtime",
        "colVisibility": "Visibilità",
        "skeletonVisibility": "Visibile al caricamento della pagina, nascosto dopo la risposta",
        "loadingVisibility": "Mostrato durante la richiesta, nascosto dopo la risposta",
        "colCLS": "Prevenzione CLS",
        "skeletonCLS": "Sì — occupa spazio prima dell'esecuzione del JS",
        "loadingCLS": "No — iniettato dopo l'inizializzazione del JS",
        "colSSG": "Compatibile SSG",
        "skeletonSSG": "Sì",
        "loadingSSG": "No",
        "visibilityTitle": "Regole di Visibilità",
        "visibilityText": "Non nascondere lo skeleton con CSS (<code>display: none</code> o una classe <code>.hidden</code>). No.JS gestisce la visibilità alternando lo stile inline <code>display</code> — se il tuo CSS nasconde l'elemento per primo, la logica di mostra/nascondi andrà in conflitto."
      },
      "pagination": {
        "title": "Paginazione & Scroll Infinito",
        "text": "No.JS supporta la paginazione dichiarativa e lo scroll infinito attraverso un insieme di attributi <code>get-*</code>. Aggiungi <code>get-trigger=\"scroll\"</code> per lo scroll infinito o <code>get-trigger=\"click\"</code> per un pulsante carica altro, combinato con <code>get-insert=\"append\"</code> per accumulare i risultati.",
        "seeAlso": "Per il riferimento completo sulla paginazione — inclusa la paginazione basata su cursore, le etichette di trigger personalizzate, la configurazione della soglia, e l'evento <code>fetch:end</code> — consulta la pagina dedicata <a href=\"#pagination\">Paginazione & Scroll Infinito</a>."
      },
      "interceptors": {
        "title": "Interceptor",
        "text": "Gli interceptor ti permettono di agganciarti a ogni richiesta e risposta HTTP effettuata da No.JS. Usali per header di autenticazione, gestione globale degli errori, caching, logging o cancellazione delle richieste.",
        "basicTitle": "Utilizzo Base",
        "asyncTitle": "Interceptor Asincroni",
        "asyncText": "Gli interceptor possono essere <code>async</code>. No.JS attende ogni interceptor con un timeout di 5 secondi — se l'interceptor non si risolve in tempo, viene saltato e viene registrato un avviso.",
        "cancelTitle": "Cancellare Richieste (NoJS.CANCEL)",
        "cancelText": "Ritorna un oggetto con <code>[NoJS.CANCEL]: true</code> da un interceptor di richiesta per annullare completamente la richiesta. La direttiva fetch tratta questo come un <code>AbortError</code>.",
        "respondTitle": "Risposte Short-Circuit (NoJS.RESPOND)",
        "respondText": "Ritorna un oggetto con <code>[NoJS.RESPOND]: data</code> da un interceptor di richiesta per saltare la chiamata HTTP e usare i dati forniti direttamente come risposta.",
        "replaceTitle": "Sostituire il Corpo della Risposta (NoJS.REPLACE)",
        "replaceText": "Ritorna un oggetto con <code>[NoJS.REPLACE]: data</code> da un interceptor di risposta per sostituire il corpo parsato con i tuoi dati.",
        "redactionTitle": "Redazione degli Header",
        "redactionText": "Per sicurezza, No.JS redige automaticamente gli header sensibili (<code>Authorization</code>, <code>X-API-Key</code>, <code>Cookie</code>, ecc.) nei log di debug e quando passa i dati della richiesta agli interceptor non fidati. Solo gli interceptor registrati con <code>{ trusted: true }</code> ricevono gli header originali.",
        "sentinelTitle": "Riepilogo Sentinel",
        "colSentinel": "Sentinel",
        "colType": "Tipo di Interceptor",
        "colEffect": "Effetto",
        "typeRequest": "Request",
        "typeResponse": "Response",
        "cancelEffect": "Annulla la richiesta (lancia AbortError)",
        "respondEffect": "Salta la chiamata HTTP, ritorna i dati forniti come risposta",
        "replaceEffect": "Sostituisce il corpo della risposta parsato con i dati forniti"
      }
    },
    "routing": {
      "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",
        "pageCanonicalDesc": "Imposta l'href di <code>&lt;link rel=\"canonical\"&gt;</code> quando la route è attiva",
        "pageJsonldDesc": "Inietta un blocco <code>&lt;script type=\"application/ld+json\"&gt;</code> nell'head del documento",
        "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>."
      },
      "deployment": {
        "title": "Deployment",
        "text": "No.JS utilizza l'API History HTML5 per impostazione predefinita (<code>useHash: false</code>), che produce URL puliti come <code>/about</code> e <code>/products/42</code>. Questi URL richiedono che il server serva lo stesso <code>index.html</code> per <strong>ogni route</strong> — altrimenti, una visita diretta a una route lato client restituisce un 404 dal server.",
        "nginxTitle": "nginx",
        "apacheTitle": "Apache",
        "apacheText": "Crea un file <code>.htaccess</code> nella root della tua applicazione:",
        "netlifyTitle": "Netlify",
        "netlifyText": "Crea un file <code>_redirects</code> nella directory di pubblicazione:",
        "netlifyToml": "Oppure usa <code>netlify.toml</code>:",
        "vercelTitle": "Vercel",
        "vercelText": "Crea un <code>vercel.json</code> nella root del progetto:",
        "cloudflareTitle": "Cloudflare Pages",
        "cloudflareText": "Crea un file <code>_redirects</code> nella directory di output del progetto:",
        "firebaseTitle": "Firebase Hosting",
        "firebaseText": "In <code>firebase.json</code>:",
        "hashTitle": "Modalità Hash",
        "hashText": "Se non puoi configurare il server (es. hosting di file statici senza regole di riscrittura), usa la modalità hash. La modalità hash produce URL come <code>https://tuo-sito.com/#/about</code> — funzionano su qualsiasi server senza configurazione, ma <strong>i motori di ricerca non indicizzano i frammenti hash come pagine separate</strong>.",
        "hashCallout": "No.JS emette un avviso nella console quando viene rilevato <code>useHash: true</code>. Per sopprimerlo, aggiungi <code>suppressHashWarning: true</code> alla configurazione del router."
      },
      "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": {
      "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",
        "emailLabel": "Email",
        "ageLabel": "Età",
        "roleLabel": "Ruolo",
        "roleDefault": "Seleziona un ruolo",
        "roleDev": "Sviluppatore",
        "roleDesign": "Designer",
        "roleMgr": "Manager",
        "termsLabel": "Accetto i termini",
        "registerButton": "Registrati",
        "successMessage": "Registrazione completata! Benvenuto."
      }
    },
    "styling": {
      "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": {
      "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:"
      },
      "viewTransitions": {
        "title": "View Transitions (Navigazione tra Route)",
        "text": "No.JS utilizza la View Transition API per transizioni fluide tra le route. Aggiungi l'attributo transition al tuo outlet route-view per abilitare la navigazione animata nativamente nel browser.",
        "configTitle": "Configurazione",
        "presetsTitle": "Preset Integrati",
        "colPreset": "Preset",
        "colEffect": "Effetto",
        "presetFade": "Dissolvenza incrociata tra vecchio e nuovo contenuto",
        "presetSlideLeft": "Scorre il contenuto verso sinistra",
        "presetSlideRight": "Scorre il contenuto verso destra",
        "presetSlideUp": "Scorre il contenuto verso l'alto",
        "routingCallout": "Le View Transitions offrono ulteriori opzioni tra cui CSS personalizzato, accessibilita e dettagli di configurazione. Consulta la sezione <a href=\"/docs/routing#view-transitions\">Routing — View Transitions</a> per il riferimento completo."
      },
      "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": {
      "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": {
      "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": {
      "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"
      },
      "tHtml": {
        "title": "Traduzioni HTML (t-html)",
        "text": "Aggiungi l'attributo t-html per renderizzare un valore di traduzione come HTML sanitizzato invece di testo semplice. Questo è utile quando le traduzioni contengono markup come link, testo in grassetto o altro HTML inline.",
        "callout": "L'output HTML viene passato attraverso _sanitizeHtml() per prevenire attacchi XSS. I tag e gli attributi pericolosi vengono rimossi automaticamente."
      },
      "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.",
        "supportedText": "Durante il caricamento lazy delle località con loadPath, elenca i codici che fornisci in supportedLocales in modo che il rilevamento possa abbinare la lingua del browser prima che venga recuperato qualsiasi file. Priorità alla prima visita: un nojs-locale persistito, poi la lingua del browser rilevata, poi defaultLocale.",
        "callout": "Combinato con persist: true, la località rilevata viene salvata in modo che le visite successive usino la stessa lingua senza ri-rilevamento."
      }
    },
    "actionsRefs": {
      "call": {
        "title": "call — Attiva Richieste API da Qualsiasi Elemento"
      },
      "callAttrs": {
        "title": "Attributi",
        "text": "call supporta gli stessi attributi delle direttive HTTP (get, post, ecc.), inclusi template di caricamento, reindirizzamento, header personalizzati e altro.",
        "col1": "Attributo",
        "col2": "Tipo",
        "col3": "Descrizione",
        "call": "URL per la richiesta (supporta interpolazione {variable})",
        "method": "Metodo HTTP. Predefinito: \"get\"",
        "body": "Corpo della richiesta (stringa JSON con interpolazione {variable})",
        "headers": "Stringa JSON di header aggiuntivi per la richiesta",
        "as": "Nome da assegnare alla risposta nel contesto. Predefinito: \"data\"",
        "into": "Scrive la risposta in uno store globale con nome",
        "loading": "ID del template da mostrare durante la richiesta (es. \"#spinner\")",
        "error": "ID del template da renderizzare in caso di errore. Riceve l'errore tramite var",
        "success": "ID del template da renderizzare in caso di successo. Riceve la risposta tramite var",
        "then": "Espressione da eseguire in caso di successo (es. \"items.push(result)\")",
        "redirect": "Route SPA verso cui navigare in caso di successo",
        "confirm": "Mostra il dialogo confirm() del browser prima dell'invio"
      },
      "loadingTpl": {
        "title": "Template di Caricamento",
        "text": "Mostra un indicatore di caricamento mentre la richiesta è in corso. L'elemento viene disabilitato durante il caricamento e il suo contenuto viene ripristinato successivamente."
      },
      "customHeaders": {
        "title": "Header Personalizzati",
        "text": "Passa header per richiesta come stringa JSON:"
      },
      "redirectAfter": {
        "title": "Reindirizzamento Dopo il Successo",
        "text": "Naviga verso una route SPA dopo una richiesta riuscita:"
      },
      "abort": {
        "title": "Abort / SwitchMap",
        "text": "I clic rapidi annullano automaticamente la richiesta precedente in corso prima di avviarne una nuova, prevenendo condizioni di race. Viene applicato solo il risultato dell'ultimo clic."
      },
      "events": {
        "title": "Eventi",
        "text": "call emette eventi sul bus eventi di NoJS (ascolta con NoJS.on(...)):",
        "col1": "Evento",
        "col2": "Descrizione",
        "fetchSuccess": "{ url, data } in caso di risposta riuscita",
        "fetchError": "{ url, error } in caso di errore",
        "fetchEnd": "{ url } quando la richiesta si completa (successo o errore)"
      },
      "lifecycle": {
        "title": "Ciclo di Vita della Richiesta"
      },
      "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": {
      "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": {
      "perElement": {
        "title": "Gestione Errori per Elemento"
      },
      "globalHandler": {
        "title": "Gestore di Errore Globale"
      },
      "errorBoundary": {
        "title": "error-boundary — Cattura Errori nel Sottoalbero",
        "text": "Avvolgi una sezione della tua pagina con error-boundary per catturare gli errori che si verificano nel suo sottoalbero. Il boundary intercetta due tipi di errori:",
        "type1": "Errori di valutazione di espressione — emessi come CustomEvents nojs:error che risalgono dalle espressioni degli handler (es: un'espressione bind o on:click lancia un errore).",
        "type2": "Errori a livello window — errori JS non catturati e fallimenti di caricamento risorse (es: un <img> 404) che provengono da elementi all'interno del boundary.",
        "httpCaveat": "error-boundary NON cattura le richieste HTTP fallite fatte dalle direttive get/post/put/patch/delete. Usa l'attributo error sull'elemento fetch per la gestione errori per richiesta, o NoJS.on('fetch:error', ...) per la gestione globale degli errori HTTP."
      },
      "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.",
        "callout": "Attiva NoJS.config({ debug: true }) per vedere avvisi dettagliati di valutazione delle espressioni nella console."
      },
      "commonMistakes": {
        "title": "Errori Comuni"
      }
    },
    "configuration": {
      "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.",
        "i18nPersistTitle": "i18n.persist",
        "i18nPersistType": "Tipo: boolean | Default: false",
        "i18nPersistText": "Quando true, la locale attualmente selezionata viene persistita nel localStorage. Al successivo caricamento della pagina, la locale persistita viene ripristinata automaticamente — utile per ricordare la preferenza linguistica dell'utente tra le sessioni.",
        "exprCacheSizeTitle": "exprCacheSize",
        "exprCacheSizeType": "Tipo: number | Default: 500",
        "exprCacheSizeText": "Numero massimo di voci in ciascuna delle due cache LRU interne utilizzate dall'evaluatore di espressioni: una per gli AST delle espressioni analizzate e una per gli AST delle istruzioni analizzate. Quando il limite viene raggiunto, la voce meno recentemente utilizzata viene eliminata. Aumentalo se la tua applicazione valuta un gran numero di espressioni template distinte; diminuiscilo per ridurre la pressione sulla memoria in ambienti limitati.",
        "maxEventListenersTitle": "maxEventListeners",
        "maxEventListenersType": "Tipo: number | Default: 100",
        "maxEventListenersText": "Numero massimo di funzioni listener consentite per nome evento sul bus degli eventi NoJS (NoJS.on()). Quando il limite viene raggiunto, viene registrato un avviso MaxListenersExceeded e il nuovo listener viene comunque registrato. Aumenta questo valore se la tua applicazione utilizza legittimamente molti listener per lo stesso evento.",
        "appIdTitle": "appId",
        "appIdType": "Tipo: string | Default: \"\"",
        "appIdText": "Un identificatore di applicazione opzionale. Esposto tramite il pannello devtools per distinguere tra più istanze o ambienti NoJS.",
        "sanitizeHtmlTitle": "sanitizeHtml",
        "sanitizeHtmlType": "Tipo: function | null | Default: null",
        "sanitizeHtmlText": "Hook di sanitizzazione personalizzato per il contenuto bind-html. Quando impostato come funzione, il sanitizer integrato viene completamente bypassato e la funzione fornita viene utilizzata per tutto il contenuto bind-html. Utile per integrare sanitizer esterni come DOMPurify.",
        "dangerouslyDisableSanitizeTitle": "dangerouslyDisableSanitize",
        "dangerouslyDisableSanitizeType": "Tipo: boolean | Default: false",
        "dangerouslyDisableSanitizeText": "Quando true, TUTTA la sanitizzazione del contenuto bind-html viene bypassata. Questo non è raccomandato — espone la tua applicazione ad attacchi XSS. Usa sanitizeHtml per fornire un sanitizer personalizzato al suo posto.",
        "sanitizeLockCallout": "Le chiavi di configurazione sanitize, dangerouslyDisableSanitize e sanitizeHtml vengono bloccate dopo il completamento di init(). Chiamare NoJS.config() dopo l'inizializzazione non modificherà questi valori — questo impedisce ai plugin o agli script tardivi di indebolire la postura di sicurezza.",
        "suppressHashWarningTitle": "router.suppressHashWarning",
        "suppressHashWarningType": "Tipo: boolean | Default: false",
        "suppressHashWarningText": "Quando si utilizza la modalità history (useHash: false), NoJS registra un avviso nella console se rileva un frammento hash nell'URL che sembra un percorso di route. Imposta a true per sopprimere quell'avviso.",
        "focusBehaviorTitle": "router.focusBehavior",
        "focusBehaviorType": "Tipo: string | Default: \"none\"",
        "focusBehaviorText": "Controlla la gestione del focus dopo la navigazione di route. Quando impostato a 'auto', NoJS sposta il focus su un elemento prevedibile all'interno del nuovo contenuto di route (autofocus, h1, tabindex, o l'outlet stesso). Imposta a 'none' per disabilitare.",
        "viewTransitionTitle": "router.viewTransition",
        "viewTransitionType": "Tipo: boolean | Default: true",
        "viewTransitionText": "Controlla se le transizioni di route utilizzano l'API View Transition. Quando true (default), i cambiamenti di route vengono animati nativamente dal browser utilizzando preset integrati (slide, fade, scale, none). Imposta a false per tornare al sistema di transizione basato sulle classi."
      },
      "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": {
      "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": {
      "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</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}."
      }
    },
    "pagination": {
      "quickStart": {
        "title": "Avvio Rapido",
        "text": "Aggiungi get-trigger e get-insert a qualsiasi direttiva get per abilitare la paginazione. Ecco un esempio minimo di infinite scroll:",
        "note": "La direttiva get recupera la pagina 1 al caricamento. Quando l'utente fa scroll vicino alla fine, recupera automaticamente la pagina successiva e aggiunge i nuovi elementi."
      },
      "attributes": {
        "title": "Riferimento Attributi",
        "col1": "Attributo",
        "col2": "Valori",
        "col3": "Predefinito",
        "col4": "Descrizione",
        "getInsert": "Controlla dove il nuovo contenuto viene posizionato rispetto al contenuto esistente. Senza questo attributo, il contenuto recuperato sostituisce interamente il contenuto attuale.",
        "getTrigger": "Controlla quando il fetch viene attivato. Senza questo attributo, il fetch viene attivato immediatamente al montaggio.",
        "getPage": "Numero di pagina iniziale per la paginazione basata su offset. La variabile di contesto page si incrementa automaticamente dopo ogni fetch riuscito.",
        "getCursor": "Abilita la paginazione basata su cursor. Il cursor viene estratto dall'header di risposta (X-Cursor) o dal campo del corpo JSON.",
        "getCursorField": "Percorso personalizzato del campo JSON per l'estrazione del cursor usando la notazione a punti (es. pagination.nextToken). Senza questo, No.JS cerca cursor, next_cursor, nextCursor, next.",
        "getThreshold": "rootMargin dell'IntersectionObserver. Controlla quanto in anticipo il fetch viene attivato prima che l'elemento entri nel viewport.",
        "getTriggerLabel": "Testo personalizzato per il pulsante load more generato automaticamente quando si usa get-trigger=\"button\"."
      },
      "examples": {
        "title": "Esempi dal Vivo",
        "infiniteScroll": {
          "title": "Infinite Scroll",
          "desc": "Carica automaticamente la pagina successiva quando l'utente fa scroll vicino alla fine della lista.",
          "label": "Risultato dal Vivo"
        },
        "loadMore": {
          "title": "Pulsante Load More",
          "desc": "Mostra un pulsante che l'utente clicca per caricare la pagina successiva di risultati.",
          "label": "Risultato dal Vivo"
        },
        "lazyLoad": {
          "title": "Lazy Load alla Visibilità",
          "desc": "Il contenuto viene recuperato solo quando l'elemento entra nel viewport tramite scroll. Ideale per le sezioni sotto la piega.",
          "label": "Risultato dal Vivo"
        },
        "hoverPrefetch": {
          "title": "Hover Prefetch",
          "desc": "Il contenuto viene recuperato al primo evento mouseenter. Utile per tooltip e card di anteprima.",
          "label": "Risultato dal Vivo",
          "hoverMe": "Passa il mouse su questa card per caricare il contenuto di anteprima"
        },
        "programmatic": {
          "title": "Fetch Programmatico",
          "desc": "Il fetch non viene attivato automaticamente. Usa $refs per attivarlo manualmente tramite un pulsante o un altro evento.",
          "label": "Risultato dal Vivo",
          "clickToLoad": "Clicca il pulsante per attivare il fetch manualmente."
        },
        "cursorPagination": {
          "title": "Cursor Pagination",
          "desc": "Usa la paginazione basata su cursor invece dei numeri di pagina. Il cursor viene estratto dal corpo della risposta JSON.",
          "label": "Risultato dal Vivo"
        },
        "liveFeed": {
          "title": "Live Feed (Prepend)",
          "desc": "Il nuovo contenuto viene inserito in cima alla lista, simulando un feed dal vivo o un ticker di notizie.",
          "label": "Risultato dal Vivo"
        }
      },
      "matrix": {
        "title": "Matrice di Composizione",
        "text": "Gli attributi get-trigger e get-insert si combinano per formare una matrice 5x3 di comportamenti. Ecco come funziona ogni combinazione:",
        "col1": "Trigger",
        "col2": "Senza insert (replace)",
        "col3": "append",
        "col4": "prepend",
        "immediateReplace": "Comportamento predefinito — il fetch sostituisce il contenuto al montaggio.",
        "immediateAppend": "Fetch al montaggio, aggiunge il risultato sotto il contenuto esistente.",
        "immediatePrepend": "Fetch al montaggio, inserisce il risultato sopra il contenuto esistente.",
        "scrollReplace": "Torna al comportamento visible (scroll richiede la modalità insert).",
        "scrollAppend": "Infinite scroll — aggiunge nuove pagine man mano che l'utente fa scroll verso il basso.",
        "scrollPrepend": "Infinite scroll — inserisce nuove pagine man mano che l'utente fa scroll verso l'alto.",
        "buttonReplace": "Torna al comportamento immediate (button richiede la modalità insert).",
        "buttonAppend": "Pulsante load more — aggiunge la pagina successiva al clic.",
        "buttonPrepend": "Pulsante load more — inserisce la pagina successiva al clic.",
        "visibleReplace": "Lazy load — recupera e sostituisce il contenuto quando l'elemento entra nel viewport.",
        "visibleAppend": "Lazy load — recupera e aggiunge il contenuto quando l'elemento entra nel viewport.",
        "visiblePrepend": "Lazy load — recupera e inserisce il contenuto quando l'elemento entra nel viewport.",
        "hoverReplace": "Prefetch — recupera e sostituisce il contenuto al primo mouseenter.",
        "hoverAppend": "Prefetch — recupera e aggiunge il contenuto al primo mouseenter.",
        "hoverPrepend": "Prefetch — recupera e inserisce il contenuto al primo mouseenter.",
        "noneReplace": "Manuale — nessun auto-fetch, usa $refs.refresh() per attivare.",
        "noneAppend": "Manuale — nessun auto-fetch, $refs.refresh() aggiunge.",
        "nonePrepend": "Manuale — nessun auto-fetch, $refs.refresh() inserisce."
      },
      "endOfData": {
        "title": "Rilevamento Fine Dati",
        "text": "No.JS rileva la fine dei dati paginati in tre modi, a seconda del formato della risposta:",
        "emptyBody": "Corpo della risposta vuoto",
        "emptyBodyText": "Quando il server restituisce un corpo di risposta vuoto (Content-Length: 0 o stringa vuota), No.JS interrompe la paginazione e nasconde il pulsante load more.",
        "lastPageHeader": "Header X-NoJS-Last-Page",
        "lastPageHeaderText": "Il server può inviare un header di risposta X-NoJS-Last-Page: true per segnalare esplicitamente che non ci sono più pagine.",
        "nullCursor": "Cursor nullo",
        "nullCursorText": "Per la paginazione basata su cursor, quando il campo del cursor nella risposta JSON è nullo o assente, No.JS interrompe la paginazione."
      },
      "templates": {
        "title": "Template con Paginazione",
        "text": "I template di loading, error ed empty funzionano perfettamente con la paginazione. Il template di loading viene mostrato durante ogni fetch di pagina, e il template di error viene mostrato se una pagina fallisce.",
        "loadingNote": "Durante la paginazione (non al primo fetch), un piccolo indicatore di loading inline viene mostrato al bordo di inserimento invece di sostituire tutto il contenuto.",
        "emptyNote": "Il template empty viene mostrato solo quando la prima pagina non restituisce dati. Le pagine successive vuote semplicemente interrompono la paginazione."
      },
      "scrollPosition": {
        "title": "Preservazione della Posizione di Scroll",
        "text": "Quando si usa get-insert=\"prepend\", No.JS preserva automaticamente la posizione di scroll dell'utente. Il nuovo contenuto viene inserito sopra il viewport attuale, e l'offset di scroll viene regolato in modo che la vista dell'utente non salti."
      }
    },
    "directiveCompatibility": {
      "overview": {
        "title": "Directive Compatibility",
        "text": "No.JS processes directives by priority order (state 0 > HTTP 1 > computed/watch 2 > ref 5 > structural 10 > rendering/events 20 > validation 30). Most directives compose freely, but certain same-element combinations require awareness of processing order and scope mechanics. This page documents every known interaction.",
        "callout": "Combinations marked \"Defined semantics\" work correctly but follow specific rules you should understand. Combinations marked \"Use workaround\" have a known limitation with a documented alternative pattern."
      },
      "matrix": {
        "title": "Compatibility Matrix",
        "structuralTitle": "Structural + Structural (same element)",
        "conditionalTitle": "Conditional + Other Directives (same element)",
        "loopTitle": "Loop + Other Directives (same element)",
        "bindingTitle": "Binding + Binding (same element)"
      },
      "semantics": {
        "title": "Defined Semantics (v1.18.0)",
        "ifGates": {
          "title": "if gates the entire element",
          "text": "As of v1.18.0, if gates the entire element, not just its children. This means all directives on the same element respect the if condition:",
          "http": "HTTP directives (get, post, etc.) on the same element only fire when the condition is true. Zero network requests while false.",
          "computed": "Computed values and watch side effects on the same element only run when the condition is true. No phantom computations.",
          "head": "Head directives (page-title, page-description, page-canonical, page-jsonld) only apply when the condition is true.",
          "binding": "Binding, model, and event directives on the same element are gated in the same way."
        },
        "perClone": {
          "title": "Per-clone computed/watch in loops",
          "text": "When computed or watch appears on a loop element, each clone gets its own independent instance. A computed creates a per-item derived value scoped to that clone's context. A watch fires independently per clone when the watched property changes."
        },
        "usePriority": {
          "title": "use priority 9",
          "text": "The use directive runs at priority 9 (just below structural directives at 10), ensuring templates are instantiated before if/each processing."
        },
        "httpPlacement": {
          "title": "HTTP verb placement",
          "text": "HTTP directives (get, post, put, patch, delete) should be placed on a parent element, not on the loop element itself. The loop element is used as a clone template — placing an HTTP directive on it would fire one request per clone."
        }
      },
      "limitations": {
        "title": "Known Limitations",
        "switchLoop": {
          "title": "switch + loop on case children",
          "text": "Placing a loop directive (each/foreach/for) on a case child of a switch renders both branches; the switch logic goes inert. Workaround: wrap the loop in a container element inside the case."
        },
        "ifLoop": {
          "title": "if + loop on the same element",
          "text": "if and a loop directive on the same element cannot coordinate — the condition cannot remove items, and empty shells may render. Workaround: wrap the loop in a container element with the if."
        },
        "elseIfLoop": {
          "title": "else-if + loop on the same element",
          "text": "else-if combined with a loop on the same element breaks the conditional chain. Items render regardless of the preceding if condition. Additionally, a sibling else element is orphaned. Workaround: wrap the loop in a container element with the else-if."
        },
        "duplicateRef": {
          "title": "Duplicate ref in loop",
          "text": "Using ref on a loop element means each clone overwrites the same ref name. Only the last clone's element is accessible via $refs. Workaround: use bind-ref with a dynamic expression to create unique ref names per clone."
        },
        "bindValueModel": {
          "title": "bind-value + model on the same input",
          "text": "Both bind-value and model set up two-way binding pipelines with input listeners. The two handlers can fight over the value during typing, especially for number inputs. Workaround: use only model for two-way binding."
        },
        "watchOnChange": {
          "title": "watch + on:change on the same element",
          "text": "Both watch and on:change claim the change event, leading to duplicate handler execution. Workaround: use only one mechanism — watch for reactive side effects or on:change for DOM event handling."
        },
        "tBind": {
          "title": "t + bind double writer",
          "text": "Both t (i18n translation) and bind write to the element's textContent. The attribute processed last wins. Workaround: use t with interpolation parameters (t-name, t-count) or use bind alone."
        },
        "httpOnLoop": {
          "title": "HTTP verb on loop element",
          "text": "Placing an HTTP directive (get, post, etc.) directly on the loop element causes one network request per clone, since clones retain the HTTP attribute. Workaround: place the HTTP directive on a parent element."
        }
      },
      "migration": {
        "title": "Migration Notes (v1.18.0)",
        "ifGates": {
          "title": "if now gates the entire element",
          "before": "Before v1.18.0, if only controlled children visibility. Directives with higher priority than if (such as HTTP at priority 1, computed/watch at priority 2, and head directives at priority 1) would still execute on the element even when the condition was false.",
          "after": "After v1.18.0, if gates the entire element. All directives on the same element respect the if condition.",
          "check": "If you relied on a falsy if branch to still compute values or fire HTTP requests, move those directives to a separate element without an if condition."
        },
        "usePriority": {
          "title": "use priority changed to 9",
          "text": "The use directive now has an explicit priority of 9, placing it just below structural directives (10). This ensures templates are instantiated before if/each processing. This change is backward-compatible for standard usage."
        }
      }
    },
    "sse": {
      "basicTitle": "Uso di base",
      "basicText": "La direttiva sse apre una connessione EventSource verso un endpoint del server ed espone i dati ricevuti come variabile di contesto reattiva tramite l'attributo as. I payload JSON vengono parsati automaticamente; i dati non-JSON vengono memorizzati come stringa.",
      "text": "Quando il server invia dati non-JSON (testo puro, righe CSV, ecc.), la variabile as riceve la stringa grezza.",
      "attributesTitle": "Attributi",
      "col1": "Attributo",
      "col2": "Tipo",
      "col3": "Descrizione",
      "sse": "URL dell'endpoint SSE. Supporta espressioni interpolate (es: /api/{channel}).",
      "as": "Nome della variabile di contesto reattiva che riceve i dati di ogni messaggio.",
      "sseEvent": "Tipo di evento SSE con nome da ascoltare. Senza questo attributo, vengono catturati solo i messaggi senza nome (default).",
      "sseInsert": "Come i nuovi messaggi aggiornano la variabile: replace (predefinito), append (array dal più vecchio al più recente) o prepend (array dal più recente al più vecchio).",
      "sseLimit": "Lunghezza massima dell'array in modalità append o prepend. Le voci più vecchie vengono scartate quando il limite viene superato. Non ha effetto in modalità replace (emette un avviso in console).",
      "sseCredentials": "Attributo booleano. Quando presente, l'EventSource viene aperto con withCredentials: true, inviando cookie nelle richieste cross-origin.",
      "into": "Nome dello store. Quando definito, ogni messaggio viene scritto anche nello store globale con il nome specificato sotto la chiave as.",
      "error": "ID di un elemento <template> da renderizzare quando la connessione fallisce permanentemente (readyState === CLOSED).",
      "then": "Espressione eseguita dopo l'elaborazione di ogni messaggio. Riceve $event (i dati parsati).",
      "insertModesTitle": "Modalità di inserimento",
      "insertModesText": "L'attributo sse-insert controlla come i messaggi successivi aggiornano la variabile di contesto. Replace è il valore predefinito ed è ideale per stream a valore singolo come le quotazioni. Append e prepend raccolgono i messaggi in un array, limitato da sse-limit. Usare append o prepend senza sse-limit emette un avviso in console riguardo alla potenziale crescita illimitata della memoria. Impostare sse-limit in modalità replace non ha effetto ed emette anch'esso un avviso.",
      "namedEventsTitle": "Eventi con nome",
      "namedEventsText": "Per impostazione predefinita, la direttiva ascolta i messaggi SSE senza nome (l'evento message). Imposta sse-event per ascoltare un tipo di evento con nome specifico. Più elementi possono sottoscrivere diversi tipi di evento sullo stesso endpoint — ognuno apre la propria connessione EventSource.",
      "connectionStateTitle": "Stato della connessione ($sse)",
      "connectionStateText": "Ogni elemento sse espone un oggetto reattivo $sse nel suo contesto con tre proprietà booleane che riflettono il readyState dell'EventSource.",
      "stateCol1": "Proprietà",
      "stateCol2": "Tipo",
      "stateCol3": "Descrizione",
      "connecting": "true mentre l'EventSource è in stato CONNECTING (connessione iniziale o riconnessione automatica).",
      "open": "true quando la connessione è aperta e riceve messaggi.",
      "errorProp": "true solo quando la connessione è fallita permanentemente (readyState === CLOSED). Durante la riconnessione automatica, error rimane false.",
      "statesCallout": "Durante la riconnessione automatica, l'EventSource del browser passa allo stato CONNECTING. NoJS rispecchia questo comportamento: $sse.connecting diventa true, $sse.open diventa false e $sse.error rimane false. Il flag di errore si attiva solo quando la connessione non può essere ripristinata (CLOSED).",
      "liveFeedTitle": "Esempio di feed in tempo reale",
      "liveFeedText": "Combina la modalità di inserimento prepend, un limite e indicatori di stato della connessione per un feed di attività in tempo reale completo con stato di riconnessione automatica.",
      "reactiveUrlTitle": "URL reattivi",
      "reactiveUrlText": "Quando l'URL del sse contiene espressioni interpolate, la direttiva monitora i cambiamenti. Se l'URL risolto cambia, l'EventSource corrente viene chiuso e ne viene aperto uno nuovo verso l'endpoint aggiornato. In modalità append/prepend, i dati accumulati vengono reimpostati a un array vuoto. In modalità replace (predefinita), il valore precedente persiste fino all'arrivo del primo messaggio sulla nuova connessione.",
      "storeTitle": "Integrazione con lo Store",
      "storeText": "Aggiungi l'attributo into per scrivere ogni messaggio in uno store globale oltre alla variabile di contesto locale. Altri elementi ovunque nel DOM possono leggere i dati tramite $store.nomeDelloStore.",
      "errorHandlingTitle": "Gestione degli errori",
      "errorHandlingText": "Punta l'attributo error a un <template> per renderizzare contenuto di fallback quando la connessione si chiude permanentemente. Il template riceve un oggetto sintetico con un singolo campo message (\"SSE connection closed\") — non l'oggetto errore del browser. Il template di errore viene renderizzato solo quando readyState raggiunge CLOSED (chiusura terminale); non viene mai mostrato durante la riconnessione automatica.",
      "thenTitle": "Callback per messaggio",
      "thenText": "L'attributo then accetta un'espressione che viene eseguita dopo l'elaborazione di ogni messaggio e l'aggiornamento della variabile di contesto. I dati parsati del messaggio sono disponibili come $event. Usalo per effetti collaterali come incrementare contatori o avviare azioni.",
      "noLoadingTitle": "Nessun template di caricamento",
      "noLoadingText": "A differenza delle direttive HTTP (get, post), la direttiva sse non supporta un attributo di template di caricamento. Le connessioni SSE sono di lunga durata — non c'è un singolo ciclo richiesta/risposta. Usa $sse.connecting per mostrare un indicatore di stato mentre la connessione viene stabilita.",
      "authTitle": "Autenticazione",
      "authText": "L'API EventSource non supporta header personalizzati. Sono disponibili due strategie di autenticazione: token tramite query string e credenziali basate su cookie.",
      "authCallout": "L'attributo <code>sse-credentials</code> imposta <code>withCredentials: true</code> sull'EventSource, inviando cookie nelle richieste cross-origin. Il server deve rispondere con gli header CORS appropriati (<code>Access-Control-Allow-Credentials: true</code>, <code>Access-Control-Allow-Origin</code> esplicito).",
      "interceptorsNote": "Gli interceptor fetch di NoJS non si applicano alle connessioni SSE. EventSource è un'API del browser separata — l'iniezione di header, la cache e la logica di retry della pipeline fetch non sono disponibili.",
      "connectionLimitTitle": "Limiti di connessione",
      "connectionLimitText": "I browser impongono un limite di circa 6 connessioni HTTP/1.1 concorrenti per origine. Ogni elemento sse apre la propria connessione EventSource — le connessioni non vengono mai condivise né accorpate, anche quando più elementi puntano allo stesso URL. NoJS emette un avviso quando viene aperta una 6ª connessione verso la stessa origine. Per rispettare i limiti, usa HTTP/2 (che multiplexa i flussi su una singola connessione TCP), riduci il numero di elementi sse nella pagina, o chiudi le connessioni non utilizzate tramite rendering condizionale (es: una direttiva if)."
    }
  }
}
