Internationalization
biagiojs builds one static variant per locale from the same project. Default language lives at /, other languages at /<lang>/…. SEO (hreflang, sitemap x-default) is automatic.
Config
site: {
baseUrl: 'https://example.com',
locales: ['en', 'it'],
defaultLocale: 'en',
}
biagio build emits /about/ and /it/about/ (and every other page twice).
Translations
UI strings live in locales/<lang>.json (nested keys, dot-path):
{
"hero": { "title": "Run lighter" },
"cta": { "buy": "Buy — {price}" }
}
In .page.js:
export default function ({ t, locale }) {
return { graph, page: { title: t('hero.title') } };
}
In .biagio templates:
<h1>{{t:hero.title}}</h1>
Interpolation: t('cta.buy', { price: '€49' }).
Content collections
Markdown follows the same folder convention as this docs site:
content/blog/post.md → /blog/post/ (default locale)
content/blog/it/post.md → /it/blog/post/ (Italian)
getCollection('content/blog') returns only files for the locale being built.
SEO
With site.locales set, every page gets:
<link rel="alternate" hreflang="…">for each languagehreflang="x-default"pointing at the default locale URL- Sitemap entries with
xhtml:linkalternates
See Automatic SEO for JSON-LD and Open Graph details.
Per-locale optimizer
Field data can differ by market. Place overrides in reports/<lang>/:
reports/
crux.json # global fallback
analytics.json
reports/it/
analytics.json # Italian CTR → overrides global for /it/ builds
During build for locale it, files in reports/it/ merge over the root reports/ folder. German click patterns won't skew Italian hydration.
Language switcher
This documentation site uses docs/i18n-ui.js for the EN·IT toggle — a small pattern you can copy into your layout.
This docs site
biagiojs/docs/ is the reference implementation: locales/en.json + locales/it.json, content/docs/.md + content/docs/it/.md, and hreflang on every page.