
使用 python-docx 为阿拉伯语、库尔德语等复杂脚本(rtl)文本设置字体大小时,直接启用 `run.font.rtl = true` 会导致 `font.size` 失效;本文提供基于底层 xml 操作的可靠解决方案,确保 rtl 文本同时支持指定字号、字体及双向排版。
在处理阿拉伯语、波斯语、希伯来语或库尔德语等从右向左(RTL)书写的语言时,python-docx 的高层 API 存在一个已知限制:当设置 run.font.rtl = True 后,常规的 run.font.size = Pt(20) 将被忽略——这是因为 RTL 文本在 Word 中实际依赖复杂脚本(Complex Script, CS)专用格式属性(如
解决此问题的关键是绕过高层封装,直接操作底层 Open XML 元素,显式添加并配置 w:szCs(复杂脚本字号)、w:lang(双向语言标识)、w:rFonts(CS 字体映射)等必需节点。以下是一个生产就绪的工具函数:
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Pt
def fix_cs_formatting_runs(run_to_fix, user_cs_font_size, user_cs_font_name, user_is_bold=False):
"""
修复 python-docx 中 RTL/复杂脚本文本的字体格式丢失问题。
:param run_to_fix: docx.text.run.Run 对象
:param user_cs_font_size: 目标字号(Pt 单位,如 20)
:param user_cs_font_name: 复杂脚本字体名(如 'Arial', 'Segoe UI')
:param user_is_bold: 是否加粗(同时作用于 CS 与拉丁字符)
"""
# 获取或创建 (运行属性容器)
rpr = run_to_fix.element.get_or_add_rPr()
# 确保存在 并设置 CS 字体(关键!)
rFonts = rpr.get_or_add_rFonts()
rFonts.set(qn('w:cs'), user_cs_font_name) # 复杂脚本字体(RTL 文字)
rFonts.set(qn('w:ascii'), user_cs_font_name) # ASCII 字体(英文/数字)
rFonts.set(qn('w:hAnsi'), user_cs_font_name) # 半宽拉丁字体
# 显式添加并设置字号节点:(拉丁)和 (复杂脚本)
# 注意:Word 内部使用半点(half-point)单位,Pt(20) → 20 * 2 = 40
sz = rpr.get_or_add_sz()
szCs = OxmlElement('w:szCs')
rpr.append(szCs)
sz.set(qn('w:val'), str(int(user_cs_font_size * 2)))
szCs.set(qn('w:val'), str(int(user_cs_font_size * 2)))
# 设置双向语言(bidi),推荐使用 'ar-SA'(阿拉伯语-沙特阿拉伯)以激活 RTL 渲染
lang = OxmlElement('w:lang')
lang.set(qn('w:bidi'), 'ar-SA')
rpr.append(lang)
# 可选:同步加粗复杂脚本与拉丁字符
if user_is_bold:
bCs = OxmlElement('w:bCs')
bCs.set(qn('w:val'), 'True')
rpr.append(bCs)
b = OxmlElement('w:b')
b.set(qn('w:val'), 'True')
rpr.append(b) ✅ 使用示例(替换原始代码):
from docx import Document
from docx.shared import Pt
doc = Document("template.docx")
text = ["کوردی بەرێز", "٢٠٢٤"] # 示例库尔德语+阿拉伯数字
for i, paragraph in enumerate(doc.paragraphs):
if '{text}' in paragraph.text:
paragraph.text = paragraph.text.replace('{text}', text[i].strip())
for run in paragraph.runs:
# ✅ 关键:先调用底层修复函数
fix_cs_formatting_runs(run, user_cs_font_size=20,
user_cs_font_name='Arial',
user_is_bold=False)
# ✅ 此后可安全设置高层属性(它们将与底层保持一致)
run.font.name = 'Arial'
run.font.cs_size = Pt(20) # 注意:使用 cs_size 而非 size
run.font.rtl = True⚠️ 重要注意事项:
立即学习“Python免费学习笔记(深入)”;
- cs_size 是必须的:对 RTL 文本,应始终使用 run.font.cs_size = Pt(N) 替代 run.font.size,后者仅影响拉丁字符;
- 字体兼容性:确保所选字体(如 'Arial', 'Segoe UI', 'Noto Sans Arabic')实际支持阿拉伯字符集,否则可能显示方块;
- 语言代码选择:w:bidi='ar-SA' 是最广泛兼容的 RTL 触发器;如需其他语言,可替换为 'fa-IR'(波斯语)、'he-IL'(希伯来语)等;
- 避免重复调用:每个 run 仅需调用一次 fix_cs_formatting_runs(),多次调用可能导致 XML 节点冗余;
- 版本兼容性:该方案适用于 python-docx >= 0.8.11,低版本需确认 OxmlElement 和 qn 的可用性。
通过上述方法,你不仅能稳定应用 RTL 排版,还能精确控制复杂脚本的字体、大小、粗细与语言行为,彻底规避 font.rtl = True 导致的样式失效问题。这是面向多语言文档自动化生成的专业级实践方案。











