Next.js(Pages Router) v16에서 오른쪽에서 왼쪽(RTL) 언어를 지원하는 방법
아랍어 및 히브리어를 위한 레이아웃 미러링
문제
대부분의 웹 레이아웃은 왼쪽에서 오른쪽으로 흐르는 텍스트를 가정합니다. 내비게이션 메뉴는 왼쪽에 고정되고, 콘텐츠는 왼쪽에서 오른쪽으로 읽히며, 간격은 margin-left 또는 padding-right와 같은 속성으로 적용됩니다. 애플리케이션이 아랍어나 히브리어로 번역되면, 이러한 언어는 오른쪽에서 왼쪽으로 읽히므로 전체 시각적 레이아웃이 이에 맞춰 미러링되어야 합니다. 미러링이 없으면 사용자는 시각적 계층 구조가 자연스러운 읽기 방향과 모순되는 혼란스러운 인터페이스를 경험하게 되어 내비게이션이 혼란스럽고 애플리케이션이 세련되지 않게 느껴집니다.
문제는 텍스트 정렬을 넘어 확장됩니다. left, right, margin-left, padding-right와 같은 물리적 CSS 속성은 콘텐츠 흐름이 아닌 고정된 화면 위치에 연결되어 있습니다. 텍스트 방향이 변경되면 이러한 속성은 동일한 물리적 가장자리에 고정되어 레이아웃이 자연스럽게 적응하지 못하게 합니다.
해결 방법
문서의 텍스트 방향 속성을 현재 로케일에 맞게 설정하여 브라우저가 RTL 언어에 대해 레이아웃 흐름을 자동으로 반전할 수 있도록 합니다. 물리적 CSS 속성을 화면 위치가 아닌 콘텐츠 흐름을 참조하는 논리적 속성으로 교체합니다. margin-inline-start 및 padding-inline-end와 같은 논리적 속성은 텍스트 방향에 따라 올바른 물리적 가장자리에 자동으로 매핑되어 추가 코드나 조건부 스타일링 없이 레이아웃이 스스로 미러링될 수 있도록 합니다.
이 접근 방식은 스타일을 복제하거나 복잡한 로직을 추가하지 않고도 LTR 및 RTL 언어 모두에서 올바르게 작동하는 방향 독립적 레이아웃을 생성합니다.
단계
1. 로케일에서 텍스트 방향을 결정하는 헬퍼 생성
논리적 속성은 텍스트 방향에 따라 적응하며, margin-inline-start는 LTR 컨텍스트에서 margin-left에 해당하고 RTL 컨텍스트에서 margin-right에 해당합니다. 로케일을 텍스트 방향에 매핑하는 유틸리티 함수를 구축합니다.
export function getDirection(locale: string): "ltr" | "rtl" {
const rtlLocales = ["ar", "he", "fa", "ur"];
return rtlLocales.includes(locale) ? "rtl" : "ltr";
}
이 함수는 RTL 언어를 식별하고 HTML 및 CSS에서 사용할 적절한 방향 값을 반환합니다.
2. 문서 방향 속성 설정
사용자 정의 Document 클래스는 render 메서드를 재정의하여 lang 및 dir과 같은 속성으로 HTML 요소를 사용자 정의할 수 있습니다. 현재 로케일을 기반으로 루트 HTML 요소에 dir 속성을 설정하는 사용자 정의 Document를 생성합니다.
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
} from "next/document";
import { getDirection } from "../utils/direction";
class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx);
return initialProps;
}
render() {
const locale = this.props.__NEXT_DATA__.locale || "en";
const dir = getDirection(locale);
return (
<Html lang={locale} dir={dir}>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
Next.js 라우터는 locale 속성을 통해 현재 활성 로케일을 제공합니다. 문서는 Next.js 라우팅 데이터에서 로케일을 읽고 HTML 요소에 해당 방향을 적용하여 브라우저 수준의 RTL 지원을 활성화합니다.
3. 물리적 CSS 속성을 논리적 속성으로 대체
margin-inline-start, padding-inline-start와 같은 논리적 속성 및 단축 형식인 margin-inline과 padding-inline은 쓰기 모드와 방향에 따라 자동으로 물리적 속성에 매핑됩니다. 컴포넌트 스타일을 업데이트하여 흐름 상대 속성을 사용하세요.
export default function Navigation() {
return (
<nav className="nav">
<ul className="nav-list">
<li className="nav-item">Home</li>
<li className="nav-item">About</li>
<li className="nav-item">Contact</li>
</ul>
</nav>
);
}
.nav {
padding-inline: 1rem;
border-inline-start: 4px solid blue;
}
.nav-list {
display: flex;
gap: 1rem;
margin-block: 0;
padding-inline-start: 0;
}
.nav-item {
margin-inline-end: 1.5rem;
}
margin, padding 및 inset에 대한 논리적 속성은 쓰기 모드 전반에 걸쳐 요소 배치를 더 쉽고 효율적으로 만듭니다. 이러한 속성은 추가 스타일이나 미디어 쿼리 없이 RTL 컨텍스트에서 자동으로 반전됩니다.
4. 위치 지정에 논리적 속성 사용
절대 또는 상대 위치 지정 요소의 경우 left와 right를 inset-inline-start와 inset-inline-end로 교체하세요.
export default function Sidebar() {
return (
<aside className="sidebar">
<button className="close-button">×</button>
<p>Sidebar content</p>
</aside>
);
}
.sidebar {
position: fixed;
inset-inline-start: 0;
inset-block-start: 0;
inline-size: 250px;
block-size: 100vh;
padding-inline: 1rem;
}
.close-button {
position: absolute;
inset-inline-end: 0.5rem;
inset-block-start: 0.5rem;
}
논리적 속성 방법론에서 width 속성은 inline-size로, height는 block-size로 대체됩니다. 이러한 속성은 위치 지정 요소가 현재 텍스트 방향에 맞는 올바른 측면에 나타나도록 보장합니다.
5. 논리적 텍스트 정렬 적용
text-align: left와 text-align: right를 text-align: start와 text-align: end로 교체하세요.
.content {
text-align: start;
}
.metadata {
text-align: end;
margin-inline-start: auto;
}
논리적 속성은 물리적 뷰포트 차원이 아닌 콘텐츠 흐름과 관련된 박스의 가장자리를 참조합니다. start와 end의 텍스트 정렬 값은 텍스트 방향에 자동으로 적응하여 LTR 및 RTL 언어 모두에 대해 콘텐츠를 적절하게 정렬합니다.