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 gate 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 gate del build. Los tipos generados viven dentro de la carpeta .astro propia de Astro, sin archivos añadidos 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 otra fuente: el frontmatter y las expresiones del markup se extraen, cada mensaje se convierte en una clave estable con params tipados, y una entrada sin traducir hace fallar el build antes de publicarse.

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 cada idioma. Enlaza tu markup con atributos data-verbaly y agrega 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 pre-rellenado, más alternates hreflang y un sitemap por idioma cuando defines baseUrl. Sin flash de contenido 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 la página no necesita nada más.

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 53 KB comprimidos. La home usa 2.8 KB de ellos, así que una primera visita deja de bajarse unos 50 KB, que son unas nueve veces lo que cuesta el runtime entero de Verbaly. La página más pesada de aquí es la de novedades, y hasta esa se ahorra 32 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