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 relatório 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 lista as traduções faltando, o mesmo relatório 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 relatório do build. Os tipos gerados vivem dentro da pasta .astro própria do Astro, e npx verbaly extract escreve esse mesmo arquivo, então nenhum é adicionado 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ê os seus arquivos .astro como qualquer outra origem. O frontmatter e as expressões do markup extraem-se os dois, cada mensagem torna-se uma chave estável com params tipados, e uma entrada por traduzir é listada por cada build e faz o verbaly check falhar antes de sair.
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 só árvore de páginas, pré-traduzida em todos os idiomas. Ligue o seu markup com atributos data-verbaly e acrescente uma seção render à sua config. Depois do astro build, a integração espelha o site em dist/es/, dist/pt/… com cada mensagem já preenchida, mais os alternates de hreflang e um sitemap por idioma quando você põe baseUrl. Sem piscar de texto por traduzir 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 sendo 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 uma página traduzida não precisa de catálogo próprio.
export default {
locales: ['en', 'es', 'pt'],
render: { baseUrl: 'https://example.com', inlineCatalog: true },
};Neste site as mensagens em espanhol pesam cerca de 59 KB comprimidas. A home usa 3 KB delas, então uma primeira visita deixa de baixar uns 56 KB, nove vezes o que pesa aqui o runtime inteiro do Verbaly. A página mais pesada é a de novidades, e até essa economiza 26 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 funcionando enquanto o visitante navega, e você não escreve nada: a integração entrega ao runtime as mensagens de cada página no momento em que essa página entra.