국제화(i18n)
Apothem 문서 사이트가 로케일 코호트를 선언하고, hreflang 대체 언어 링크를 내보내며, 열두 개 언어에 걸쳐 오른쪽에서 왼쪽 방향을 렌더링하는 방식.
이 페이지는 Apothem 문서 사이트가 여러 언어를 처리하는 방식, 즉 사이트가
선언하는 로케일 코호트, 내보내는 hreflang 메커니즘, 오른쪽에서 왼쪽 렌더링,
그리고 각 언어의 페이지가 라우팅에 연결되는 방식을 설명합니다.
결정 요약
- 플랫폼: Next.js App Router + Fumadocs. 사이트는
site/에서 빌드됩니다. 로케일 코호트는site/lib/i18n.ts에 선언되며, 대체 언어 링크 메커니즘은site/lib/hreflang.ts에 있습니다. - 로케일 코호트: 열두 개 언어. 열두 개 로케일로 이루어진 Modern Dev
Cohort가 정식 진실의 원천입니다. 영어가 소스 로케일이며, 열한 개 대상
로케일은 각각 영어 페이지 세트에서 기계로 시드됩니다. 로케일별 사람 검토가
진행 중이며, 어떤 로케일이 아직 작성하지 않은 페이지는
fallbackLanguage: 'en'이 처리합니다. - 로케일별 라우팅: 코호트 전체에서 활성화. 모든 로케일이 라우팅에 연결되어
각자의 URL 접두사(
/es/,/zh-cn/, …)로 접근할 수 있으며, 영어는 사이트 루트에서 제공됩니다. hreflang메커니즘: 활성. 모든 페이지는 각 로케일과x-default폴백을 포괄하는<link rel="alternate">세트를 내보내므로, 검색 엔진은 전체 대체 언어 클러스터를 볼 수 있습니다. 링크는 파일 시스템에서 파일별로 확인되므로, 페이지는 해당 로케일에 그 페이지가 있을 때만 그 로케일로 알려집니다.- 오른쪽에서 왼쪽 렌더링: 활성. 공유 스타일시트는 전반적으로 논리적 CSS
속성을 사용하므로, 아랍어 페이지가
dir="rtl"아래에서 올바르게 렌더링됩니다. - 번역 검토: 페이지별 추적. 기계로 시드된 로케일 페이지는 제공되며, 사람이
검토하기 전까지 프런트매터에
machineTranslated: true를 지닙니다. 이 플래그는 검토 추적용 메타데이터이며 페이지에 표시되지 않습니다. 어떤 로케일에 없는 페이지는 영어가 폴백으로 처리합니다. 로케일 페이지의 80%를 검토하는 것은 검토 목표이지, 게시를 막는 관문이 아닙니다. - 번역 최신성: 페이지별 추적. 각 로케일 페이지는 번역의 바탕이 된 영어 텍스트를 기록합니다. 이후 영어 페이지가 변경되면, 번역된 페이지에 영어 페이지로 연결되는 한 줄짜리 안내가 표시되며, 영어 페이지가 계속 권위를 가집니다.
로케일 코호트
Modern Dev Cohort는 열두 개 로케일을 선언합니다. 영어는 사이트 루트에서
제공됩니다. 열한 개 대상 로케일은 각각 영어 페이지 세트에서 기계로 시드되어
자체 URL 접두사에서 제공되며, 아직 작성되지 않은 페이지는
fallbackLanguage: 'en'이 처리합니다.
| 코드 | 경로 | 언어 | 방향 |
|---|---|---|---|
en | / | 영어 | LTR |
zh-CN | /zh-cn/ | 중국어 간체 | LTR |
es | /es/ | 스페인어 | LTR |
pt-BR | /pt-br/ | 브라질 포르투갈어 | LTR |
fr | /fr/ | 프랑스어 | LTR |
de | /de/ | 독일어 | LTR |
ja | /ja/ | 일본어 | LTR |
ko | /ko/ | 한국어 | LTR |
ru | /ru/ | 러시아어 | LTR |
id | /id/ | 인도네시아어 | LTR |
ar | /ar/ | 아랍어 | RTL |
hi | /hi/ | 힌디어 | LTR |
코호트는 단일 진실의 원천입니다. 코호트에 대한 수정은 신중한 결정을 거치며, 결코 조용한 편집으로 이루어지지 않습니다.
hreflang 작동 방식
site/lib/hreflang.ts는 Next.js가 각 페이지의 <head>에 렌더링하는
alternates.languages 맵을 만듭니다. 이 맵은 한 가지 규칙을 따릅니다.
로케일의 대체 언어 링크는 해당 로케일이 그 페이지를 작성한 경우에만
내보내며, 이는 파일 시스템에서 파일별로 확인됩니다
(site/lib/translated-pages.ts). 따라서 완전히 번역된 페이지는 전체 클러스터를
내보냅니다.
<link rel="alternate" hreflang="en" href="https://apothem.ahmedgad.com/..." />
<link rel="alternate" hreflang="es" href="https://apothem.ahmedgad.com/es/..." />
<link rel="alternate" hreflang="ar" href="https://apothem.ahmedgad.com/ar/..." dir="rtl" />
<!-- … one per cohort locale … -->
<link rel="alternate" hreflang="x-default" href="https://apothem.ahmedgad.com/..." />페이지의 canonical 링크는 항상 그 페이지 자신의 URL이며, 결코 다른 로케일을
가리키지 않습니다.
오른쪽에서 왼쪽 렌더링
아랍어는 코호트의 오른쪽에서 왼쪽 방향 로케일이며, 사이트는 이를 올바르게 렌더링합니다.
- 논리적 CSS 속성만 사용. 공유 스타일시트와 컴포넌트는 물리적 속성
(
margin-left,text-align: left) 대신 논리적 속성(margin-inline-start,padding-inline-end,text-align: start,inset-inline-start)을 사용합니다. 논리적 속성은dir="rtl"아래에서 자동으로 뒤집히므로, 같은 스타일시트가 두 방향 모두를 올바르게 지원합니다. - 방향 속성. 아랍어 페이지는
<html>요소에lang="ar"와 함께dir="rtl"을 설정합니다. - 양방향 콘텐츠. 방향이 섞인 문자열 — 예를 들어 아랍어 단락 안의 영어
명령 — 은
<bdi>로 감싸, 포함된 왼쪽에서 오른쪽 방향 구간이 오른쪽에서 왼쪽 흐름 안에서 올바르게 렌더링되도록 합니다.
로케일 추가 또는 업데이트
코호트와 라우팅은 site/lib/i18n.ts가 구동합니다.
- 영어 소스를 그대로 반영하여
content/docs/<locale>/아래에 페이지를 작성합니다. - 페이지가 번역한 영어 텍스트를 기록합니다.
site/에서node scripts/translation-sources.mjs --stamp <locale>/<path>.mdx를 실행하면, 영어 페이지의 해시가 로케일 페이지의sourceHash프런트매터에 기록됩니다. - 로케일이
ROUTED_LOCALES에 나열되어 있는지 확인합니다(현재 코호트의 열두 개 로케일이 모두 라우팅됩니다). - 해당 로케일의
hreflang링크와 라우트는 파일 시스템에서 자동으로 확인됩니다.
오래된 번역
로케일 페이지의 sourceHash는 번역의 바탕이 된 영어 페이지의 해시로, 영어
프런트매터와 본문은 포함하지만 레퍼런스 생성기가 모든 언어에서 한꺼번에 다시
쓰는 생성된 표는 포함하지 않습니다. 빌드 시 사이트는 현재 영어 페이지의 해시를
계산하며, 두 값이 다르면 번역된 페이지에 번역 이후 영어 페이지가 변경되었다는
안내가 영어 페이지 링크와 함께 표시됩니다. site/에서
node scripts/translation-sources.mjs를 실행해 로케일별로 오래된 페이지를
나열한 다음, 각 번역을 갱신하고 위 2단계와 같이 스탬프합니다. 어떤 로케일이
전혀 번역하지 않은 페이지는 영어 텍스트로 표시된 채 영어 소스에서 제공됩니다.
영어가 계속 진실의 원천이며, 각 로케일 페이지는 대응하는 영어 페이지의 구조, 링크, 코드 샘플을 그대로 반영합니다.