关于 rtl-internationalization
帮助开发者让 Web 和 React Native 界面支持从右向左书写的语言。内容涵盖方向感知布局、双向文本、本地化和 RTL 测试。
主要功能
- 01审查物理方向样式
- 02采用逻辑 CSS 与 Tailwind 属性
- 03运行时设置文本方向
- 04处理双向用户文本
- 05调整方向性图标与控件
- 06本地化并测试 RTL 界面
适用场景
- 01审查 Web 界面的 RTL 问题
- 02支持阿拉伯语或希伯来语
- 03检查界面中的混合文字方向
- 04添加 RTL 视觉回归检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mindrally/ skills --skill rtl-internationalization安装后在 Claude Code 中输入/rtl-internationalization确认已加载。
详细介绍
RTL(从右到左)国际化
支持希伯来语、阿拉伯语、波斯语和乌尔都语等 RTL 语言,需要使用与方向无关的 CSS 构建布局,并将文本方向视为一项一等属性,可在运行时切换,而不是将其固定在左右样式中。
构建 RTL 安全界面的工作流
- 检查物理属性 — 在代码库中搜索
margin-left/right、padding-left/right、left/right定位、text-align: left/right,以及ml-*、mr-*、pl-*、pr-*、left-*、right-*等 Tailwind 类。 - 转换为逻辑属性 — 将每个物理属性/类替换为对应的逻辑属性(
margin-inline-start、ms-*等),这样浏览器会根据dir自动翻转。 - 在根节点设置方向 — 在
<html>或顶层容器上应用dir="rtl"(或dir="auto"),并由当前语言区域驱动,而不是在各个组件中硬编码。 - 处理混合文字 — 对方向可能与周围文本不同的用户生成内容或插值字符串使用
<bdi>包裹。 - 检查图标和方向性组件 — 镜像翻转箭头、尖括号和后退/前进按钮;非方向性图标(搜索、设置、主页)保持原样;反转轮播、滑块和进度条的方向。
- 将所有字符串外置 — 通过翻译函数处理每一条面向用户的字符串,并使用
IntlAPI 处理数字、货币和日期,而不是手动格式化。 - 在 RTL 模式下测试 — 使用
dir="rtl"和真实的 RTL 内容(而不只是镜像后的 LTR 占位文本)渲染应用,并对每个屏幕进行视觉验证。
CSS 逻辑属性
始终使用 CSS 逻辑属性,而不是物理属性——逻辑属性会根据元素的 direction 和 writing-mode 自动解析为正确的物理方向,因此同一份样式表无需重复即可同时适用于 LTR 和 RTL。
| 物理属性(避免使用) | 逻辑属性(使用) |
|---|---|
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 |
border-left | border-inline-start |
border-right | border-inline-end |
text-align: left | text-align: start |
text-align: right | text-align: end |
/* Before: breaks in RTL */
.card {
margin-left: 1rem;
padding-right: 1.5rem;
border-left: 2px solid var(--border);
text-align: left;
}
/* After: direction-agnostic */
.card {
margin-inline-start: 1rem;
padding-inline-end: 1.5rem;
border-inline-start: 2px solid var(--border);
text-align: start;
}
Tailwind CSS 逻辑类
使用 Tailwind 的逻辑工具类,而不是方向性(l/r)类:
- 使用
ms-4代替ml-4(margin-inline-start) - 使用
me-4代替mr-4(margin-inline-end) - 使用
ps-4代替pl-4(padding-inline-start) - 使用
pe-4代替pr-4(padding-inline-end) - 使用
start-0代替left-0(inset-inline-start) - 使用
end-0代替right-0(inset-inline-end) - 使用
text-start代替text-left - 使用
text-end代替text-right
<div class="ml-4 pr-6 text-left">...</div>
<div class="ms-4 pe-6 text-start">...</div>
React Native 逻辑属性
React Native 的 Yoga 布局引擎也支持逻辑属性——请使用这些属性,而不是 Left/Right 变体:
- 使用
paddingStart/paddingEnd代替paddingLeft/paddingRight - 使用
marginStart/marginEnd代替marginLeft/marginRight - 使用
borderStartWidth/borderEndWidth代替borderLeftWidth/borderRightWidth - 在绝对定位中使用
start/end代替left/right
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
paddingStart: 16,
paddingEnd: 16,
},
badge: {
position: 'absolute',
end: 8, // flips automatically with I18nManager.isRTL
top: 8,
},
})
双向文本安全
对于方向可能与周围上下文不同的文本——用户名、产品代码、文件路径,或插入翻译句子的任何用户生成内容——使用 <bdi> 包裹,以便浏览器的双向文本算法正确隔离这些内容。
<p>User <bdi>{userName}</bdi> posted a comment</p>
<p>Order number: <bdi>{orderCode}</bdi> has shipped</p>
如果不使用 <bdi>,嵌入阿拉伯语句子中的拉丁字母用户名(或反之)可能会导致周围的标点符号和相邻词语在视觉上重新排序。
方向性图标和组件
- 在 RTL 模式下镜像方向性图标:箭头、尖括号、后退/前进/下一步/上一步按钮,以及邮件/聊天界面中的“回复”图标。
- 不要镜像非方向性图标:主页、设置、搜索、打印、垃圾桶、对勾,以及现实物体的图标(钟面、电话)。
- 在 RTL 模式下反转轮播、滑块和进度条的方向,使“下一步”仍与阅读方向一致。
- 在 RTL 模式下反转滑动手势的方向(例如,滑动关闭卡片时应朝末端边缘滑动,而不总是向左)。
- 翻转具有方向轴的图表和图形(例如从左向右延伸的时间线),使时间流向仍符合阅读顺序。
/* Mirror an icon only when the document is RTL */
[dir="rtl"] .icon-chevron-forward {
transform: scaleX(-1);
}
// React: pick the mirrored icon variant based on direction
function BackButton({ dir }: { dir: 'ltr' | 'rtl' }) {
const Icon = dir === 'rtl' ? ChevronRightIcon : ChevronLeftIcon
return (
<button aria-label="Back">
<Icon aria-hidden="true" />
</button>
)
}
国际化基础
- 切勿硬编码面向用户的字符串——将每个字符串都通过翻译函数(
t()、intl.formatMessage()等)处理,以便进行本地化,并确保 RTL 语言环境使用正确的标点和词序。 - 使用
Intl.NumberFormat格式化数字和货币,而不要手动格式化字符串——不同语言环境的数字形态和分组分隔符各不相同。 - 使用
Intl.DateTimeFormat格式化日期和时间,而不要手动拼接。 - 对用户生成的内容字段(评论、聊天消息)设置
dir="auto",以便浏览器根据内容推断方向;并根据当前语言环境,在文档根元素上明确设置dir="rtl"或dir="ltr"。
const currency = new Intl.NumberFormat('ar-EG', {
style: 'currency',
currency: 'EGP',
}).format(1234.5)
// "١٬٢٣٤٫٥٠ ج.م."
document.documentElement.dir = locale.startsWith('ar') || locale.startsWith('he') ? 'rtl' : 'ltr'
document.documentElement.lang = locale
测试
- 务必在根元素应用
dir="rtl"进行测试,而不只是查看镜像后的 LTR 布局截图。 - 使用真实的 RTL 内容(真实的阿拉伯语/希伯来语字符串,通常比对应的英文字符串更短或更长)进行验证,而不要使用反转后的 LTR 占位文本——字符串长度差异会暴露截断和溢出问题,仅靠镜像无法发现这些问题。
- 为关键界面(导航、表单、数据表、模态框)添加 RTL 快照或视觉回归测试,并与 LTR 版本一同维护。
- 检查焦点顺序和键盘导航(Tab 顺序)是否遵循 RTL 的视觉阅读方向,因为某些框架不会自动反转 DOM/Tab 顺序。
- 验证第三方组件(日期选择器、图表、富文本编辑器)是否遵循
dir——许多常用库默认仅支持 LTR,需要明确启用 RTL 模式或覆盖 CSS。
常见错误
- 使用物理 CSS/Tailwind 属性(
ml-*、left、text-align: left),导致语言环境切换到 RTL 时布局悄然出错。 - 镜像不应镜像的图标(例如钟表或“播放”三角形),这会让 RTL 用户觉得视觉效果不自然。
- 将翻译后的字符串与硬编码的标点或顺序拼接(例如
name + ": " + value),而不是使用 ICU 消息格式化,从而破坏 RTL 语言环境中的词序。 - 以为仅设置
dir="rtl"就能解决所有问题——行内样式、通过 canvas 绘制的界面,以及使用left/right定位的绝对定位元素仍需手动改用逻辑属性。
评论
支持 Markdown