Docs / Astro
Astro i18n, automated
Localize an Astro site: .astro pages get t() from the URL’s language, every static page gets a copy per language for search engines, and React, Vue or Svelte islands follow along.
How it works
Text and expressions in .astro files become {t('key')}, with t reading the language from the URL (/es/about). Each page gets a copy per language, so every language is a real, indexable page; dynamic routes keep their getStaticPaths and props.
React, Vue and Svelte islands are localized in the same run, each with its own library, following the page’s language.
Before and after
The engine’s real output for this file. In a real run, the hosted model names the keys from context.
---
import Layout from '../../layouts/Layout.astro';
const product = { name: 'Jasmine tea', stock: 12 };
---
<Layout title="Our teas">
<h1>{product.name}, picked this spring</h1>
<p>{product.stock > 0 ? 'In stock' : 'Sold out'}</p>
</Layout>---
import Layout from '../../layouts/Layout.astro';
import { getLangFromUrl, useTranslations } from '../i18n';
const product = { name: 'Jasmine tea', stock: 12 };
const t = useTranslations(getLangFromUrl(Astro.url));
---
<Layout title={t('tea.our_teas')}>
<h1>{t('tea.picked_this_spring', { name: product.name })}</h1>
<p>{product.stock > 0 ? t('tea.in_stock') : t('tea.sold_out')}</p>
</Layout>{
"tea": {
"our_teas": "Our teas",
"picked_this_spring": "{{name}}, picked this spring",
"in_stock": "In stock",
"sold_out": "Sold out"
}
}What the setup adds
The first run sets up a generated src/i18n module (islands: their own libraries) if the project doesn’t have it yet:
src/i18nwitht,getLangFromUrlandlocalizePath- A copy of each page under
src/pages/<lang>/, dynamic routes included <html lang dir>set from the URL in layouts
Run it
The CLI needs Node.js 22 or later.
npm install --save-dev localize-dev
npx localize-dev login
# Preview, then write the changes
npx localize-dev run --dry-run -l es,fr,de
npx localize-dev run -l es,fr,de
# Or open a pull request instead
npx localize-dev pr -l es,fr,deOr add the GitHub Action and get a pull request on every push. Try it on your own code first in the playground.