---
createdAt: 2025-09-22
updatedAt: 2026-01-26
title: Nuevo Intlayer v8 - ¿Qué hay de nuevo?
description: Descubre qué hay de nuevo en Intlayer v8. Mejoras importantes en la experiencia del desarrollador, validación de contenido y gestión de diccionarios.
keywords:
  - Intlayer
  - CMS
  - Experiencia del Desarrollador
  - Características
  - React
  - Next.js
  - JavaScript
  - TypeScript
youtubeVideo: https://www.youtube.com/watch?v=ia6JmVf-kkU
slugs:
  - doc
  - releases
  - v8
---

# Nuevo Intlayer v8 - ¿Qué hay de nuevo?

¡Bienvenido a Intlayer v8! Esta versión se centra en mejorar la experiencia del desarrollador con la detección automática de contenido, garantizar la integridad de los datos con la validación de esquemas y proporcionar más control sobre la gestión de diccionarios.

<iframe
  src="https://www.youtube.com/embed/ia6JmVf-kkU"
  className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
  title="Demo Video - New Intlayer v8 - What's new?"
  sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
  loading="lazy"
/>

## Tabla de contenidos

<TOC levels={[2]} maxDepth={1} />

---

## Evolución del Contenido Enriquecido: Markdown y HTML

Intlayer v8 aporta mejoras importantes en la forma en que se maneja el contenido enriquecido, introduciendo **nodos HTML** (que no existían en v7) y unificando la API con **nodos Markdown** (que existían en v7 pero han sido mejorados).

### La API unificada `.use()`

Introdujimos el método `.use()` tanto para los nodos Markdown como para los HTML. Este método le permite personalizar las etiquetas HTML o los componentes utilizados durante el renderizado.

- **Reemplazo de componentes**: Puede reemplazar fácilmente etiquetas HTML o componentes personalizados con sus propios componentes de framework (por ejemplo, reemplazar `<a>` con `NextLink` o `<CustomCmp>` con un componente React).
- **Seguridad de tipos**: Todas las funciones para proporcionar componentes están completamente tipadas, lo que garantiza que reciba las props correctas.

### Comportamiento de renderizado por defecto

En la v7, si no se definía ningún proveedor, los nodos Markdown se renderizaban como cadenas de texto planas, lo que a menudo requería bibliotecas externas para analizarlos.

**En la v8, Intlayer incluye su propio analizador interno de Markdown.** Por defecto, los nodos Markdown ahora se renderizan directamente como HTML sin necesidad de bibliotecas externas.

### Nuevas utilidades de renderizado y proveedor

Hemos introducido nuevas funciones y componentes de renderizado independientes para darle más control fuera del flujo estándar de `useIntlayer`.

- **Markdown**: `MarkdownRenderer`, `useMarkdownRenderer`, `renderMarkdown`. (Nota: `MarkdownProvider` existía en v7 pero ahora se integra con estas nuevas herramientas).
- **HTML**: `HTMLRenderer`, `useHTMLRenderer`, `renderHTML`, `HTMLProvider`.

#### Ejemplos: Herramientas de renderizado de Markdown

<Tabs group='framework'>
  <Tab label="React / Next.js" value="react">

    **1. Usando el componente:**

    ```tsx
    import { MarkdownRenderer } from "react-intlayer";

    <MarkdownRenderer
      forceBlock={true}
      components={{
        h1: ({ children }) => <h1 className="text-2xl">{children}</h1>
      }}
    >
      {"# My Title"}
    </MarkdownRenderer>
    ```

    **2. Usando el hook:**

    ```tsx
    import { useMarkdownRenderer } from "react-intlayer";

    const renderMarkdown = useMarkdownRenderer({
      components: {
        h1: ({ children }) => <h1 className="text-red-500">{children}</h1>
      }
    });

    return <div>{renderMarkdown("# My Title")}</div>;
    ```

    **3. Usando la función de utilidad:**

    ```tsx
    import { renderMarkdown } from "react-intlayer";

    const html = renderMarkdown("# My Title", {
      forceBlock: true
    });
    ```

  </Tab>
  <Tab label="Vue" value="vue">

    **1. Usando el componente:**

    ```vue
    <script setup>
    import { MarkdownRenderer } from "vue-intlayer";
    </script>

    <template>
      <MarkdownRenderer :forceBlock="true" content="# My Title" />
    </template>
    ```

  </Tab>
  <Tab label="Svelte" value="svelte">

    **1. Usando el componente:**

    ```svelte
    <script>
      import { MarkdownRenderer } from "svelte-intlayer";
    </script>

    <MarkdownRenderer forceBlock={true} value="# My Title" />
    ```

    **2. Usando el hook:**

    ```svelte
    <script>
      import { useMarkdownRenderer } from "svelte-intlayer";
      const render = useMarkdownRenderer();
    </script>

    {@html render("# My Title")}
    ```

    **3. Usando la función de utilidad:**

    ```svelte
    <script>
      import { renderMarkdown } from "svelte-intlayer";
    </script>

    {@html renderMarkdown("# My Title")}
    ```

  </Tab>
  <Tab label="Angular" value="angular">

    **1. Usando el servicio:**

    ```typescript
    import { Component } from "@angular/core";
    import { IntlayerMarkdownService } from "angular-intlayer";

    @Component({ ... })
    export class MyComponent {
      constructor(private markdownService: IntlayerMarkdownService) {}

      render(markdown: string) {
        return this.markdownService.renderMarkdown(markdown);
      }
    }
    ```

  </Tab>
  <Tab label="Solid" value="solid">

    **1. Usando el componente:**

    ```tsx
    import { MarkdownRenderer } from "solid-intlayer";

    <MarkdownRenderer forceBlock={true}>
      {"# My Title"}
    </MarkdownRenderer>
    ```

    **2. Usando el hook:**

    ```tsx
    import { useMarkdownRenderer } from "solid-intlayer";

    const render = useMarkdownRenderer();

    return <div>{render("# My Title")}</div>;
    ```

    **3. Usando la función de utilidad:**

    ```tsx
    import { renderMarkdown } from "solid-intlayer";

    return <div>{renderMarkdown("# My Title")}</div>;
    ```

  </Tab>
  <Tab label="Preact" value="preact">

    **1. Usando el componente:**

    ```tsx
    import { MarkdownRenderer } from "preact-intlayer";

    <MarkdownRenderer forceBlock={true}>
      {"# My Title"}
    </MarkdownRenderer>
    ```

    **2. Usando el hook:**

    ```tsx
    import { useMarkdownRenderer } from "preact-intlayer";

    const render = useMarkdownRenderer();

    return <div>{render("# My Title")}</div>;
    ```

    **3. Usando la función de utilidad:**

    ```tsx
    import { renderMarkdown } from "preact-intlayer";

    return <div>{renderMarkdown("# My Title")}</div>;
    ```

  </Tab>
</Tabs>

#### Ejemplos: Herramientas de renderizado HTML

<Tabs group='framework'>
  <Tab label="React / Next.js" value="react">

    **1. Usando el componente:**

    ```tsx
    import { HTMLRenderer } from "react-intlayer";

    <HTMLRenderer
      components={{
        p: ({ children }) => <p className="mb-4">{children}</p>
      }}
    >
      {"<p>Hello World</p>"}
    </HTMLRenderer>
    ```

    **2. Usando el hook:**

    ```tsx
    import { useHTMLRenderer } from "react-intlayer";

    const renderHTML = useHTMLRenderer({
      components: {
        strong: ({ children }) => <b className="font-bold">{children}</b>
      }
    });

    return <div>{renderHTML("<p>Hello <strong>World</strong></p>")}</div>;
    ```

    **3. Usando la función de utilidad:**

    ```tsx
    import { renderHTML } from "react-intlayer";

    const html = renderHTML("<p>Hello World</p>");
    ```

  </Tab>
  <Tab label="Vue" value="vue">

    **1. Usando el componente:**

    ```vue
    <script setup>
    import { HTMLRenderer } from "vue-intlayer";
    </script>

    <template>
      <HTMLRenderer content="<p>Hello World</p>" />
    </template>
    ```

  </Tab>
  <Tab label="Svelte" value="svelte">

    **1. Usando el componente:**

    ```svelte
    <script>
      import { HTMLRenderer } from "svelte-intlayer";
    </script>

    <HTMLRenderer value="<p>Hello World</p>" />
    ```

    **2. Usando el hook:**

    ```svelte
    <script>
      import { useHTMLRenderer } from "svelte-intlayer";
      const render = useHTMLRenderer();
    </script>

    {@html render("<p>Hello World</p>")}
    ```

    **3. Usando la función de utilidad:**

    ```svelte
    <script>
      import { renderHTML } from "svelte-intlayer";
    </script>

    {@html renderHTML("<p>Hello World</p>")}
    ```

  </Tab>
  <Tab label="Angular" value="angular">

    **1. Uso directo:**

    En Angular, puede utilizar el enlace estándar `[innerHTML]`.

    ```html
    <div [innerHTML]="'<p>Hello World</p>'"></div>
    ```

  </Tab>
  <Tab label="Solid" value="solid">

    **1. Usando el componente:**

    ```tsx
    import { HTMLRenderer } from "solid-intlayer";

    <HTMLRenderer>
      {"<p>Hello World</p>"}
    </HTMLRenderer>
    ```

    **2. Usando el hook:**

    ```tsx
    import { useHTMLRenderer } from "solid-intlayer";

    const render = useHTMLRenderer();

    return <div>{render("<p>Hello World</p>")}</div>;
    ```

    **3. Usando la función de utilidad:**

    ```tsx
    import { renderHTML } from "solid-intlayer";

    return <div>{renderHTML("<p>Hello World</p>")}</div>;
    ```

  </Tab>
  <Tab label="Preact" value="preact">

    **1. Usando el componente:**

    ```tsx
    import { HTMLRenderer } from "preact-intlayer";

    <HTMLRenderer>
      {"<p>Hello World</p>"}
    </HTMLRenderer>
    ```

    **2. Usando el hook:**

    ```tsx
    import { useHTMLRenderer } from "preact-intlayer";

    const render = useHTMLRenderer();

    return <div>{render("<p>Hello World</p>")}</div>;
    ```

    **3. Usando la función de utilidad:**

    ```tsx
    import { renderHTML } from "preact-intlayer";

    return <div>{renderHTML("<p>Hello World</p>")}</div>;
    ```

  </Tab>
</Tabs>

Para más detalles, consulte la [Documentación de Contenido HTML](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/html.md) y la [Documentación de Markdown](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/markdown.md).

---

## Reescrituras de URL personalizadas

Intlayer v8 introduce el soporte para **Reescrituras de URL personalizadas**, lo que le permite definir rutas específicas de locale que difieren de la estructura estándar `/locale/path`. Esta es una característica poderosa para mejorar el SEO local y proporcionar una experiencia de usuario más natural para los hablantes no ingleses.

**Mejoras clave en la v8:**

- **Formateadores de framework**: Nuevos `nextjsRewrite`, `svelteKitRewrite`, `reactRouterRewrite`, `vueRouterRewrite`, `solidRouterRewrite`, `tanstackRouterRewrite`, `nuxtRewrite` y `viteRewrite` para proporcionar una sintaxis de patrón idiomática para cada enrutador.
- **Hook `useRewriteURL`**: Un nuevo hook del lado del cliente que corrige silenciosamente la barra de direcciones a la URL localizada "bonita" sin disparar navegaciones del enrutador.
- **Redirecciones SEO automáticas**: Los proxies integrados ahora redirigen automáticamente a los usuarios de rutas canónicas escritas manualmente (por ejemplo, `/fr/about`) a sus versiones localizadas más bonitas (por ejemplo, `/fr/a-propos`).

**Ejemplo de configuración:**

<Tabs group='routers'>
  <Tab label="Next.js" value="nextjs">

    ```typescript fileName="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;
    ```

  </Tab>
    <Tab label="React Router" value="reactrouter">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { reactRouterRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-all",
        rewrite: reactRouterRewrite({
          "/:locale/about": {
            fr: "/:locale/a-propos",
            es: "/:locale/acerca-de",
          },
          "/:locale/products/:id": {
            fr: "/:locale/produits/:id",
            es: "/:locale/productos/:id",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
  <Tab label="Vite (Vue, Solid, Svelte)" value="vite">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { viteRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-all",
        rewrite: viteRewrite({
          "/:locale/about": {
            fr: "/:locale/a-propos",
            es: "/:locale/acerca-de",
          },
          "/:locale/products/:id": {
            fr: "/:locale/produits/:id",
            es: "/:locale/productos/:id",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
  <Tab label="Nuxt" value="nuxt">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { nuxtRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-all",
        rewrite: nuxtRewrite({
          "/[locale]/about": {
            fr: "/[locale]/a-propos",
            es: "/[locale]/acerca-de",
          },
          "/[locale]/products/[id]": {
            fr: "/[locale]/produits/[id]",
            es: "/[locale]/productos/[id]",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
  <Tab label="SvelteKit" value="sveltekit">

    ```typescript fileName="intlayer.config.ts"
    import { Locales, type IntlayerConfig } from "intlayer";
    import { svelteKitRewrite } from "intlayer/routing";

    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
        defaultLocale: Locales.ENGLISH,
      },
      routing: {
        mode: "prefix-all",
        rewrite: svelteKitRewrite({
          "/[locale]/about": {
            fr: "/[locale]/a-propos",
            es: "/[locale]/acerca-de",
          },
          "/[locale]/products/[id]": {
            fr: "/[locale]/produits/[id]",
            es: "/[locale]/productos/[id]",
          },
        }),
      },
    };

    export default config;
    ```

  </Tab>
</Tabs>

Esta característica es compatible de forma nativa en **Next.js** y **Vite** a través de los proxies de Intlayer, y puede integrarse fácilmente en otros enrutadores como **TanStack Router**, **React Router**, **Vue Router**, **SvelteKit** y **Solid Router**.

Para más información y guías de integración, consulte la [Documentación de Reescrituras de URL Personalizadas](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/custom_url_rewrites.md).

---

### Valores de inserción mejorados

En la v8, los valores de inserción ahora pueden **aceptar elementos React (o nodos Vue)** además de cadenas y números. Esto le permite inyectar componentes enriquecidos e interactivos directamente en sus plantillas de inserción.

Intlayer ahora maneja de forma robusta los nodos anidados de React y Preact dentro de las inserciones, garantizando que las estructuras complejas de la interfaz de usuario se preserven y se rendericen correctamente.

**Ejemplo:**

```typescript fileName="src/example.content.ts"
import { insert } from "intlayer";

export default {
  key: "my-key",
  content: {
    myInsertion: insert("Hi {{name}}"),
  },
};
```

<Tabs group='framework'>
  <Tab label="Next.js" value="nextjs">

    ```tsx
    import { useIntlayer } from "next-intlayer";

    const { myInsertion } = useIntlayer("my-key");

    return (
      <div>
        {myInsertion({
          name: 2, // número
          // o
          name: "John", // cadena
          // o
          name: <span>John</span>, // elemento React
        })}
      </div>
    );
    ```

  </Tab>
  <Tab label="React" value="react">

    ```tsx
    import { useIntlayer } from "react-intlayer";

    const { myInsertion } = useIntlayer("my-key");

    return (
      <div>
        {myInsertion({
          name: 2, // número
          // o
          name: "John", // cadena
          // o
          name: <span>John</span>, // elemento React
        })}
      </div>
    );
    ```

  </Tab>
  <Tab label="Vue" value="vue">

    ```vue
    <script setup>
    import { h } from "vue";
    import { useIntlayer } from "vue-intlayer";

    const { myInsertion } = useIntlayer("my-key");
    </script>

    <template>
      <div>
        <component
          :is="myInsertion({
            name: 2,
            // o
            name: 'John',
            // o
            name: h('span', 'John'),
          })"
        />
      </div>
    </template>
    ```

  </Tab>
  <Tab label="Preact" value="preact">

    ```tsx
    import { useIntlayer } from "preact-intlayer";

    const { myInsertion } = useIntlayer("my-key");

    return (
      <div>
        {myInsertion({
          name: 2, // número
          // o
          name: "John", // cadena
          // o
          name: <span>John</span>, // elemento Preact
        })}
      </div>
    );
    ```

  </Tab>
  <Tab label="Solid" value="solid">

    ```tsx
    import { useIntlayer } from "solid-intlayer";

    const { myInsertion } = useIntlayer("my-key");

    return (
      <div>
        {myInsertion({
          name: 2, // número
          // o
          name: "John", // cadena
          // o
          name: <span>John</span>, // elemento Solid
        })}
      </div>
    );
    ```

  </Tab>
  <Tab label="Svelte" value="svelte">

    ```svelte
    <script>
      import { useIntlayer } from "svelte-intlayer";

      const { myInsertion } = useIntlayer("my-key");
    </script>

    <div>
      {myInsertion({
        name: 2, // número
        // o
        name: "John", // cadena
      })}
    </div>
    ```

  </Tab>
  <Tab label="Angular" value="angular">

    ```typescript
    import { Component } from "@angular/core";
    import { useIntlayer } from "angular-intlayer";

    @Component({
      selector: "app-insertion-example",
      template: `
        <div>
          {{ content().myInsertion({
            name: 'John'
          }) }}
        </div>
      `,
    })
    export class InsertionExampleComponent {
      content = useIntlayer("my-key");
    }
    ```

  </Tab>
</Tabs>

## Validación del esquema de contenido

Intlayer v8 introduce la validación de esquemas para diccionarios. Ahora puede definir esquemas de validación reutilizables en su configuración utilizando Zod y aplicarlos a sus archivos de contenido. Esto garantiza que su contenido siempre se adhiera a la estructura esperada, detectando errores en el momento de la construcción.

### 1. Definir esquemas

Defina sus esquemas en `intlayer.config.ts`:

```typescript fileName="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. Aplicar esquemas a los diccionarios

Haga referencia a la clave del esquema en la definición de su diccionario:

```typescript fileName="src/example.content.ts"
import { type Dictionary } from "intlayer";

const aboutPageMetaContent = {
  key: "about-page-meta",
  schema: "seo-metadata", // <--
  content: {
    title: "About Our Company - Learn More About Us",
    description: "Discover our company's mission, values, and team.",
  },
} satisfies Dictionary<"seo-metadata">;

export default aboutPageMetaContent;
```

Si el contenido no coincide con el esquema (por ejemplo, el título es demasiado corto), el proceso de construcción arrojará un error.

---

### Detección automática de contenido mejorada

En la v8, Intlayer detecta inteligentemente la sintaxis Markdown, las etiquetas HTML y las inserciones de variables en sus cadenas de contenido. Esto significa que a menudo puede omitir funciones auxiliares como `md()`, `html()` o `insert()`.

Este comportamiento está habilitado por defecto. Ahora puede ajustar esta detección globalmente en su `intlayer.config.ts` o por diccionario.

#### Control granular

Puede habilitar o deshabilitar tipos específicos de transformaciones:

```typescript fileName="intlayer.config.ts"
export default {
  dictionary: {
    // contentAutoTransformation: false (predeterminado)
    contentAutoTransformation: {
      markdown: true,
      html: true,
      insertion: false, // Deshabilitar la detección automática de inserciones
    },
  },
};
```

**Comportamiento v7 (envoltura manual):**

```typescript fileName="src/example.content.ts"
import { md, insert } from "intlayer";

export default {
  key: "my-key",
  content: {
    myMarkdown: md("## Hello World"),
    myInsertion: insert("Hi {{name}}"),
  },
};
```

**Comportamiento v8 (detección automática):**

```typescript fileName="src/example.content.ts"
export default {
  key: "my-key",
  contentAutoTransformation: true, // También puede ser configurado por definición de diccionario o globalmente en intlayer.config.ts
  content: {
    myMarkdown: "## Hello World", // Detectado automáticamente como Markdown
    myHTML: "<p>Hello World</p>", // Detectado automáticamente como HTML
    myInsertion: "Hi {{name}}", // Detectado automáticamente como Inserción
  },
};
```

El resultado JSON subyacente sigue siendo el mismo, preservando la rica información de tipo necesaria para el renderizado:

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

---

## Localización: nuevo hook `useIntl`

Un nuevo hook `useIntl()` está ahora disponible en React, Next.js y Vue. Proporciona un objeto `Intl` vinculado al locale que utiliza automáticamente el idioma actual para formatear números, fechas y más, sin necesidad de pasar manualmente el locale.

<Tabs group='framework'>
  <Tab label="Next.js" value="nextjs">

    ```tsx
    import { useIntl } from "next-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    ```

  </Tab>
  <Tab label="React" value="react">

    ```tsx
    import { useIntl } from "react-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    ```

  </Tab>
  <Tab label="Vue" value="vue">

    ```vue
    <script setup>
    import { useIntl } from "vue-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    </script>
    ```

  </Tab>
  <Tab label="Preact" value="preact">

    ```tsx
    import { useIntl } from "preact-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    ```

  </Tab>
  <Tab label="Solid" value="solid">

    ```tsx
    import { useIntl } from "solid-intlayer";

    const intl = useIntl();

    const formattedPrice = new intl.NumberFormat({
      style: "currency",
      currency: "USD",
    }).format(123.45);
    ```

  </Tab>
  <Tab label="Svelte" value="svelte">

    ```svelte
    <script>
      import { useIntl } from "svelte-intlayer";

      const intl = useIntl();

      const formattedPrice = new intl.NumberFormat({
        style: "currency",
        currency: "USD",
      }).format(123.45);
    </script>
    ```

  </Tab>
  <Tab label="Angular" value="angular">

    ```typescript
    import { Component, computed } from "@angular/core";
    import { useIntl } from "angular-intlayer";

    @Component({
      selector: "app-intl-example",
      template: `<div>{{ formattedPrice() }}</div>`,
    })
    export class IntlExampleComponent {
      intl = useIntl();

      formattedPrice = computed(() =>
        new (this.intl().NumberFormat)({
          style: "currency",
          currency: "USD",
        }).format(123.45)
      );
    }
    ```

  </Tab>
</Tabs>

---

## Herramientas: Mejoras en la extensión de VSCode

La extensión de Intlayer para VSCode recibe actualizaciones importantes en la v8 para agilizar su flujo de trabajo de internacionalización:

- **Tiempo de inicio**: Mejoras de rendimiento al abrir un proyecto.
- **Almacenamiento en caché**: Capa de caché mejorada para una validación y un autocompletado casi instantáneos.
- **Detección de claves no utilizadas y duplicadas**: Nuevas funciones para detectar automáticamente **claves no utilizadas** y **claves duplicadas** en sus diccionarios, lo que le ayuda a mantener su contenido limpio y eficiente.

---

## Optimizaciones del compilador

Intlayer v8 incluye una nueva capa de almacenamiento en caché para el compilador de Markdown y HTML. Esto garantiza que las cadenas de contenido idénticas con la misma configuración solo se analicen una vez, lo que reduce significativamente la sobrecarga durante los re-renderizados o cuando se utiliza el mismo contenido en varios lugares.

<Tabs group='bundler'>
  <Tab label="Next.js" value="nextjs">
  
    ```typescript fileName="babel.config.js"
      const {
      intlayerExtractBabelPlugin,
      intlayerOptimizeBabelPlugin,
      getExtractPluginOptions,
      getOptimizePluginOptions,
    } = require('@intlayer/babel');

    module.exports = {
      presets: ['next/babel'],
      plugins: [
        // Extraer contenido de los componentes a los diccionarios
        [intlayerExtractBabelPlugin, getExtractPluginOptions()],
        // Optimizar las importaciones reemplazando useIntlayer con importaciones directas de diccionarios
        [intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],
      ],
    };
    ```

  </Tab>
  <Tab label="Vite" value="vite">
   
    ```typescript fileName="vite.config.js"
    import { defineConfig } from 'vite';
    import {intlayer, intlayerCompiler} from 'vite-intlayer';

    export default defineConfig({
      plugins: [intlayer(), intlayerCompiler()],
    });
    ```

> Para vue / svelte necesitará instalar el paquete de compilador apropiado:
>
> ```bash
> # Para Vue
> npm install @intlayer/vue-compiler
> ```
>
> ```bash
> # Para Svelte
> npm install @intlayer/svelte-compiler
> ```

  </Tab>
</Tabs>

---

## Flexibilidad: Modo de Importación Unificado

La propiedad booleana `live` ha sido marcada como obsoleta en favor de una propiedad `importMode` más completa. Esto permite una definición explícita de cómo deben cargarse los diccionarios: de forma estática, dinámica o mediante sincronización en vivo.

### Modos

- **`static`** (Por defecto): El diccionario se incluye en el bundle en el momento de la construcción. Es el mejor para el rendimiento.
- **`dynamic`**: El diccionario se carga en tiempo de ejecución (por ejemplo, mediante fetch JSON o suspense).
- **`fetch`**: El diccionario se obtiene del CMS/Servidor en tiempo de ejecución y se sincroniza.

**Migración:**

| Config v7     | Config v8                            |
| :------------ | :----------------------------------- |
| `live: true`  | `importMode: 'fetch'`                |
| `live: false` | `importMode: 'static'` (o 'dynamic') |

Nota: En Intlayer v8, la propiedad `importMode` se ha movido de la configuración de `build` a la configuración de `dictionary` en `intlayer.config.ts`. Esto le permite definir un modo de importación por defecto para todos sus diccionarios, pudiendo sobrescribirlo para cada uno de ellos individualmente.

**Ejemplo de configuración global:**

```typescript fileName="intlayer.config.ts"
export default {
  dictionary: {
    importMode: "dynamic", // Valor global por defecto
  },
  // ...
};
```

**Ejemplo de diccionario:**

```typescript fileName="src/example.content.ts"
export default {
    key: 'my-key',
    importMode: "fetch", // Sobrescribe la configuración global
    content: { ... }
}
```

---

## Control de ubicación del diccionario

La v8 introduce la propiedad `location` para gestionar explícitamente dónde residen los diccionarios y cómo se sincronizan. Esto es especialmente útil para flujos de trabajo híbridos que implican tanto archivos locales como contenido remoto de un CMS.

### Opciones

- **`local`**: El diccionario solo existe localmente. No se enviará al CMS remoto.
- **`remote`**: El diccionario se gestiona de forma remota. Una vez enviado al CMS, se desvinculará del local. El diccionario remoto se extraerá del CMS.
- **`local_and_remote`**: El diccionario existe en ambos lugares. Los cambios locales se envían y los cambios remotos se extraen (sincronizados).

**Ejemplo:**

```typescript fileName="src/example.content.ts"
export default {
    key: 'my-key',
    location: "local", // Mantener este diccionario solo local
    content: { ... }
}
```

---

## Separación de la configuración del sistema

Intlayer v8 separa la configuración de las fuentes de contenido de las rutas internas del sistema y de salida. Esto despeja la propiedad `content` y deja claro qué ajustes están destinados a la gestión por el usuario frente a los que gestiona el sistema Intlayer.

Las siguientes propiedades se han movido de `content` a una nueva propiedad `system` en `intlayer.config.ts`:

- `dictionariesDir`
- `moduleAugmentationDir`
- `unmergedDictionariesDir`
- `typesDir`
- `mainDir`
- `configDir`
- `cacheDir`
- `outputFilesPatternWithPath`

**Comportamiento v7:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src"],
    dictionariesDir: ".intlayer/dictionary", // Mezclado con la configuración de origen
  },
};
```

**Comportamiento v8:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src"],
  },
  system: {
    dictionariesDir: ".intlayer/dictionary", // Claramente separado
  },
};
```

---

## Separación de directorios de contenido y código

Intlayer v8 separa la configuración para los archivos de definición de contenido de la configuración para la transformación de código. Esto permite una vigilancia y un escaneo más precisos, lo que mejora el rendimiento de la construcción.

Anteriormente, se utilizaba `contentDir` tanto para vigilar los archivos `.content.*` como para escanear el código en busca de llamadas a `useIntlayer`. Ahora:

- **`contentDir`**: Específicamente para sus archivos de declaración de contenido.
- **`codeDir`**: Específicamente para el código de su aplicación que necesita transformación (por ejemplo, poda, optimización).

**Migración:**

Si anteriormente tenía configurado `contentDir`, Intlayer v8 lo utilizará también como valor por defecto para `codeDir`, pero registrará una advertencia. Debería definir explícitamente `codeDir` en su configuración.

**Comportamiento v7:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src", "@packages/design-system"], // Se utiliza tanto para contenido como para código
  },
};
```

**Comportamiento v8:**

```typescript fileName="intlayer.config.ts"
export default {
  content: {
    contentDir: ["src/content", "@packages/design-system"], // Solo vigila aquí los archivos src/content/*.content.* y los archivos @packages/design-system/dist/*.content.*
    codeDir: ["src", "@packages/design-system"], // Solo escanea para transformación de código aquí y los archivos @packages/design-system/src/*.content.*
  },
};
```

---

## Framework: Mejoras en Svelte

El contenido Markdown y HTML en Svelte ahora se analiza automáticamente a HTML cuando se convierte en cadena. Esto facilita mucho el uso con la sintaxis `{@html}` de Svelte, ya que ahora puede simplemente pasar el nodo de contenido directamente.

---

## Notas de migración desde v7

### Cambios en la configuración

- **Propiedad `live`**: La propiedad `live` en los diccionarios ha sido eliminada. Use `importMode: 'fetch'` en su lugar.
- **importMode**: La propiedad `build.importMode` en la configuración ha sido obsoleta. Use `dictionary.importMode` en su lugar.
- **`contentDir` y `codeDir`**: `contentDir` ahora es específicamente para archivos de contenido. Se ha añadido una nueva propiedad `codeDir` para la transformación del código. Si `codeDir` no está configurado, Intlayer recurrirá a `contentDir` y registrará una advertencia.
- **Validación del esquema**: Para utilizar la nueva función `schema`, asegúrese de tener `zod` instalado en su proyecto.

---

## Enlaces útiles

- [Referencia de Configuración](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/configuration.md)
- [Documentación del Archivo de Contenido](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/content_file.md)
- [Documentación de Contenido HTML](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/html.md)
- [Documentación de Contenido Markdown](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/dictionary/markdown.md)
- [Documentación de Reescrituras de URL Personalizadas](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/custom_url_rewrites.md)
