Framework
Astro
The official Astro integration. One line in astro.config wires live extraction, typed keys and the build gate; if you use the pre-translated mirror flow, verbaly render runs by itself after every build.
What you can accomplish:
- Write your text directly in
.astrofiles, frontmatter and markup: keys, types and catalogs stay in sync while you code - Ship every language as static pages, with two flows to choose from
- In the mirror flow,
verbaly renderruns by itself after every build: pre-translated copies, hreflang and a per-locale sitemap with zero extra steps - A build that refuses to ship missing translations, same gate as every other Verbaly setup
Installation
Install the package with your preferred package manager.
pnpm add verbaly @verbaly/astroWire it up
import { defineConfig } from 'astro/config';
import verbaly from '@verbaly/astro';
export default defineConfig({
integrations: [verbaly()],
});That single line injects the Vite plugin with your project root pinned: live extraction while you code, the typed virtual:verbaly module and the build gate. The generated types live inside Astro's own .astro folder, no file added to your project. Options are the same as the Vite plugin (locales, sourceLocale, dir, failOnMissing…), inline or in your verbaly.config.
Write the text in place
---
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" />The compiler reads your .astro files like any other source: the frontmatter and the markup expressions both extract, every message becomes a stable key with typed params, and an untranslated entry fails the build before it ships.
Two ways to ship the languages
Astro sites are static by default, so the language has to be decided at build time. Pick the flow that matches your routing:
Path-based pages
If Astro's i18n routing owns your URLs (/es/…, /pt/…), create one instance per page and use t as usual. Astro owns the routes, Verbaly owns the catalogs and the type safety.
---
import { createRequestInstance } from 'virtual:verbaly';
const { t } = await createRequestInstance(Astro.currentLocale);
---Mirror mode
One page tree, pre-translated copies. Bind your markup with data-verbaly attributes and add a render section to your config: after astro build, the integration mirrors the site into dist/es/, dist/pt/… with every message pre-filled, plus hreflang alternates and a per-locale sitemap when you set baseUrl. No flash of untranslated content and no client work.
export default {
locales: ['en', 'es', 'pt'],
render: { baseUrl: 'https://example.com', sitemap: true },
};