How to build a multilingual static website
From one language to two, in about fifteen minutes.

To build a multilingual static website with vagejs, list your extra languages under i18n in vage.config.ts, put translated pages in a folder per language, and add a language switcher to your layout. vagejs writes the lang and hreflang tags and lists any page still missing a translation.

This guide adds French to an English site. The same steps work for any language, and for more than one.

You need vagejs 0.10 or newer. Start a new site with npm create vagejs@latest my-site, or update an existing one with npm install vagejs@latest.

1. Name your languages

Open vage.config.ts. lang is your main language, and it stays where it is. Add the others under i18n:

TypeScript
export default defineConfig({
  site: "https://example.com",
  lang: "en",
  i18n: { locales: ["fr"] },
  // ...the rest of your settings
});

2. Add French pages

Make a fr folder in src/pages and add pages to it. A French page with the same file name as an English one is its translation:

---
title: Accueil
description: Bienvenue sur notre site, en français.
---

# Bienvenue

Ce site existe aussi en anglais.

Save that as src/pages/fr/index.md and it's served at /fr/, as the French version of your home page.

French visitors may prefer French addresses: /fr/a-propos/ rather than /fr/about/. Name the file in French and say which page it translates:

---
title: À propos
description: Qui nous sommes et ce que nous faisons.
translationOf: /about/
---

# À propos

Nous sommes une petite équipe.

3. Check what's missing

Run the check:

terminal
npm run check

Every English page without a French version shows up as a warning, with the file to add:

warning translation-missing    /blog/ (src/pages/blog/index.md)
        No fr version of this page. Add src/pages/fr/blog/index.md (or a page with translationOf: /blog/).

They're warnings, not errors, so the site still builds while you translate. Mistakes are errors: a translationOf that points to a page that doesn't exist, or two French pages that both claim to translate the same English one.

4. Add a language switcher

Your layout gets page.translations: every version of the page being shown. In the starter layout (src/layouts/default.ts), add this after the main <nav>:

TypeScript
${page.translations.length > 1
  ? html`<nav aria-label="Language">${page.translations.map((t) =>
      t.current
        ? html`<span aria-current="page">${t.lang.toUpperCase()}</span> `
        : html`<a href="${t.route}" hreflang="${t.lang}">${t.lang.toUpperCase()}</a> `,
    )}</nav>`
  : ""}

Pages that exist in one language get no switcher, and the links always point to pages that exist. Make sure the layout's <html> tag uses page.lang, as the starter does: <html lang="${page.lang}">.

5. Translate the menu

Add a French menu next to the English one in vage.config.ts:

TypeScript
menus: {
  main: [{ page: "/" }, { page: "/about/" }, { page: "/blog/" }],
  "main-fr": [{ page: "/fr/" }, { page: "/fr/a-propos/" }],
},

Then pick the menu by language in the layout: menus[page.lang === "fr" ? "main-fr" : "main"]. The labels come from each page's title, so the French menu reads in French.

6. Build and look

terminal
npm run build

Open dist/about/index.html. vagejs added links to every version of the page, plus a default for visitors whose language you don't have:

HTML
<html lang="en">
<link rel="alternate" hreflang="en" href="https://example.com/about/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/a-propos/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/about/" />

The French page has <html lang="fr"> and the same three links. Google uses these to show each searcher the version in their language.

Can an AI assistant do the translating?

Every vagejs site includes an AGENTS.md file that explains these rules to coding assistants. You can ask Claude Code, Cursor or Codex to "translate the about page into French", and it knows where the file goes and how to link it. Run npm run check afterwards: the list of missing translations is a good to-do list. Read the translations yourself before publishing, or ask someone who speaks the language.

More on multilingual vagejs sites

Start with one command.
You'll have a site running in a minute.

npm create vagejs@latest my-site

Read the docsUse it with your AI assistant