支持从右到左(RTL)布局

为阿拉伯语和希伯来语等语言适配布局

问题

应用程序的布局通常使用 margin-leftpadding-right 等 CSS 属性构建,这些属性默认假设文本方向为从左到右(LTR)。当应用被翻译为阿拉伯语或希伯来语等 RTL 语言时,整个布局会变得颠倒,内容错位且难以阅读。

解决方案

将方向性 CSS 属性(left / right)替换为现代、与方向无关的逻辑属性(start / end)。在 <html> 元素上根据当前语言设置 dir 属性,浏览器会自动正确翻转布局。

步骤

1. 定义哪些语言为 RTL

首先,你需要一种方式来识别你支持的语言中哪些是 RTL。

新建一个 app/i18n-config.ts 文件(或更新现有文件)来存储这些信息。

// i18n-config.ts

export const locales = ['en', 'es', 'ar', 'he']; // ar=Arabic, he=Hebrew
export const defaultLocale = 'en';
export const localeCookieName = 'NEXT_LOCALE';

export const rtlLocales = ['ar', 'he'];

2. 在根布局中设置 dir 属性

修改你的 app/[lang]/layout.tsx,有条件地为 <html> 标签添加 dir(direction)属性。

// app/[lang]/layout.tsx
import { rtlLocales } from '@/i18n-config';

export async function generateStaticParams() {
  return [{ lang: 'en' }, { lang: 'es' }, { lang: 'ar' }, { lang: 'he' }];
}

export default async function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  // Determine if the current language is RTL
  const isRtl = rtlLocales.includes(params.lang);

  return (
    <html lang={params.lang} dir={isRtl ? 'rtl' : 'ltr'}>
      <body>
        {/* ...your providers and content... */}
        {children}
      </body>
    </html>
  );
}

通过在 <html> 标签上添加 dir="rtl",你告知浏览器该页面的整个文档流应为从右到左。

3. 更新 CSS,使用逻辑属性

检查你的全局 CSS 和组件样式,将所有方向性属性替换为逻辑属性。

  • margin-left 替换为 margin-inline-start
  • margin-right 替换为 margin-inline-end
  • padding-left 替换为 padding-inline-start
  • padding-right 替换为 padding-inline-end
  • left(定位时)替换为 inset-inline-start
  • right(定位时)替换为 inset-inline-end
  • text-align: left 替换为 text-align: start
  • text-align: right 替换为 text-align: end

示例:

之前(方向性):

.card {
  padding-left: 16px;
  border-left: 4px solid blue;
}
.title {
  text-align: left;
}

之后(逻辑性):

.card {
  padding-inline-start: 16px;
  border-inline-start: 4px solid blue;
}
.title {
  text-align: start;
}

当用户访问 /endir="ltr")时,padding-inline-start 会应用在左侧。当用户访问 /ardir="rtl")时,浏览器会自动将 padding-inline-start 应用到右侧,从而正确翻转你的组件布局。