阿拉伯语就绪输出
目标:在任意输出格式中,首次尝试即让阿拉伯语正确渲染、阅读自然且具有原生感。
1. 在撰写任何内容之前,先决定三件事
| 决策项 | 默认值 | 何时更改 |
|---|---|---|
| 受众区域 | ar + 已知地区(如 ar-SA、ar-EG、ar-AE、ar-MA...) | 用户指定国家/城市/市场 |
| 数字 | UI、价格、电话、代码、图表中使用西方 0-9。面向埃及、沙特阿拉伯、伊拉克、黎凡特、苏丹、也门的正式/编辑文本使用阿拉伯-印度数字 ٠-٩ | 用户要求,或品牌/地区明确使用 ٠-٩。马格里布(MA/DZ/TN)始终使用 0-9 |
| 语体 | 现代标准阿拉伯语(فصحى),清晰现代,非古典语体 | 用户要求方言(埃及、海湾、黎凡特...),或渠道为休闲场合(WhatsApp促销、社交媒体帖子):参见 references/writing.md |
永远不要在同一个输出中混用数字系统。
2. 核心规则(适用于所有输出类型)
- 在根元素声明方向,仅一次。 然后让所有元素继承。
❌
<html>+ 在元素上散布style="direction:rtl"✅<html lang="ar" dir="rtl">· docx<w:bidi/>+<w:rtl/>· pptxrtl="1"· FlutterDirectionality(textDirection: TextDirection.rtl)/locale: Locale('ar') - 使用逻辑方向,永远不要用 left/right。 在阿拉伯语中,“Start”在右侧。
❌
margin-left、ml-4、text-left、left: 0、EdgeInsets.only(left:)✅margin-inline-start、ms-4、text-start、inset-inline-start: 0、EdgeInsetsDirectional.only(start:) - 隔离 LTR 孤岛(电话号码、电子邮件、URL、代码、数字旁边的英文名称、负数)。
❌
اتصل على +966 50 123 4567.→ 渲染为4567 123 50 966+✅اتصل على <bdi dir="ltr">+966 50 123 4567</bdi>.· 纯文本:包裹在 LRI…PDI(…)中,或在-5前放置 LRM - 电话、电子邮件、URL、代码、IBAN、密码的输入框保持
dir="ltr",即使在 RTL 表单内部(使用text-end对齐)。 - 仅镜像方向性图标。 后退/前进箭头、V形符号、发送、回复、撤销/重做、进度方向需要翻转。播放/暂停、媒体控件、对勾、时钟、搜索、徽标、品牌标识和数字不需要翻转。
- 排版: 使用专为阿拉伯语设计的字体(列表见
references/typography.md),正文行高 ≥ 1.6,并在上方和下方为发音符号(tashkeel)留出空间。切勿对阿拉伯语应用letter-spacing/tracking-*、uppercase、italic或过紧的overflow:hidden高度。 - 字形连接:将原始文本传递给支持字形的渲染器,将已连接的文本传递给不支持字形的渲染器。切勿两者都做。
浏览器、Word、LibreOffice、PowerPoint、WeasyPrint、Chromium PDF、matplotlib ≥ 3.11、支持 libraqm 的 Pillow、fpdf2 与
set_text_shaping()本身就能连接阿拉伯语:传递原始字符串。 reportlab、PyMuPDFinsert_text、OpenCV、matplotlib ≤ 3.10、不带 raqm 的 Pillow 逐字形绘制:传递prepare(text)(来自scripts/shape_text.py)。 为已经支持字形连接的渲染器重新连接文本会导致逆向操作(已在 matplotlib 3.11 和 Pillow+raqm 中验证)。 - 阿拉伯语标点符号: 使用
،逗号、؛分号、؟问号、«»引号。保留.和!。标点符号前无空格,后有一个空格。 - 以阿拉伯语原生方式写作,不要逐字翻译。 按钮使用祈使动词(
أرسل、احفظ、ابدأ الآن),不要使用英语语序。参见references/writing.md。 - 使用区域设置格式化数字/日期/货币,不要使用字符串拼接。 使用
Intl.NumberFormat('ar-SA', ...)/Intl.DateTimeFormat('ar-EG-u-nu-latn', ...),并始终显式设置nu(数字)和ca(日历)。
3. 根据输出类型加载参考文件
仅读取任务所需的文件:
| 输出类型 | 读取文件 |
|---|---|
| HTML、CSS、Tailwind、React、Next.js、Vue、React Native、Flutter、HTML邮件 | references/web.md + references/bidi.md |
| 任何混合阿拉伯语+英语/数字的内容(包括 Markdown、纯文本、短信、JSON 字符串) | references/bidi.md |
| 字体、行高、发音符号、字重、两端对齐 | references/typography.md |
| Word (.docx)、PowerPoint (.pptx)、PDF | references/documents.md |
| matplotlib、Pillow、SVG、canvas、OpenCV、Plotly、任何带文本的图像 | references/charts-images.md |
| 文案写作、翻译、方言、数字、日期、货币、姓名、伊历 | references/writing.md |
4. 在 RTL 中翻转和不变的内容
| 翻转(镜像布局) | 保持不变 |
|---|---|
| 阅读顺序、文本对齐、导航顺序、侧边栏位置 | 电话号码、信用卡号、IBAN(始终 LTR) |
面包屑导航、分页、步骤条:“下一步”指向左侧。文本 › > ( 自动镜像,但 → 和 SVG 图标不自动镜像 | 代码块、终端输出、URL、电子邮件 |
| 后退/下一步箭头、V形符号、轮播/滑块滑动方向 | 时间序列图表 x 轴(时间从左到右)。分类轴可能翻转 |
| 表格列顺序(第一列在右侧) | 媒体控件(播放 ▶、快进)、时钟、对勾 |
| 进度条和范围滑块从右侧填充 | 徽标、品牌标识、照片、地图 |
表单标签在右侧,关闭按钮 × 在对话框左侧 | 数学表达式和数字本身(1,234.5 保持 1,234.5) |
| Toast/抽屉滑入侧、头像上的徽章、列表项目符号 | 键盘快捷键(Ctrl+S) |
5. 完成之前
- 对生成的任何代码运行 linter(它只需要 Python 标准库):
python <skill-dir>/scripts/rtl_check.py <文件或文件夹>修复所有error。除非有意为之,否则修复warnings,并在有意保留的 warning 旁添加rtl-ok注释。 - 在可能的情况下渲染并观察,然后检查字母是否连接、第一个单词是否在右侧、标点符号是否在左端、数字顺序是否正确:
- HTML:
python -m playwright screenshot --full-page file://$PWD/index.html shot.png(或npx playwright screenshot …)。如果浏览器不可用,weasyprint index.html out.pdf可提供静态渲染。 - docx/pptx:
soffice --headless --convert-to pdf file.docx,然后将 PDF 栅格化。 - PDF → PNG:
python -c "import pymupdf; pymupdf.open('f.pdf')[0].get_pixmap(dpi=110).save('f.png')" - 图像/图表:打开您编写的 PNG 文件。
- HTML:
- 如果脚本无法运行(无 Python、无 shell),请手动检查此清单:
- 根元素
dir="rtl"+lang="ar…"(或对应格式的等效项) - 间距、定位或对齐中无
left/right - 电话/电子邮件/URL/代码已隔离且为 LTR
- 方向性图标已镜像,其他图标未改动
- 已加载阿拉伯语字体,行高 ≥ 1.6,无字母间距、斜体或大写
- 图像/PDF 文本:字形连接路径与渲染器匹配(规则 7)
- 使用了
،؛؟,使用一种数字系统,自然的现代标准阿拉伯语(或要求的方言)
- 根元素
脚本
scripts/rtl_check.py <路径>:对 HTML/CSS/Tailwind/JSX/TSX/Vue/Svelte/React Native/Flutter 进行 RTL 错误检查。输出文件:行、问题描述和确切的修复方法。有错误时退出码为 1。仅使用标准库。scripts/shape_text.py:prepare(text, target)用于不支持阿拉伯语字形连接的渲染器。它会检测 matplotlib/Pillow 的原生支持,并在不需要字形连接时原样返回文本。它使用arabic-reshaper+python-bidi(按需 pip 安装),否则回退到内建的标准库字形连接器。python shape_text.py --check报告当前机器需要什么。