Saltar al contenido

Integraciones

Astro

La integración oficial de Astro. Una línea en astro.config conecta la extracción en vivo, las claves tipadas y el reporte del build; si usas el flujo de espejo pre-traducido, verbaly render corre solo después de cada build.

Qué puedes lograr:

Instalación

Instala el paquete con tu gestor de paquetes preferido.

 pnpm add verbaly @verbaly/astro

Conéctalo

astro.config.mjs
import { defineConfig } from 'astro/config';
import verbaly from '@verbaly/astro';

export default defineConfig({
  integrations: [verbaly()],
});

Esa única línea inyecta el plugin de Vite con la raíz de tu proyecto fijada: extracción en vivo mientras programas, el módulo tipado virtual:verbaly y el reporte del build. Los tipos generados viven dentro de la carpeta .astro propia de Astro, y npx verbaly extract escribe ese mismo fichero, así que no se añade ninguno a tu proyecto. Las opciones son las mismas del plugin de Vite (locales, sourceLocale, dir, failOnMissing…), inline o en tu verbaly.config.

Escribe el texto en su lugar

src/pages/index.astro
---
import { createRequestInstance } from 'virtual:verbaly';
const { t } = await createRequestInstance('en');
const title = t`Search and find`;
---

<h1>{title}</h1>
<p>{t`Hello ${name}, you have ${count} messages`}</p>
<img alt={t`Company logo`} src="/logo.png" />

El compilador lee tus archivos .astro como cualquier otro fuente. El frontmatter y las expresiones del markup se extraen los dos, cada mensaje se vuelve una clave estable con params tipados, y una entrada sin traducir la lista cada build y hace fallar verbaly check antes de que salga.

Dos formas de publicar los idiomas

Los sitios Astro son estáticos por defecto, así que el idioma se decide al momento del build. Elige el flujo que calce con tu routing:

Páginas por ruta

Si el routing i18n de Astro es dueño de tus URLs (/es/…, /pt/…), construye una instancia por request y usa t como siempre. Astro es dueño de las rutas, Verbaly de los catálogos y de la seguridad de tipos. createRequestInstance espera al catálogo antes de devolver, que es lo que hace que la página llegue traducida en vez de parpadear, y Astro.currentLocale viene vacío fuera de una ruta con idioma, así que el fallback no es decoración.

src/pages/[locale]/index.astro
---
import { createRequestInstance, sourceLocale } from 'virtual:verbaly';
const { t } = await createRequestInstance(Astro.currentLocale ?? sourceLocale);
---

Modo espejo

Un solo árbol de páginas, pre-traducido en todos los idiomas. Bindea tu markup con atributos data-verbaly y añade una sección render a tu config. Después de astro build, la integración espeja el sitio en dist/es/, dist/pt/… con cada mensaje ya relleno, más los alternates de hreflang y un sitemap por idioma cuando pones baseUrl. Sin parpadeo de texto sin traducir y sin trabajo en el cliente.

verbaly.config.mjs
export default {
  locales: ['en', 'es', 'pt'],
  render: { baseUrl: 'https://example.com', sitemap: true },
};

El sitemap lleva las páginas que un buscador debería indexar. Tus redirecciones y tu 404 se quedan fuera, porque lo dicen ellas mismas, y se siguen mirroreando a todos los idiomas para que quien llegue a una la reciba ahí. Deja fuera más con render.exclude.

Un sitio con mirror puede ir más lejos: el texto que solo enseña una página no necesita llegar al navegador, porque el mirror ya lo escribió en el HTML. Nombra esos grupos bajo bundle y el resto de páginas dejan de descargarlos.

verbaly.config.mjs
export default {
  locales: ['en', 'es', 'pt'],
  bundle: { exclude: ['changelog'] },
  render: { baseUrl: 'https://example.com', sitemap: true },
};

Cada página trae solo sus palabras

Una página del mirror llega ya traducida y, aun así, el visitante se descarga todos los mensajes de ese idioma, la mayoría de los cuales esa página no muestra nunca. Enciende inlineCatalog y el mirror escribe en cada página exactamente los mensajes que renderiza, así que una página traducida no necesita catálogo propio.

verbaly.config.mjs
export default {
  locales: ['en', 'es', 'pt'],
  render: { baseUrl: 'https://example.com', inlineCatalog: true },
};

En este sitio los mensajes en español pesan unos 59 KB comprimidos. La home usa 3 KB de ellos, así que una primera visita deja de bajarse unos 56 KB, nueve veces lo que pesa aquí el runtime entero de Verbaly. La página más pesada es la de novedades, y hasta esa se ahorra 26 KB.

Si tu página pide después un mensaje que no mostró, Verbaly se trae el resto una vez y actualiza, en vez de enseñar tu idioma de origen sin decir nada. Tus páginas en el idioma de origen no reciben nada extra: sus mensajes ya viajan con la app.

Con <ClientRouter /> esto sigue funcionando mientras el visitante navega, y tú no escribes nada: la integración le pasa al runtime los mensajes de cada página en el momento en que esa página entra.

↑↓para moverteEnterpara abrir
Copiado en el portapapeles