本文约 3,976 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:切到阿拉伯语,整个页面像是「没对齐」
做外贸或多语言站点的同学,给站点加上阿拉伯语、希伯来语、波斯语之后,常会遇到这种画面:文字确实从右往左排了,但侧边栏还在右边、图标箭头还指向右、进度条方向反了、圆角按钮的圆角还在错误的一侧。整体感觉「每个元素都差一点」。
原因很简单:把文字方向改成 RTL 只解决了文本流,没有解决布局镜像。传统 CSS 用的是 margin-left、padding-right 这类物理属性,它们不会随 direction 自动翻转。要真正适配 RTL,得改用逻辑属性(margin-inline-start 等),或者写一套 rtl.css 覆盖。本文讲清 WordPress 的 RTL 判定机制、自动加载 rtl.css 的规则、以及哪些视觉元素必须单独处理「不能镜像」。
原理分析:WordPress 怎么判断 RTL
WordPress 通过语言包里的 rtl 标记决定当前是否为 RTL。核心函数 is_rtl() 读取全局的 $wp_locale 的 text_direction 属性,返回 rtl 即认为是 RTL 语言。启用后有两件事会自动发生:
<html>标签上会输出dir="rtl"属性;body_class()会额外输出一个rtl类;- 主题根目录下的
rtl.css会被自动加载(如果存在),加载顺序在style.css之后。
前两点给了你写选择器的抓手(.rtl .xxx),第三点是 WordPress 官方推荐的 RTL 适配方式。注意 rtl.css 必须放在主题根目录且文件名完全小写,子主题的 rtl.css 会覆盖父主题的。
| 处理方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
rtl.css 覆盖 |
已有主题改造 | 不动主样式,风险低 | 维护两份,易遗漏 |
| CSS 逻辑属性 | 新主题开发 | 一份代码双向通用 | 旧浏览器支持需确认 |
[dir="rtl"] 选择器 |
精细控制 | 可与主样式同文件 | 选择器变长 |
| 自动翻转工具(RTLCSS) | 构建流程 | 自动生成 rtl.css | 需构建链,例外要标注 |
关于「不能镜像」的例外,这是最容易出错的地方:方向性图标(箭头、播放键)、进度条、阴影方向、以及拉丁文字与数字都不应翻转。阿拉伯语页面里的英文品牌名和数字仍按 LTR 排,需要对这些元素显式声明 direction: ltr。
多语言插件方面,Polylang 与 WPML 都会正确设置语言对应的文本方向,主题无需额外处理;但主题的 style.css 若写死了物理属性,插件也无能为力。语言切换与内容翻译的组织方式可参考 WordPress 多语言插件选型。
保姆级实操
- 确认
is_rtl()生效:切到阿拉伯语后查看源代码,<html>上应有dir="rtl",<body>的 class 里应有rtl。没有则说明语言包未正确加载。 - 建
rtl.css:在子主题根目录新建rtl.css,只写需要翻转的规则,不复制整份style.css。 - 新写样式优先用逻辑属性:
margin-inline-start等价于 LTR 下的margin-left、RTL 下的margin-right,一份代码两边正确。 - 处理不能镜像的元素:给方向性图标、进度条、含拉丁文字的块显式设
direction: ltr,或用/* rtl:ignore */之类的注释配合构建工具排除(若使用 RTLCSS)。 - 字体与数字:阿拉伯语常用字体(如 Noto Naskh Arabic、Tajawal)需要在
rtl.css里单独声明;数字与英文片段用unicode-bidi: isolate避免标点位置错乱。 - 验证:切换到 RTL 语言,逐页检查侧边栏位置、表单对齐、箭头方向、导航下拉方向、以及移动端断点下的表现。
<?php
// 子主题 functions.php:确认并按需要加载 rtl.css
add_action( 'wp_enqueue_scripts', function() {
if ( is_rtl() ) {
wp_enqueue_style(
'mimangfei-rtl',
get_stylesheet_directory_uri() . '/rtl.css',
array(),
wp_get_theme()->get( 'Version' )
);
}
}, 20 );
// 给 body 补一个语言类,方便按语言精细控制
add_filter( 'body_class', function( $classes ) {
$classes[] = 'lang-' . sanitize_html_class( determine_locale() );
if ( is_rtl() ) {
$classes[] = 'is-rtl';
}
return $classes;
} );
/* rtl.css:只写需要翻转的规则 */
.rtl .site-content {
flex-direction: row-reverse;
}
.rtl .main-navigation ul ul {
left: auto;
right: 0;
}
.rtl .entry-meta time {
direction: ltr;
unicode-bidi: isolate; /* 让日期数字保持 LTR,避免标点跑到错误一侧 */
}
.rtl .widget-area {
border-left: 0;
border-right: 1px solid #eaeaea;
}
/* 新写样式推荐:使用逻辑属性,一份代码适配双向 */
.card {
margin-inline-start: 16px;
padding-inline-end: 24px;
border-start-start-radius: 8px;
text-align: start;
inset-inline-start: 0;
}
.progress-bar {
direction: ltr; /* 进度条方向不随语言翻转 */
}
.icon-arrow::before {
/* 方向性图标需按语言单独指定,不能简单翻转 */
content: "\2192";
}
.rtl .icon-arrow::before {
content: "\2190";
}
<!-- 局部混排:阿拉伯语段落里的英文品牌名保持 LTR -->
<p dir="rtl">
مرحبا بالعالم
<span dir="ltr" class="brand-latin">mimangfei.com</span>
هو موقع تقني.
</p>
常见踩坑
- 以为
dir="rtl"会自动翻转一切:物理属性不会翻转,必须靠rtl.css或逻辑属性。 rtl.css放在了assets/css/下:WordPress 只在主题根目录自动加载它,子目录里不会被自动引入(可手动 enqueue,但要注意加载顺序)。- 翻转了不该翻转的元素:箭头、播放按钮、进度条翻转后语义就错了。这是 RTL 适配里最高频的错误。
- 数字与标点位置错乱:混排内容缺少
unicode-bidi: isolate,括号和百分号会跑到奇怪的位置。 - 只测桌面端:RTL 下的移动端断点常常另有一套
float或left/right,必须逐断点验证。 - 案例:一个面向中东市场的 B2B 站点上线阿拉伯语版后,客户反馈「页面看起来是坏的」。排查发现主题用
float: left排商品卡片、margin-left做间距,切到 RTL 后卡片仍从左排起,与从右开始的文字冲突。改造方案是把新写的组件全部改成逻辑属性(margin-inline-start),历史组件在rtl.css里补翻转规则,同时把分页箭头和播放图标排除在翻转之外。两周后客户确认视觉正常。关键教训:RTL 不是「镜像一切」,而是「镜像布局、保留方向性语义」。 - 多语言插件未正确设置方向:极少数情况下语言包的
text_direction未定义,is_rtl()返回 false,页面完全不会翻转,需检查语言包文件。相关排查见WordPress 多语言配置。
总结
RTL 适配的判断标准:切到阿拉伯语后,<html dir="rtl"> 与 body.rtl 必须出现;布局的左右关系必须整体镜像;而箭头、播放键、进度条、拉丁文字与数字必须保持 LTR。落地方式是「新代码用逻辑属性 + 历史代码用 rtl.css 覆盖 + 例外元素显式声明」,三者缺一不可。验证不能只看首页,要覆盖列表页、详情页、表单页与移动端。中文字体与编码相关的处理是另一条线,见 繁体中文与简体的显示处理。
