mcpField
R
rtl-internationalization

rtl-internationalization

github.com/mindrally设计与 UI28788 次安装3 周前更新
代码仓库

关于 rtl-internationalization

帮助开发者让 Web 和 React Native 界面支持从右向左书写的语言。内容涵盖方向感知布局、双向文本、本地化和 RTL 测试。

主要功能

  1. 01审查物理方向样式
  2. 02采用逻辑 CSS 与 Tailwind 属性
  3. 03运行时设置文本方向
  4. 04处理双向用户文本
  5. 05调整方向性图标与控件
  6. 06本地化并测试 RTL 界面

适用场景

  1. 01审查 Web 界面的 RTL 问题
  2. 02支持阿拉伯语或希伯来语
  3. 03检查界面中的混合文字方向
  4. 04添加 RTL 视觉回归检查

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mindrally/skills --skill rtl-internationalization

安装后在 Claude Code 中输入/rtl-internationalization确认已加载。

详细介绍

RTL(从右到左)国际化

支持希伯来语、阿拉伯语、波斯语和乌尔都语等 RTL 语言,需要使用与方向无关的 CSS 构建布局,并将文本方向视为一项一等属性,可在运行时切换,而不是将其固定在左右样式中。

构建 RTL 安全界面的工作流

  1. 检查物理属性 — 在代码库中搜索 margin-left/right、padding-left/right、left/right 定位、text-align: left/right,以及 ml-*、mr-*、pl-*、pr-*、left-*、right-* 等 Tailwind 类。
  2. 转换为逻辑属性 — 将每个物理属性/类替换为对应的逻辑属性(margin-inline-start、ms-* 等),这样浏览器会根据 dir 自动翻转。
  3. 在根节点设置方向 — 在 <html> 或顶层容器上应用 dir="rtl"(或 dir="auto"),并由当前语言区域驱动,而不是在各个组件中硬编码。
  4. 处理混合文字 — 对方向可能与周围文本不同的用户生成内容或插值字符串使用 <bdi> 包裹。
  5. 检查图标和方向性组件 — 镜像翻转箭头、尖括号和后退/前进按钮;非方向性图标(搜索、设置、主页)保持原样;反转轮播、滑块和进度条的方向。
  6. 将所有字符串外置 — 通过翻译函数处理每一条面向用户的字符串,并使用 Intl API 处理数字、货币和日期,而不是手动格式化。
  7. 在 RTL 模式下测试 — 使用 dir="rtl" 和真实的 RTL 内容(而不只是镜像后的 LTR 占位文本)渲染应用,并对每个屏幕进行视觉验证。

CSS 逻辑属性

始终使用 CSS 逻辑属性,而不是物理属性——逻辑属性会根据元素的 direction 和 writing-mode 自动解析为正确的物理方向,因此同一份样式表无需重复即可同时适用于 LTR 和 RTL。

物理属性(避免使用)逻辑属性(使用)
margin-leftmargin-inline-start
margin-rightmargin-inline-end
padding-leftpadding-inline-start
padding-rightpadding-inline-end
leftinset-inline-start
rightinset-inline-end
border-leftborder-inline-start
border-rightborder-inline-end
text-align: lefttext-align: start
text-align: righttext-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