IkboljonMe
Yozuvlar

09.09.26Ingliz tilida2 daqiqa o‘qishNext.js · i18n

One site, three languages

English, Uzbek and Russian on a single Next.js 16 site — the routing, the SEO details, and the two typography problems I didn't see coming.


One site, three languages

Most of the people I work with read English, Uzbek or Russian, and plenty read all three. So ikboljon.me speaks all three. English stays at the root, Uzbek lives under /uz and Russian under /ru.

Routing

Every page sits inside an app/[lang] folder. English visitors should never see an /en prefix, so a small proxy.ts rewrites unprefixed requests to the English route behind the scenes. It rewrites rather than redirects, so the address bar keeps saying /blog.

typescript
export function proxy(request: NextRequest) {
  const first = request.nextUrl.pathname.split("/")[1] ?? ""
  if (isLocale(first)) return NextResponse.next()

  const url = request.nextUrl.clone()
  url.pathname = `/en${request.nextUrl.pathname}`
  return NextResponse.rewrite(url)
}

Interface text lives in one dictionary per language. The English dictionary defines the type every other language must match, so a missing translation is a compile error instead of a blank label in production.

Posts don't have to be translated

I'm not going to write every post three times. Each post has a Language column in Notion. The Uzbek and Russian blog pages show posts written in that language, plus English posts marked as such, so those pages are never empty. For search engines, an English post shown under /ru points its canonical link back to the English URL, so the two never compete.

Two typography problems

  • The main typeface has no Cyrillic at all. Instead of switching fonts for Russian, a Cyrillic-only subset of a second typeface sits behind it in the font stack. Browsers fall back glyph by glyph, so Latin stays in the original font and Russian text picks up the second one.
  • Uzbek writes oʻ and gʻ with a modifier letter. In this typeface that character has a wide advance, so words looked broken in the middle. I switched to the typographic quote most Uzbek websites use, and the words closed up.

Neither of these shows up in a routing tutorial. Both show up the moment a real sentence is on the screen.