Autore:
    Creazione:2025-09-22Ultimo aggiornamento:2026-06-14

    Nuovo Intlayer v8 - Novità

    Benvenuti in Intlayer v8! Questa release si concentra sul miglioramento della Developer Experience con il rilevamento automatico dei contenuti, sull'assicurare l'integrità dei dati tramite la validazione degli schemi e sul fornire un maggior controllo nella gestione dei dizionari.

    www.youtube.com

    Indice


    Evoluzione dei contenuti ricchi: Markdown & HTML

    Intlayer v8 apporta grandi miglioramenti nel modo in cui vengono gestiti i contenuti ricchi, introducendo i nodi HTML (che non esistevano nella v7) e unificando l'API con i nodi Markdown (che esistevano nella v7 ma sono stati potenziati).

    L'API unificata .use()

    Abbiamo introdotto il metodo .use() sia per i nodi Markdown che per quelli HTML. Questo metodo ti permette di personalizzare i tag HTML o i componenti utilizzati durante il rendering.

    • Sostituzione dei componenti: Puoi facilmente sostituire i tag HTML o i componenti personalizzati con i tuoi componenti del framework (ad esempio, sostituire <a> con NextLink o <CustomCmp> con un componente React).
    • Type Safety: Tutte le funzioni per fornire componenti sono completamente tipizzate, garantendo la ricezione delle prop corrette.

    Comportamento di rendering predefinito

    Nella v7, se non veniva definito alcun provider, i nodi Markdown venivano renderizzati come stringhe grezze, richiedendo spesso librerie esterne per il parsing.

    Nella v8, Intlayer include il proprio parser Markdown interno. Per impostazione predefinita, i nodi Markdown vengono ora renderizzati direttamente come HTML senza necessità di librerie esterne.

    Nuove utility Renderer & Provider

    Abbiamo introdotto nuove funzioni di rendering e componenti standalone per offrirti maggiore controllo al di fuori del flusso standard useIntlayer.

    • Markdown: MarkdownRenderer, useMarkdownRenderer, renderMarkdown. (Nota: MarkdownProvider esisteva nella v7 ma ora si integra con questi nuovi strumenti).
    • HTML: HTMLRenderer, useHTMLRenderer, renderHTML, HTMLProvider.

    Esempi: Strumenti di rendering Markdown

    1. Utilizzo del componente:

    tsx
    import { MarkdownRenderer } from "react-intlayer/markdown";<MarkdownRenderer  forceBlock={true}  components={{    h1: ({ children }) => <h1 className="text-2xl">{children}</h1>  }}>  {"# Il mio titolo"}</MarkdownRenderer>

    2. Utilizzo dell'hook:

    tsx
    import { useMarkdownRenderer } from "react-intlayer/markdown";const renderMarkdown = useMarkdownRenderer({  components: {    h1: ({ children }) => <h1 className="text-red-500">{children}</h1>  }});return <div>{renderMarkdown("# Il mio titolo")}</div>;

    3. Utilizzo della funzione utility:

    tsx
    import { renderMarkdown } from "react-intlayer/markdown";const html = renderMarkdown("# Il mio titolo", {  forceBlock: true});

    Esempi: Strumenti di rendering HTML

    1. Utilizzo del componente:

    tsx
    import { HTMLRenderer } from "react-intlayer/html";<HTMLRenderer  components={{    p: ({ children }) => <p className="mb-4">{children}</p>  }}>  {"<p>Ciao Mondo</p>"}</HTMLRenderer>

    2. Utilizzo dell'hook:

    tsx
    import { useHTMLRenderer } from "react-intlayer/html";const renderHTML = useHTMLRenderer({  components: {    strong: ({ children }) => <b className="font-bold">{children}</b>  }});return <div>{renderHTML("<p>Ciao <strong>Mondo</strong></p>")}</div>;

    3. Utilizzo della funzione utility:

    tsx
    import { renderHTML } from "react-intlayer/html";const html = renderHTML("<p>Ciao Mondo</p>");

    Per maggiori dettagli, consulta la Documentazione dei contenuti HTML e la Documentazione Markdown.


    File di contenuto YAML e Markdown (v8.10.0)

    Ora puoi dichiarare i contenuti direttamente utilizzando le estensioni di file .content.md e .content.yaml. Questo è perfetto per contenuti di lunga forma, blog, documentazione e politiche sulla privacy.

    Questi file sono completamente modificabili dall'Editor Visuale, fornendo un flusso di lavoro semplificato per i membri del team non tecnici.

    Per maggiori dettagli, consulta la Documentazione sui file di contenuto YAML e la Documentazione sui file di contenuto Markdown.


    Riscritture URL personalizzate

    Intlayer v8 introduce il supporto per le Riscritture URL personalizzate, che ti permettono di definire percorsi specifici per ogni locale che differiscono dalla struttura standard /locale/path. Questa è una funzionalità potente per migliorare la SEO locale e offrire un'esperienza utente più naturale per i parlanti non inglesi.

    Miglioramenti chiave nella v8:

    • Formattatori per framework: nuovi nextjsRewrite, svelteKitRewrite, reactRouterRewrite, vueRouterRewrite, solidRouterRewrite, tanstackRouterRewrite, nuxtRewrite e viteRewrite per fornire una sintassi di pattern idiomatica per ciascun router.
    • useRewriteURL Hook: Un nuovo hook lato client che corregge silenziosamente la barra degli indirizzi verso l'URL localizzato "più leggibile" senza attivare navigazioni del router.
    • Automatic SEO Redirects: Reindirizzamenti SEO automatici: i proxy integrati ora reindirizzano automaticamente gli utenti da percorsi canonici digitati manualmente (es., /fr/about) alle loro versioni localizzate più leggibili (es., /fr/a-propos).

    Esempio di configurazione:

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";import { nextjsRewrite } from "intlayer/routing";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },  routing: {    mode: "prefix-no-default",    rewrite: nextjsRewrite({      "/[locale]/about": {        fr: "/[locale]/a-propos",        es: "/[locale]/acerca-de",      },      "/[locale]/products/[id]": {        fr: "/[locale]/produits/[id]",        es: "/[locale]/productos/[id]",      },    }),  },};export default config;

    Questa funzionalità è supportata nativamente in Next.js e Vite tramite i proxy di Intlayer, e può essere facilmente integrata in altri router come TanStack Router, React Router, Vue Router, SvelteKit e Solid Router.

    Per maggiori informazioni e guide all'integrazione, vedi la documentazione su Custom URL Rewrites.


    Valori di inserzione potenziati

    Nella v8, i valori di inserzione possono ora accettare elementi React (o nodi Vue) oltre a stringhe e numeri. Questo ti permette di inserire componenti ricchi e interattivi direttamente nei tuoi template di inserzione.

    Intlayer ora gestisce in modo robusto i nodi annidati di React e Preact all'interno delle inserzioni, assicurando che strutture UI complesse siano preservate e renderizzate correttamente.

    Esempio:

    src/example.content.ts
    import { insert } from "intlayer";export default {  key: "my-key",  content: {    myInsertion: insert("Ciao {{name}}"),  },};
    tsx
    import { useIntlayer } from "next-intlayer";const { myInsertion } = useIntlayer("my-key");return (  <div>    {myInsertion({      name: 2, // numero      // oppure      name: "John", // stringa      // oppure      name: <span>John</span>, // elemento React    })}  </div>);

    Regole di Pluralizzazione Unicode CLDR (v8.8.0)

    È stato introdotto un nuovo helper per nodi plural basato sulle regole di pluralizzazione definite dal Progetto Unicode CLDR, migliorando il supporto per le lingue complesse.

    src/openings.content.ts
    import { plural, t, type Dictionary } from "intlayer";const openingsContent = {  key: "total_openings",  content: {    totalOpenings: t({      en: plural({        one: "{{count}} opening",        other: "{{count}} openings",      }),      fr: plural({        one: "{{count}} offre",        other: "{{count}} offres",      }),      it: plural({        // Added Italian translation        one: "{{count}} offerta",        other: "{{count}} offerte",      }),    }),  },} satisfies Dictionary;export default openingsContent;

    Puoi quindi passare il conteggio dinamicamente nel componente del tuo framework:

    tsx
    import type { FC } from "react";import { useIntlayer } from "react-intlayer";const OpeningsComponent: FC<{ count: number }> = ({ count }) => {  const { totalOpenings } = useIntlayer("total_openings");  return (    <div>      {/* In English:                                  */}      {/*  count=0  → "0 openings"   (other)           */}      {/*  count=1  → "1 opening"    (one)             */}      {/*  count=2  → "2 openings"   (other)           */}      {/*  count=21 → "21 openings"  (other)           */}      {/* In Italian:                                  */}      {/*  count=0  → "0 offerte"    (other)           */}      {/*  count=1  → "1 offerta"    (one)             */}      {/*  count=2  → "2 offerte"    (other)           */}      {/*  count=21 → "21 offerte"   (other)           */}      <p>{totalOpenings(count)}</p>    </div>  );};

    Per maggiori informazioni, consulta la Documentazione sulla Pluralizzazione.


    Validazione dello schema di contenuto

    Intlayer v8 introduce la validazione degli schemi per i dizionari. Ora puoi definire schemi di validazione riutilizzabili nella tua configurazione utilizzando Zod e applicarli ai tuoi file di contenuto. Questo garantisce che i tuoi contenuti rispettino sempre la struttura prevista, intercettando gli errori in fase di build.

    1. Definire gli schemi

    Definisci i tuoi schemi in intlayer.config.ts:

    intlayer.config.ts
    import { z } from "zod";export default {  schemas: {    "seo-metadata": z.object({      title: z.string().min(50).max(60),      description: z.string().min(150).max(160),    }),  },};

    2. Applicare gli schemi ai dizionari

    Fai riferimento alla chiave dello schema nella definizione del tuo dizionario:

    src/example.content.ts
    import { type Dictionary } from "intlayer";const aboutPageMetaContent = {  key: "about-page-meta",  schema: "seo-metadata", // <--  content: {    title: "Informazioni sulla nostra azienda - Scopri di più su di noi",    description: "Scopri la missione, i valori e il team della nostra azienda.",  },} satisfies Dictionary;export default aboutPageMetaContent;

    Se il contenuto non corrisponde allo schema (ad esempio, il titolo è troppo corto), il processo di build genererà un errore.


    TypeScript: Accessori Primitivi IntlayerNode

    Il tipo IntlayerNode è stato aggiornato per consentire di chiamare metodi JavaScript primitivi direttamente sui nodi di contenuto. Questo rende possibile interagire con il tuo contenuto localizzato direttamente come se fosse una stringa, un numero, un booleano o un array primitivo standard.

    Supportato su React, Preact, Solid, Svelte, Vue e Angular.

    Esempio Stringa

    typescript
    content.placeholder; // Restituisce IntlayerNode<string>content.placeholder.value; // Restituisce stringacontent.placeholder.toString(); // Restituisce stringacontent.placeholder.toLowerCase(); // Restituisce stringaString(content.placeholder); // Restituisce stringacontent.placeholder.toUpperCase(); // Restituisce stringa in maiuscolocontent.placeholder.replace("a", "b"); // Restituisce stringa modificata

    Esempio Array

    typescript
    content.myArrayOfString             // Restituisce IntlayerNode<Array<string>>content.myArrayOfString.find(...)   // Restituisce elementocontent.myArrayOfString.join(', ')  // Restituisce stringa unita

    Rilevamento automatico del contenuto potenziato

    Nella v8, Intlayer rileva in modo intelligente la sintassi Markdown, i tag HTML e le inserzioni di variabili nelle stringhe di contenuto. Questo significa che spesso puoi omettere funzioni helper come md(), html(), o insert().

    Questo comportamento è abilitato per impostazione predefinita. Ora puoi perfezionare questo rilevamento globalmente nel tuo intlayer.config.ts o per singolo dizionario.

    Controllo granulare

    Puoi abilitare o disabilitare tipi specifici di trasformazioni:

    intlayer.config.ts
    export default {  dictionary: {    // contentAutoTransformation: false (default)    contentAutoTransformation: {      markdown: true,      html: true,      insertion: false, // Disabilita il rilevamento automatico delle inserzioni    },  },};

    Comportamento v7 (Avvolgimento manuale):

    src/example.content.ts
    import { md, insert } from "intlayer";export default {  key: "my-key",  content: {    myMarkdown: md("## Hello World"),    myInsertion: insert("Ciao {{name}}"),  },};

    Comportamento v8 (Rilevamento automatico):

    src/example.content.ts
    export default {  key: "my-key",  contentAutoTransformation: true, // Può anche essere impostato nella definizione del dizionario o globalmente in intlayer.config.ts  content: {    myMarkdown: "## Hello World", // Rilevato automaticamente come Markdown    myHTML: "<p>Hello World</p>", // Rilevato automaticamente come HTML    myInsertion: "Ciao {{name}}", // Rilevato automaticamente come Inserzione  },};

    Il risultato JSON sottostante rimane lo stesso, preservando le ricche informazioni di tipo necessarie per il rendering:

    json
    {  "key": "my-key",  "content": {    "myMarkdown": {      "nodeType": "markdown",      "markdown": "## Hello World"    },    "myHTML": {      "nodeType": "html",      "html": "<p>Hello World</p>"    },    "myInsertion": {      "nodeType": "insertion",      "insertion": "Ciao {{name}}"    }  }}

    Localizzazione: nuovo hook useIntl

    Un nuovo hook useIntl() è ora disponibile in React, Next.js e Vue. Fornisce un oggetto Intl legato alla locale che utilizza automaticamente la lingua corrente per formattare numeri, date e altro, senza bisogno di passare manualmente la locale.

    tsx
    import { useIntl } from "next-intlayer";const intl = useIntl();const formattedPrice = new intl.NumberFormat({  style: "currency",  currency: "USD",}).format(123.45);

    Tooling: Miglioramenti dell'estensione VSCode

    L'estensione Intlayer per VSCode riceve aggiornamenti importanti nella v8 per semplificare il tuo flusso di lavoro di internazionalizzazione:

    • Tempo di avvio: Miglioramenti delle prestazioni all'apertura di un progetto.
    • Caching: Layer di caching migliorato per validazione e autocompletamento quasi istantanei.
    • Rilevamento chiavi inutilizzate e chiavi duplicate: Nuove funzionalità per rilevare automaticamente chiavi inutilizzate e chiavi duplicate nei tuoi dizionari, aiutandoti a mantenere i tuoi contenuti ordinati ed efficienti.

    Tooling: C++ Watcher & LSP basato su OXC (v8.12.0)

    Intlayer v8.12.0 apporta importanti miglioramenti alla developer experience:

    • Parcel Watcher: Il watcher dei contenuti è stato migrato da chokidar a @parcel/watcher, sfruttando il file watching nativo in C++ per fornire aggiornamenti più rapidi e un consumo di memoria significativamente inferiore.
    • Nuovo Language Server Protocol (LSP): È ora disponibile un LSP completamente nuovo. Costruito con parsing basato su OXC, aiuta il tuo IDE e gli agenti AI a collegare senza soluzione di continuità le chiamate useIntlayer('my-key') con i loro file .content corrispondenti, e viceversa.

    Per maggiori dettagli, consulta la Documentazione LSP.


    Ottimizzazioni del compilatore

    Intlayer v8 include un nuovo layer di caching per il compilatore Markdown e HTML. Questo garantisce che stringhe di contenuto identiche con la stessa configurazione vengano analizzate solo una volta, riducendo significativamente l'overhead durante i re-render o quando lo stesso contenuto è utilizzato in più punti.

    babel.config.js
      const {  intlayerExtractBabelPlugin,  intlayerOptimizeBabelPlugin,  getExtractPluginOptions,  getOptimizePluginOptions,} = require('@intlayer/babel');module.exports = {  presets: ['next/babel'],  plugins: [    // Estrai il contenuto dai componenti nei dizionari    [intlayerExtractBabelPlugin, getExtractPluginOptions()],    // Ottimizza le importazioni sostituendo useIntlayer con importazioni dirette dei dizionari    [intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],  ],};

    Ottimizzazioni sperimentali della build: Minify & Purge (v8.7.0)

    Intlayer v8.7.0 introduce nuove funzionalità di build sperimentali nel tuo intlayer.config.ts progettate per ottimizzare il tuo bundle di produzione:

    • Minificazione del dizionario: Minifica i file del dizionario per ridurne le dimensioni.
    • Pulizia delle chiavi inutilizzate: Scansiona e rimuove le chiavi di traduzione inutilizzate dai dizionari, rinominando le chiavi attive con caratteri brevi (es. "products" -> "a", "pricing" -> "b"). Questo riduce le dimensioni del bundle fino al 5%.
    • Disabilita i controlli TypeScript: Accelera le build disabilitando il controllo dei tipi TypeScript durante la fase di compilazione.
    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH],    defaultLocale: Locales.ENGLISH,  },  dictionary: {    importMode: "dynamic",  },  build: {    /**     * Minify the dictionaries to reduce the bundle size.     */    minify: true,    /**     * Purge the unused keys in dictionaries     */    purge: true,    /**     * Indicates if the build should check TypeScript types     */    checkTypes: false,  },};export default config;

    Flessibilità: Modalità di importazione unificata

    La proprietà booleana live è stata deprecata a favore di una proprietà più completa, importMode. Questo consente di definire esplicitamente come devono essere caricati i dizionari: staticamente, dinamicamente o tramite sincronizzazione live.

    Modalità

    • static (Predefinito): Il dizionario viene incluso nel bundle al momento della build. Ideale per le prestazioni.
    • dynamic: Il dizionario viene caricato a runtime (es. tramite fetch JSON o suspense).
    • fetch: Il dizionario viene recuperato dal CMS/Server a runtime e sincronizzato.

    Migrazione:

    Configurazione v7 Configurazione v8
    live: true importMode: 'fetch'
    live: false importMode: 'static' (o 'dynamic')

    Nota: In Intlayer v8, la proprietà importMode è stata spostata dalla configurazione build alla configurazione dictionary in intlayer.config.ts. Questo ti permette di definire una modalità di importazione predefinita per tutti i tuoi dizionari, pur potendo sovrascrittore per singolo dizionario.

    Esempio di configurazione globale:

    intlayer.config.ts
    export default {  dictionary: {    importMode: "dynamic", // Global default  },  // ...};

    Esempio di dizionario:

    src/example.content.ts
    export default {    key: 'my-key',    importMode: "fetch", // Overrides global config    content: { ... }}

    Controllo della posizione del dizionario

    La v8 introduce la proprietà location per gestire esplicitamente dove risiedono i dizionari e come si sincronizzano. Questo è particolarmente utile per workflow ibridi che coinvolgono sia file locali sia contenuti CMS remoti.

    Opzioni

    • local: Il dizionario esiste solo localmente. Non verrà pushato sul CMS remoto.
    • remote: Il dizionario è gestito remotamente. Una volta pushato sul CMS, verrà scollegato da quello locale. Il dizionario remoto sarà pullato dal CMS.
    • local_and_remote: Il dizionario esiste in entrambi i luoghi. Le modifiche locali vengono pushate e le modifiche remote vengono pullate (sincronizzate).

    Esempio:

    src/example.content.ts
    export default {    key: 'my-key',    location: "local", // Mantieni questo dizionario solo locale    content: { ... }}

    Separazione della Configurazione del Sistema

    Intlayer v8 separa la configurazione delle sorgenti di contenuto dai percorsi interni di sistema e di output. Questo snellisce la proprietà content e rende chiaro quali impostazioni sono destinate alla gestione dall'utente e quali sono gestite dal sistema Intlayer.

    Le seguenti proprietà sono state spostate da content a una nuova proprietà system in intlayer.config.ts:

    • dictionariesDir
    • moduleAugmentationDir
    • unmergedDictionariesDir
    • typesDir
    • mainDir
    • configDir
    • cacheDir
    • outputFilesPatternWithPath

    Comportamento v7:

    intlayer.config.ts
    export default {  content: {    contentDir: ["src"],    dictionariesDir: ".intlayer/dictionary", // Mescolato con la configurazione sorgente  },};

    Comportamento v8:

    intlayer.config.ts
    export default {  content: {    contentDir: ["src"],  },  system: {    dictionariesDir: ".intlayer/dictionary", // Separato chiaramente  },};

    Separazione delle directory di contenuto e codice

    Intlayer v8 separa la configurazione per i file di definizione dei contenuti dalla configurazione per la trasformazione del codice. Questo permette un watch e una scansione più precisi, migliorando le prestazioni della build.

    In precedenza, contentDir veniva usato sia per il watch dei file .content.* sia per la scansione del codice per le chiamate useIntlayer. Ora:

    • contentDir: specificamente per i file di dichiarazione dei contenuti.
    • codeDir: specificamente per il codice della tua applicazione che necessita di trasformazioni (es. pruning, ottimizzazione).

    Migrazione:

    Se in precedenza avevi impostato contentDir, Intlayer v8 lo userà anche come impostazione predefinita per codeDir, ma registrerà un avviso. Dovresti definire esplicitamente codeDir nella tua configurazione.

    Comportamento v7:

    intlayer.config.ts
    export default {  content: {    contentDir: ["src", "@packages/design-system"], // Usato sia per il contenuto sia per il codice  },};

    Comportamento v8:

    intlayer.config.ts
    export default {  content: {    contentDir: ["src/content", "@packages/design-system"], // Osserva solo i file src/content/*.content.* qui e i file @packages/design-system/dist/*.content.*    codeDir: ["src", "@packages/design-system"], // Scansiona solo il codice per la trasformazione qui e i file @packages/design-system/src/*.content.*  },};

    Framework: Miglioramenti per Svelte

    Il contenuto Markdown e HTML in Svelte ora viene automaticamente convertito in HTML quando viene serializzato. Questo rende molto più semplice l'uso con la sintassi {@html} di Svelte, poiché ora puoi semplicemente passare direttamente il nodo di contenuto.


    Supporto Angular: Vite Bundler (v8.11.0)

    Per gli utenti Angular, Intlayer ora supporta nativamente il bundler Vite tramite un nuovo plugin esbuild personalizzato, accelerando i tempi di sviluppo e di build.

    Per i dettagli sulla configurazione, consulta la Documentazione dell'ambiente Angular.


    Generazione della Sitemap (v8.6.0)

    Intlayer ora genera automaticamente le sitemap in base alle tue locali e alla modalità di routing. Questo è particolarmente utile per l'ottimizzazione SEO in architetture di router come TanStack Router:

    src/routes/sitemap.xml.ts
    import { createFileRoute } from "@tanstack/react-router";import { generateSitemap } from "intlayer";const SITE_URL = (  import.meta.env.VITE_SITE_URL ?? "http://localhost:3000").replace(/\/$/, "");export const Route = createFileRoute("/sitemap.xml")({  server: {    handlers: {      GET: async () => {        const sitemap = generateSitemap(          [            { path: "/", changefreq: "daily", priority: 1.0 },            { path: "/about", changefreq: "monthly", priority: 0.8 },          ],          { siteUrl: SITE_URL }        );        return new Response(sitemap, {          headers: { "Content-Type": "application/xml" },        });      },    },  },});

    Note di migrazione dalla v7

    Modifiche alla configurazione

    • Proprietà live: La proprietà live nei dizionari è stata rimossa. Usa importMode: 'fetch' al suo posto.
    • importMode: La proprietà build.importMode nella configurazione è stata deprecata. Usa dictionary.importMode al suo posto.
    • contentDir e codeDir: contentDir è ora specificamente per i file di contenuto. È stata aggiunta una nuova proprietà codeDir per la trasformazione del codice. Se codeDir non è impostato, Intlayer farà fallback su contentDir e registrerà un warning.
    • Validazione dello schema: Per usare la nuova funzionalità schema, assicurati di avere zod installato nel tuo progetto.