Intermediatei18n25 분2026년 4월 18일

정적 사이트의 i18n — 5개 로케일

CMS 없이 하는 슬래시 라우트 현지화: 사전, 동적 [locale] 경로, hreflang, 그리고 다섯 언어를 동기화하는 법.

아키텍처

/en/blog/hello    ← 기본 로케일, 그래도 프리픽스 있음 (예외 케이스보다 깔끔)
/ru/blog/hello
/zh/blog/hello
/ja/blog/hello
/de/blog/hello

세 가지 움직이는 부품:

  1. 사전 — 로케일당 JSON 하나, 동일한 형태, Record<Locale, typeof en>으로 타입화해서 키가 어긋나면 TypeScript가 즉시 알린다.
  2. 동적 라우트 — src/pages/[locale]/...에 getStaticPaths()로 모든 로케일을 반환.
  3. 콘텐츠 폴백 — en/에 한 번만 글을 쓰고, 번역이 생길 때까지 모든 로케일 아래에서 렌더링.

널 살려주는 타입 트릭

export type Locale = "en" | "ru" | "zh" | "ja" | "de";
const dictionaries: Record<Locale, typeof en> = { en, ru, zh, ja, de };

typeof en이 스키마다. en.json에 키를 추가하면 나머지 네 사전이 따라잡을 때까지 빌드가 실패한다.

head를 잊지 마라

모든 로케일에 대한 <link rel="alternate" hreflang="...">와 x-default, 페이지별 canonical, 그리고 Astro.url에서 유도된 경로. 검색엔진은 지루한 배관 공사에 보상한다.