Integrações
Astro
A integração oficial do Astro. Uma linha no astro.config conecta a extração ao vivo, as chaves tipadas e o gate do build; se você usa o fluxo de espelho pré-traduzido, o verbaly render roda sozinho depois de cada build.
O que você pode fazer:
- Escreva seu texto diretamente em arquivos
.astro, frontmatter e markup: chaves, tipos e catálogos ficam em sincronia enquanto você programa - Publique cada idioma como páginas estáticas, com dois fluxos para escolher
- No fluxo de espelho,
verbaly renderroda sozinho depois de cada build: páginas pré-traduzidas, hreflang e um sitemap por idioma sem passos extras - Um build que se recusa a publicar traduções faltando, o mesmo gate de qualquer outro setup do Verbaly
Instalação
Instale o pacote com o seu gerenciador de pacotes preferido.
pnpm add verbaly @verbaly/astroConecte
import { defineConfig } from 'astro/config';
import verbaly from '@verbaly/astro';
export default defineConfig({
integrations: [verbaly()],
});Essa única linha injeta o plugin do Vite com a raiz do seu projeto fixada: extração ao vivo enquanto você programa, o módulo tipado virtual:verbaly e o gate do build. Os tipos gerados vivem dentro da pasta .astro própria do Astro, sem arquivos adicionados ao seu projeto. As opções são as mesmas do plugin do Vite (locales, sourceLocale, dir, failOnMissing…), inline ou no seu verbaly.config.
Escreva o texto no lugar
---
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" />O compilador lê seus arquivos .astro como qualquer outra fonte: o frontmatter e as expressões do markup são extraídos, cada mensagem vira uma chave estável com params tipados, e uma entrada sem tradução falha o build antes de publicar.
Duas formas de publicar os idiomas
Sites Astro são estáticos por padrão, então o idioma é decidido na hora do build. Escolha o fluxo que combina com seu routing:
Páginas por rota
Se o routing i18n do Astro é dono das suas URLs (/es/…, /pt/…), construa uma instância por request e use t como sempre. O Astro é dono das rotas, o Verbaly dos catálogos e da segurança de tipos. createRequestInstance espera o catálogo antes de devolver, que é o que faz a página chegar traduzida em vez de piscar, e Astro.currentLocale vem vazio fora de uma rota com idioma, então o fallback não é decoração.
---
import { createRequestInstance, sourceLocale } from 'virtual:verbaly';
const { t } = await createRequestInstance(Astro.currentLocale ?? sourceLocale);
---Modo espelho
Uma única árvore de páginas, pré-traduzida em cada idioma. Vincule seu markup com atributos data-verbaly e adicione uma seção render à sua config: depois do astro build, a integração espelha o site em dist/es/, dist/pt/… com cada mensagem pré-preenchida, mais alternates hreflang e um sitemap por idioma quando você define baseUrl. Sem flash de conteúdo sem tradução e sem trabalho no cliente.
export default {
locales: ['en', 'es', 'pt'],
render: { baseUrl: 'https://example.com', sitemap: true },
};O sitemap leva as páginas que um buscador deveria indexar. Os seus redirecionamentos e o seu 404 ficam de fora, porque eles próprios o dizem, e continuam a ser espelhados para todos os idiomas para que quem chegar a um o receba ali. Deixe mais de fora com render.exclude.
Um site com mirror pode ir mais longe: o texto que só uma página mostra não precisa chegar ao navegador, porque o mirror já escreveu ele no HTML. Nomeie esses grupos em bundle e as outras páginas param de baixar eles.
export default {
locales: ['en', 'es', 'pt'],
bundle: { exclude: ['changelog'] },
render: { baseUrl: 'https://example.com', sitemap: true },
};Cada página traz só as palavras dela
Uma página do mirror chega já traduzida e, mesmo assim, o visitante baixa todas as mensagens daquele idioma, a maioria das quais essa página nunca mostra. Ligue o inlineCatalog e o mirror escreve em cada página exatamente as mensagens que ela renderiza, então a página não precisa de mais nada.
export default {
locales: ['en', 'es', 'pt'],
render: { baseUrl: 'https://example.com', inlineCatalog: true },
};Neste site as mensagens em espanhol pesam 53 KB comprimidas. A home usa 2.8 KB delas, então uma primeira visita deixa de baixar uns 50 KB, cerca de nove vezes o que custa o runtime inteiro do Verbaly. A página mais pesada daqui é a de novidades, e até essa economiza 32 KB.
Se sua página pedir depois uma mensagem que não mostrou, o Verbaly busca o resto uma vez e atualiza, em vez de mostrar seu idioma de origem sem avisar. Suas páginas no idioma de origem não recebem nada extra: as mensagens delas já viajam com o app.
Com <ClientRouter /> isto continua a funcionar enquanto o visitante navega, e não escreves nada: a integração entrega ao runtime as mensagens de cada página no momento em que essa página entra.