DEV Community

mathew lam
mathew lam

Posted on • Originally published at jerseytome.com

Scaling a Content Site to 5 Languages with Next.js + next-intl (Zero Manual Translation)

Why Multi-Language?

I run a niche content site about NBA jerseys. Basketball is global — fans in China, Japan, Korea, and Latin America search for the same jerseys in their own languages. By adding 4 additional locales, I 5x'd my addressable search traffic overnight.

But manually translating 60+ articles into 4 languages? Not happening.

The Stack

  • Next.js 16 App Router
  • next-intl v4 for routing and message handling
  • MDX for content
  • Claude API for translation
  • Custom pipeline for batch processing

Architecture: Locale-First File Structure

content/
├── en/
│   └── jerseys/
│       └── michael-jordan/
│           └── bulls-pinstripe.mdx
├── zh/
├── ja/
├── ko/
└── es/
Enter fullscreen mode Exit fullscreen mode

Each locale gets its own content directory. The English version is the source of truth.

Routing with next-intl

export const locales = ['en', 'zh', 'ja', 'ko', 'es'] as const;

export const routing = defineRouting({
  locales,
  defaultLocale: 'en',
  localePrefix: 'as-needed',
});
Enter fullscreen mode Exit fullscreen mode

The as-needed prefix means English URLs stay clean while other locales get their prefix.

The Translation Pipeline

I built a batch translator that reads English MDX, checks which translations are missing, sends to Claude API, and writes translated files preserving frontmatter.

Hreflang: The Critical SEO Piece

Every page needs alternates pointing to its translations. Both in page metadata AND in the sitemap.

Content Fallback Strategy

Missing translations gracefully fall back to English. No 404s.

Results

  • 63 English source articles → 267 total pages across 5 locales
  • Zero manual translation work
  • Build time: ~45 seconds for all 267 pages

The site: JerseyToMe

Top comments (0)