必须为每个<p>显式设置lang和dir属性,以确保多语言混排时文本流、对齐、标点及屏幕阅读器行为准确;lang不可继承,需用BCP 47标准值;混排内容须用<bdi>隔离,CSS应基于:lang()伪类而非属性选择器。

<p> 标签本身不自动适配排版方向,必须配合 lang 和 dir 属性协同工作,才能在多语言切换时正确呈现文本流、对齐方式与标点行为。
<p> 的语言声明必须显式写在每个段落上
浏览器和屏幕阅读器不会继承父级 lang 值,只依据 <p> 自身的 lang 属性决定字体回退、连字规则、标点宽度和拼写检查。
- ✅ 正确:
<p lang="ar">مرحبا بك في موقعنا</p>(阿拉伯语段落) - ✅ 正确:
<p lang="zh-Hans">欢迎访问我们的网站</p>(简体中文段落) - ❌ 错误:仅靠
<html lang="ar">就省略<p>的lang——中文混排时顿号、逗号会按英文间距渲染,视觉拥挤
所有含文本的 <p> 都应带合法 BCP 47 语言标签:zh-Hans、ar、he、fa、ur 等;避免 zh_CN、chinese 或 zh 这类非标准写法。
<p> 的方向控制依赖 dir,但不能只靠它
dir="rtl" 写在 <p> 上能翻转该段文本流、text-align: start 解析为右对齐、<bdi> 内部隔离生效,但它不改变块级布局逻辑:
立即学习“前端免费学习笔记(深入)”;
-
margin-left: 16px仍向左偏移,不是“逻辑左侧” -
width、height、margin-top完全不受影响 - Flex/Grid 主轴起点只在父容器设
dir="rtl"时才整体翻转
所以真正可靠的写法是:
-
<html dir="rtl" lang="ar">(整页 RTL 基线) -
<p lang="ar" dir="rtl">...</p>(双重保障,尤其表单内嵌段落) -
<p lang="en" dir="ltr">...</p>(混排英文时强制 LTR,避免被父级 RTL 拖拽错乱)
混合方向内容要用 <bdi> 包裹,别用 dir="auto"
当 <p> 里插入 API 返回的用户名或搜索词(如 "أحمد Smith"),首字符可能是中性字符或 ASCII,dir="auto" 会 fallback 到 LTR,导致阿拉伯名字显示异常。
应这样处理:
<p lang="ar">مرحبا، مرحبا <bdi>{{username}}</bdi>!</p><bdi> 创建独立双向隔离上下文,既不影响 <p> 整体方向,也不反转数字顺序(对比 <bdo> 会把 "123" 显示成 "321")。
CSS 排版要基于 :lang(),而非 [lang]
想让不同语言段落自动应用合适样式,必须用伪类:
p:lang(ar) { text-align: right; }
p:lang(zh-Hans) { line-height: 1.6; }
p:lang(ja) { quotes: "「" "」" "『" "』"; }:lang(ar) 能匹配 <p lang="ar"> 或其任意祖先有 lang="ar" 的 <p>,适合嵌套结构;而 [lang="ar"] 只匹配属性值完全相等的元素,无法处理继承场景。
动态插入段落时,lang 和 dir 必须手动同步
AJAX 加载新 <p> 后,JS 必须立即设置:
-
pElement.lang = 'ar' -
pElement.dir = 'rtl' - 再替换
textContent或innerHTML(防 XSS,纯文本优先)
仅靠 data-i18n 替换文字而不设 lang,会导致屏幕阅读器继续用旧语音引擎朗读,Chrome 翻译按钮也不激活。



















