← All notes

Shipping a bilingual site without maintaining two content trees

How build-time data pipelines prevent translation drift across language routes.

A common mistake when scaling websites to support multiple languages is duplicating directory structures or managing distinct content trees for each locale. This approach almost guarantees content drift, where updates in the primary language fail to propagate to secondary locales.

Single Source of Truth

Instead of creating separate markdown folders like /content/en and /content/hi, store primary content in a unified format and process translations as a build-time transformation step.

{
  "slug": "bilingual-site-without-two-trees",
  "title": "Shipping a bilingual site...",
  "translated": false
}

Automated Build-Time Translation Pipeline

Before executing next build, a lightweight Node script inspects your source posts. Any entry marked with translated: false is processed through an LLM API to generate the corresponding translation data file.

// scripts/generate-translations.ts
import dotenv from 'dotenv';
dotenv.config({ path: '.env.local' });

async function translatePosts() {
  const unhandled = posts.filter(p => !p.translated);
  for (const post of unhandled) {
    const translatedData = await translateWithLLM(post);
    saveHindiTranslation(post.slug, translatedData);
  }
}

Unified Component Architecture

By parameterizing your routing and template components by lang, a single Next.js template page renders both /posts/[slug] and /hi/posts/[slug]. Both routes share the exact same typography, layout rules, and SEO logic while referencing locale-matched data dictionaries.