关于 hebrew-document-generator
此 Skill 根据提供的内容生成希伯来语 PDF、Word 和 PowerPoint 文档,并说明 RTL 排版及希伯来语与拉丁文字混排。适用于制作文档草稿和模板;不提供法律或税务建议。
主要功能
- 01希伯来语 PDF、DOCX 和 PPTX 指引
- 02RTL 排版与文字脚本处理
- 03合同和发票结构示例
- 04字体与依赖项设置
- 05示例文档生成脚本
适用场景
- 01排版希伯来语合同和报价
- 02制作发票与收据版式
- 03创建希伯来语演示文稿
- 04排查希伯来语与拉丁文字混排问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ skills-il/ localization --skill hebrew-document-generator安装后在 Claude Code 中输入/hebrew-document-generator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evidence.jsonmetadata.jsonoptimization-log.jsonSKILL_HE.mdreferences/domain-checklist.mdhebrew-fonts.mdtemplates.mdscripts/docx_rtl.pygenerate_doc.py详细介绍
希伯来语文档生成器
法律声明
这是一款由 AI 模型运营的免费信息工具。它根据你提供的内容排版和格式化希伯来语文档(PDF、Word 和 PowerPoint),并展示合同、发票、收据和报价方案惯用的章节与字段结构。其所有输出均由 AI 模型自动生成,未经律师、税务顾问或会计师的参与、审阅或批准。输出内容不是法律建议,不是法律意见,也不是由律师起草的文件;它是一个排版模板,由你自己填写和调整。该工具不审查你交易的实际情况,不评估任何条款是否有效或可执行,也不会根据适用于你的法律调整条款。AI 模型可能会出错、遗漏信息或得出错误结论。
本技能起草的任何合同、信函或其他文本均为仅供个人整理使用的自动草稿。它不是由律师起草的文件,不得作为证据依赖。发票和收据示例是排版示例,不是已开具的税务文件。申报和缴纳税款的责任由你承担,具有约束力的计算以税务机关为准,在税务机关面前进行代理仅限法律允许的人员。它不能替代考虑每个人具体情况和需求的建议:在采取法律行动、签署文件或向行政机关或法院提交文件之前,请咨询律师。对输出内容的任何使用均由用户自行承担全部责任。
说明
第 1 步:选择输出格式
| 格式 | 库 | 最适合 | RTL 支持 |
|---|---|---|---|
| reportlab | 发票、税务文件、可打印表单 | 注册希伯来文字体,使用 canvas.drawRightString() | |
| WeasyPrint | 从 HTML/CSS 生成带样式的文档 | 通过 HTML 中的 dir="rtl" 原生支持 | |
| DOCX | python-docx | 合同、提案、会议纪要 | scripts/docx_rtl.py:段落 bidi,按文字系统拆分 run,仅对希伯来文 run 设置 w:rtl,对每个 run 设置 w:cs 字体 |
| PPTX | pptxgenjs (Node) | 演示文稿、幻灯片 | 使用 rtlMode: true 的 RTL 文本框 |
第 2 步:安装依赖项和希伯来文字体
Python PDF 生成:
pip install reportlab weasyprint python-bidi
WeasyPrint 还需要 Pango 系统库。在 macOS 上最简单的方法是 brew install weasyprint;在 Debian 或 Ubuntu 上,请先安装 libpango-1.0-0 libpangoft2-1.0-0 libharfbuzz-subset0,然后再执行 pip install。缺少库时会报错 cannot load library 'libgobject-2.0-0';在已通过 Homebrew 安装 Pango 的 macOS 上,export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib 可以解决。
Python DOCX 生成:
pip install python-docx
Node.js PPTX 生成:
npm install pptxgenjs
推荐的希伯来文字体(安装到系统):
| 字体 | 风格 | 最适合 | 来源 |
|---|---|---|---|
| Heebo | 无衬线,现代 | 网页风格文档、发票 | Google Fonts |
| David | 经典衬线 | 法律合同、正式信函 | 系统(Windows;装有 Microsoft Office 的 macOS) |
| Narkisim | 衬线,优雅 | 提案、邀请函 | 系统(Windows) |
| Frank Ruehl | 传统衬线 | 学术、文学 | Google Fonts (Frank Ruhl Libre) |
| Rubik | 无衬线,圆润 | 演示文稿、营销 | Google Fonts |
| Assistant | 无衬线,简洁 | 商务信函 | Google Fonts |
有关下载链接和安装说明,请参见 references/hebrew-fonts.md。
第 3 步:使用 reportlab 生成希伯来语 PDF
完整的生成流程请参阅 scripts/generate_doc.py。
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.units import mm
from bidi.algorithm import get_display # NOT `from bidi import get_display`, see below
# Register Hebrew font
pdfmetrics.registerFont(TTFont('Heebo', 'Heebo-Regular.ttf'))
pdfmetrics.registerFont(TTFont('Heebo-Bold', 'Heebo-Bold.ttf'))
def create_hebrew_pdf(filename, title, content_lines):
c = canvas.Canvas(filename, pagesize=A4)
width, height = A4
# Title -- right-aligned for RTL
c.setFont('Heebo-Bold', 18)
hebrew_title = get_display(title)
c.drawRightString(width - 20*mm, height - 30*mm, hebrew_title)
# Body lines
c.setFont('Heebo', 12)
y = height - 50*mm
for line in content_lines:
display_line = get_display(line)
c.drawRightString(width - 20*mm, y, display_line)
y -= 7*mm
c.save()
reportlab 处理希伯来语的关键要点:
- 始终使用 python-bidi 的
get_display()来重排字符 - 对右对齐的 RTL 文本使用
drawRightString() - 显式注册 TTF 希伯来语字体——reportlab 没有内置的希伯来语支持
- 将行高设置为至少字体大小的 1.5 倍,以保证希伯来语的可读性
- python-bidi 导入,请使用
from bidi.algorithm import get_display。 python-bidi 0.6.x 提供两套实现。bidi.algorithm是纯 Python 实现,与早期版本兼容,并且会镜像括号。顶层的from bidi import get_display包装了一个 Rust crate,它跳过了镜像规则(上游 issue #25),因此(18%)在 reportlab PDF 中会打印成)18%(,希伯来语行中的每个括号都会反向显示。python-bidi 0.6.x 需要 Python 3.9+。 - 多行文本:
drawRightString()只绘制单行,且不换行。不要将get_display()的输出交给 reportlab 的Paragraph:它会对已经反转的字符串进行换行,导致最后一句出现在顶行,而在没有 bidi 的情况下使用wordWrap='RTL'会让每个单词的字母反向打印。先按逻辑顺序换行,然后对每一行成品运行get_display():scripts/generate_doc.py中的wrap_hebrew_lines()/draw_hebrew_paragraph()就是这么做的。对于长篇流式文档(合同),WeasyPrint(第 4 步)原生支持希伯来语换行。
希伯来语 / 拉丁字母 / 数字混合行
生成文档中最常见的 RTL 失败,是同一行中混合了希伯来语描述、LTR 数字和货币符号,例如发票行项目。get_display() 会处理 bidi 重排,但你必须一次性传入整个逻辑字符串,这样算法才能看到完整上下文:
from bidi.algorithm import get_display
# Logical order: Hebrew description, then qty, unit price, currency
line = 'ייעוץ טכני (3 שעות) - 1,500.00 ש"ח'
c.setFont('Heebo', 11)
c.drawRightString(width - 20 * mm, y, get_display(line))
数字、逗号、句点和括号都能正确落位,因为 bidi 算法会相对于周围的希伯来语来解析它们(并且 bidi.algorithm 会镜像括号)。不要将该行拆成片段自行重排,也不要只对希伯来语部分调用 get_display(),这两种做法都会破坏数字顺序。
第 4 步:使用 WeasyPrint 生成希伯来语 PDF
from weasyprint import HTML
html_content = """
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="utf-8">
<style>
@font-face {
font-family: 'Heebo';
src: url('Heebo-Regular.ttf');
}
body {
font-family: 'Heebo', sans-serif;
direction: rtl;
font-size: 12pt;
line-height: 1.7;
}
h1 { font-size: 18pt; text-align: start; }
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #333;
padding: 6px 10px;
text-align: start;
}
</style>
</head>
<body>
<h1>חשבונית מס</h1>
</body>
</html>
"""
# base_url is required: without it the relative font URL is silently ignored
# and a fallback font (no Hebrew on many Linux servers) is embedded instead.
HTML(string=html_content, base_url='.').write_pdf('invoice.pdf')
WeasyPrint 处理希伯来语的优势:
- 支持 CSS 逻辑属性
- 通过 HTML
dir属性原生支持 RTL - 表格在 RTL 下正确渲染
- 支持
@font-face以使用自定义希伯来语字体
第 5 步:用 python-docx 生成希伯来语 DOCX
DOCX 是希伯来语/英语混排最容易出问题的地方。Microsoft Word 的双向文本处理与 LibreOffice、macOS Preview/Quick Look 以及大多数查看器不同,后者会宽容地渲染输出,从而掩盖了 Word 独有的 bug,因此要在 Word 本身中验证。使用随附的 scripts/docx_rtl.py(把它复制到你的代码旁边或导入它);它实现了以下规则:
- 段落方向: 任何包含希伯来语的行都会获得
<w:bidi/>(RTL 基准方向)并且不设置显式对齐。w:jc是逻辑对齐,因此对 RTL 段落设置jc=right表示行的末尾,而 Word 会把它画在视觉上的左侧。没有jc的 RTL 段落从视觉右侧开始。纯英文行获得 LTR 基准方向和左对齐。 - 按文字脚本拆分 run,希伯来语 run 上带
<w:rtl/>,拉丁字母或数字 run 上绝不带。 如果希伯来语 run 上没有<w:rtl/>,Word 会把混合行的各个 run 从左到右排列:ההסכם נחתם בין חברת Acme בע"מ的各个短语会以相反顺序出现。如果在一个标记为 rtl 的 run 内放入拉丁单词或数字,Word 会将其反转(7/2023变成2023/7)。因此数字要形成自己的 LTR run,数字之间的分隔符(1,500.00、03-1234567)以及%/货币符号要跟随数字,拉丁单词之后的数字(KI-67)要并入该单词,前导的+/-符号要并入其数字(+972-3-1234567),而两种脚本之间的括号和标点要归到希伯来语一侧,这样(גרסה 2).的右括号和句点才能保持在原位。例外情况是紧跟在拉丁单词之后的、包围拉丁文本的一对括号(Acme (Israel)、Office (365)):它留在拉丁 run 中,否则 Word 会把右括号镜像到希伯来语 run 中。字母按其 Unicode 双向类别分类,因此带重音的拉丁字母(Nestlé)仍是一个单词。前导的列表标记(2.、10.)会并入希伯来语 run,这样句点就不会翻转成.2。 - 每个 run 上都要设置复杂脚本属性:
w:cs字体和w:szCs字号(Word 只把w:ascii/w:sz应用于拉丁文本),以及在与w:b/w:i并列的w:bCs/w:iCs。省略w:cs/w:szCs就是典型的“我设置的字体/字号毫无作用”的 bug。 - 绝不插入 Unicode 方向标记或隔离符(U+200E、U+2066-2069):Word 会在 David 字体中把它们画成可见的方框。
import sys
sys.path.insert(0, 'scripts') # wherever docx_rtl.py lives
from docx_rtl import new_hebrew_document, add_rtl_paragraph, add_rtl_table
doc = new_hebrew_document(font='David', size=12) # also sets <w:bidi/> on the section
add_rtl_paragraph(doc, 'חוזה שירותים', size=18, bold=True)
add_rtl_paragraph(doc, 'ההסכם נחתם ביום 13/01/2026 בין חברת Acme בע"מ לבין הלקוח (גרסה 2).')
add_rtl_paragraph(doc, '2. תמורה', bold=True)
add_rtl_table(doc, ['תיאור', 'כמות', 'מחיר', 'סה"כ'],
[['ייעוץ טכני (3 שעות)', 1, '1,500.00', '1,500.00'],
['פיתוח Acme', 2, '600.00', '1,200.00']])
doc.save('contract.docx')
python scripts/docx_rtl.py --output sample.docx 会写出一个涵盖每条规则的示例。以上所有内容都已对照 Microsoft Word 自身的渲染进行了验证(Mac 版 Word 16.113,由 Word 本身导出为 PDF)。
不要对 DOCX 文本调用 get_display()。 Word 会自行运行双向文本算法,所以预先整形会重复应用它并打乱整行。get_display() 只属于 reportlab 路径。
页眉、页脚和编号列表 是独立的文档故事:用相同的逻辑填充它们的段落(模块的 _fill_paragraph(p, text, font, size) 可用于任何段落对象,例如 section.footer.paragraphs[0])。
DOCX 中的希伯来语表格(“表格出来是反的”修复)
表格反转(第一个逻辑列,例如 תיאור,出现在左侧)是列顺序 bug,不是文本方向问题。python-docx 表格没有 <w:bidiVisual/>,因此 Word 按从左到右排列列。希伯来语表格需要同时应用两种修复,而 add_rtl_table 会同时应用两者:
- 列顺序:
table.table_direction = WD_TABLE_DIRECTION.RTL会输出<w:bidiVisual/>,从而将第一个逻辑列绘制在右侧。table.alignment = WD_TABLE_ALIGNMENT.RIGHT会让表格块紧贴右边距。 - 单元格文本: 每个单元格都是独立段落,因此它会获得
<w:bidi/>以及规则 2 中按文字系统划分的 run,并且不设置显式对齐。在 RTL 单元格上设置“右对齐”会把希伯来语推到视觉上的左侧,而数字单元格仍保持右侧(v1.7.0 bug)。
表头和行数据都保持逻辑顺序;一旦设置了 bidiVisual,你自己再反转列列表就会造成双重反转。对于发票合计块,标签单元格通常通过 row.cells[a].merge(row.cells[b]) 跨列;合并后的跨列在 bidiVisual 下可能落到错误一侧,因此请在 Word 中检查合并后的行。
步骤 6:使用 pptxgenjs 生成希伯来语 PPTX
const pptxgen = require('pptxgenjs');
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9';
pptx.rtlMode = true;
const slide = pptx.addSlide();
// Hebrew title
slide.addText('סקירה רבעונית', {
x: 0.5, y: 0.5, w: '90%', h: 1.0,
fontSize: 28,
fontFace: 'Heebo',
color: '1a1a2e',
align: 'right',
rtlMode: true,
lang: 'he-IL', // default is en-US: PowerPoint would spell-check the Hebrew as English
bold: true,
});
// Hebrew bullet points
slide.addText([
{ text: 'תוצאות כספיות', options: { bullet: true, rtlMode: true } },
{ text: 'יעדים לרבעון הבא', options: { bullet: true, rtlMode: true } },
{ text: 'סיכום פעילות', options: { bullet: true, rtlMode: true } },
], {
x: 0.5, y: 2.0, w: '90%', h: 3.0,
fontSize: 18,
fontFace: 'Heebo',
align: 'right',
rtlMode: true,
lang: 'he-IL',
});
pptx.writeFile({ fileName: 'quarterly-review.pptx' });
PPTX 表格与 DOCX 有同样的 RTL 列顺序问题。pptxgenjs 会按你的 rows 数组顺序渲染表格列,它不会为 RTL 自动镜像。为了让第一个逻辑列显示在右侧,请在数据中逐行反转单元格顺序,并在每个单元格的 options 上设置 rtlMode: true(以及 align: 'right'),这样每个单元格内的文本就会右对齐并接受 bidi 处理:
// Logical columns: תיאור | כמות | מחיר. Reverse per row so col 1 displays on the right
const headers = ['תיאור', 'כמות', 'מחיר'];
const dataRows = [['ייעוץ', '1', '1,500.00']];
const opt = { rtlMode: true, align: 'right', fontFace: 'Heebo', lang: 'he-IL' };
const tableRows = [headers, ...dataRows].map(
row => [...row].reverse().map(text => ({ text, options: opt }))
);
slide.addTable(tableRows, { x: 0.5, y: 1.5, w: 9 }); // rtlMode is a per-cell text option, not a table option
注意这与 DOCX 的约定相反:python-docx 暴露了真正的 bidiVisual 列翻转(table_direction = RTL),因此你可以让数据保持逻辑顺序;而 pptxgenjs 没有这样的标志,因此你需要自己在数据中反转列。请验证渲染后的幻灯片。
步骤 7:以色列业务文档模板
每种文档类型的字段列表见 references/templates.md。
| 模板 | 希伯来语名称 | 核心字段 |
|---|---|---|
| Tax Invoice | חשבונית מס | “חשבונית מס”和“עוסק מורשה”字样、商家名称、地址和 osek 编号、序列号、日期、交易详情、税前价格、VAT(18%)和总计、原件上的“מקור” |
| Contract | חוזה | 各方、TZ/公司编号、条款、签名、日期 |
| Price Proposal | הצעת מחיר | 商家详情、逐项定价、有效期、条款 |
| Meeting Minutes | פרוטוקול | 日期、参会者、议程、决议、行动项 |
| Receipt | קבלה | 商家名称、收据编号、金额、付款方式、日期 |
在生成“发票”之前,先询问用户实际需要哪种文档。 עוסק פטור 不收取 VAT,且不得开具 חשבונית מס 或 חשבונית מס/קבלה;它在收到付款时开具 קבלה。עוסק מורשה 开具 חשבונית עסקה 或 חשבונית מס、付款时的 קבלה,或仅在交易时即收到付款的情况下开具合并的 חשבונית מס/קבלה。חשבון עסקה(付款请求)是一种无申报义务的自由格式文档。
分配编号(מספר הקצאה,Israel Invoices 模型): 自 2026 年 6 月 1 日起,当交易在税前金额超过 5,000 NIS 且买方是要求提供该编号的 עוסק מורשה 时,税务发票上必须包含该编号(2025 年为 20,000 NIS,自 2026 年 1 月 1 日起为 10,000 NIS);没有它,买方就不能抵扣进项 VAT。阈值一直在变化,因此请将其视为时效敏感信息。
随附样例是版式,不是已开具的文档。 真正的税务发票是从预印本或经授权的开票软件打印,分为原件和副本,分配编号来自税务局。使用样例来把希伯来语版式做对,并把需要开具发票的用户引导到开票软件(见 green-invoice skill)。
示例
示例 1:生成税务发票 PDF
用户说:“为我的企业创建一份希伯来语税务发票 PDF” 结果:首先询问该企业是 עוסק מורשה 还是 עוסק פטור,以及款项是否已收到(第 7 步),然后使用 reportlab 或 WeasyPrint 构建 A4 PDF:包含必需字样的企业抬头、序列号、逐项表格、18% 的增值税、以 NIS 计的总计、分配编号字段,以及一条说明:该文件是版式示例,而非已开具的税务发票。
示例 2:创建希伯来语合同 DOCX
用户说:“以 Word 文档形式起草一份希伯来语服务合同”
结果:使用 scripts/docx_rtl.py(第 5 步):<w:bidi/> 段落且不设置显式对齐,按文字系统分别设置的 run,并在希伯来语 run 上添加 <w:rtl/>,使嵌入的英语和数字保持原位,使用 w:cs 字体和 w:szCs 字号、David 字体,以及结构化章节(各方、范围、付款条款、终止、签名)。根据法律声明将其作为草稿呈现。
示例 3:构建希伯来语演示文稿
用户说:“为我们的季度回顾制作一份希伯来语 PowerPoint”
结果:使用 pptxgenjs,并在每个文本框中设置 rtlMode 和 lang: 'he-IL',使用 Heebo 字体、右对齐文本、RTL 项目符号,以及表格中反转的列顺序。
示例 4:批量生成文档
用户说:“从 CSV 文件生成 50 份希伯来语发票 PDF”
结果:scripts/generate_doc.py 没有 CSV 输入。导入其 generate_invoice(filename, font_name, business_info) 和 register_hebrew_font() 并遍历各行,或将其绘图辅助函数复制到你自己的循环中。它绘制一页且没有分页符,因此请自行拆分较长的项目列表。对于必须依法开具的文档,请转用开票软件(第 7 步)。
捆绑资源
脚本
scripts/generate_doc.py- 使用 reportlab 生成的希伯来语发票和收据 PDF 示例:带字形检查的希伯来语字体注册(自动检测希伯来语系统字体,遇到问题时以代码 2 退出,而不是打印方框)、括号安全的双向文本重排序、按逻辑顺序换行、18% 的增值税。运行:python scripts/generate_doc.py --helpscripts/docx_rtl.py- 适用于 python-docx 的 Word 安全希伯来语段落、表格和 RTL 节(第 5 步)。导入它,或运行python scripts/docx_rtl.py --output sample.docx。
参考资料
references/hebrew-fonts.md- 希伯来语字体目录,包含适用于不同文档类型的推荐字体(无衬线、衬线、等宽)、Google Fonts 下载链接、系统字体可用性矩阵、字体搭配建议,以及 macOS、Linux 和 Windows 的安装说明。references/templates.md- 以色列商业文档模板:税务发票的必需字段、每种类型的企业开具哪种文档,以及合同、提案、收据和会议纪要的惯用字段、增值税规则和标准希伯来语商务用语。
参考链接
| 来源 | URL | 需要检查的内容 |
|---|---|---|
| reportlab 文档 | https://docs.reportlab.com/ | Canvas API、platypus flowables、字体注册 |
| WeasyPrint 文档 | https://doc.courtbouillon.org/weasyprint/stable/ | HTML/CSS 转 PDF、RTL 支持、@font-face |
| python-docx 文档 | https://python-docx.readthedocs.io/ | 文档模型、run、段落属性 |
| python-bidi (PyPI) | https://pypi.org/project/python-bidi/ | 当前版本、导入路径、变更日志 |
| Kol Zchut:税务发票、交易发票和收据 | https://www.kolzchut.org.il/he/הוצאת_חשבונית_מס,_חשבונית_עסקה_וקבלה | 必需字段、谁可以开具哪种文档 |
| 以色列税务局:分配编号阈值 | https://www.gov.il/he/pages/pa240525-1 | 当前 Israel Invoices 阈值 |
推荐的 MCP 服务
没有 MCP 服务适用于此技能。希伯来语文档生成完全通过本地 Python 和 Node 库(reportlab、WeasyPrint、python-docx、pptxgenjs)运行;没有可包装为 MCP 服务的外部服务。请直接使用捆绑脚本和“说明”部分中的代码。
易错点
get_display()必须在绘制时逐行应用,紧接在drawRightString()之前,而不是在整个多行文档或块上一次性应用。bidi 算法不是幂等的:对已经重排过的文本再次运行会双重反转字符,产生乱序输出。Agent 常犯的一个错误是先把整组行通过get_display()“预处理”一遍,然后在绘制循环里再调用一次。- PDF 生成器通常默认从左到右的文本流向。希伯来语文档必须使用 RTL 段落方向,而希伯来语-英语混排文本需要正确的 BiDi(双向)算法支持。
- DOCX(python-docx)有一个与 PDF 相反的陷阱:不要对文本运行
get_display(),Word 会自行应用 bidi 算法。导致希伯来语 Word 文件“损坏”的失败模式有:(a) 整行混排文本放在一个 run 中并标记<w:rtl/>(数字和英文会反向),(b) 混排行中的希伯来语 run 没有<w:rtl/>(短语会以相反顺序出现),(c) 对 RTL 段落设置jc=right(文本左对齐),(d) 没有复杂脚本的w:cs字体 /w:szCs字号(你的字体和字号永远不会应用到希伯来语上)。scripts/docx_rtl.py规避了这全部四种情况。 - 在 reportlab PDF 中,
from bidi import get_display(Rust 实现)不会镜像括号,因此希伯来语中的每个(...)都会反向打印。请从bidi.algorithm导入。 - 手动向已有的希伯来语段落追加 run(例如签名行)会跳过按脚本拆分和
<w:rtl/>标记。请改用add_rtl_paragraph构建整行。 - 反向的希伯来语 DOCX 表格(第一列在左侧)是列顺序 bug,不是文本方向问题。
add_rtl_paragraph和逐单元格 bidi 对此无能为力:python-docx 表格没有<w:bidiVisual/>,所以 Word 按 LTR 布局列。请在表格上设置table.table_direction = WD_TABLE_DIRECTION.RTL,并且让每个单元格都经过逐单元格 bidi 辅助函数,两者都需要(参见“DOCX 中的希伯来语表格”)。请让列数据保持逻辑顺序,一旦设置了bidiVisual,自己再反转就会双重反转。 - Agent 可能会选择缺少希伯来语字符支持的字体(例如 Arial 可以,但许多装饰性拉丁字体不行)。务必验证字体包含希伯来语 Unicode 范围(U+0590-U+05FF)。
- 希伯来语日期格式在世俗语境中使用 DD/MM/YYYY,在宗教/传统文档中使用希伯来历日期(例如 15 Adar 5786)。Agent 可能会默认使用 MM/DD/YYYY。
- 以色列的法律文档需要特定格式:标准商务/法律希伯来语中不使用 nikud(元音符号)。Agent 可能会添加 nikud,以为它能提升清晰度,但在正式文档中它实际上显得不专业。
故障排查
错误:“希伯来语字符显示为方框或问号”
原因:希伯来语字体未注册或系统上未找到
解决方案:下载一个希伯来语 TTF 字体(例如来自 Google Fonts 的 Heebo),对 reportlab 使用 pdfmetrics.registerFont() 注册它,或对 WeasyPrint 将其安装为系统字体。
错误:“文本显示为从左到右而非从右到左”
原因:缺少 bidi 重排或 RTL 方向设置
解决方案:对 reportlab,应用来自 bidi.algorithm 的 get_display()。对 python-docx,使用 scripts/docx_rtl.py 构建段落(在段落上设置 <w:bidi/>,在希伯来语 run 上设置 <w:rtl/>)。对 WeasyPrint,确保 HTML 元素上有 dir="rtl"。
错误:“数字和标点位置错误”
原因:双向文本算法未正确处理希伯来语/数字混合内容
解决方案:对于 reportlab,将整个逻辑字符串一次性传给 bidi.algorithm 中的 get_display()(参见“希伯来语 / 拉丁语 / 数字混合行”);如果括号输出为 )...(,说明使用了顶层 Rust 的 bidi 导入。在 WeasyPrint 中,为 <html> 元素设置 dir="rtl",并按逻辑顺序传入文本:其文本引擎按逻辑顺序排版该行(已用 WeasyPrint 70 验证,尽管 WeasyPrint 的文档仍将双向文本列为不支持的功能),因此切勿用 get_display() 预先重排 HTML 文本,并检查渲染后的 PDF。对于 DOCX/python-docx,采取与 PDF 修复相反的做法:切勿调用 get_display()(Word 会自行重排)。在段落上设置 <w:bidi/>,将行拆分为按文字系统划分的 run,仅将希伯来语 run 标记为 <w:rtl/>,并在每个 run 上设置 w:cs 字体 + w:szCs 字号(参见步骤 5)。
错误:“希伯来语 Word(.docx)渲染时英语出现在错误的一侧,或我的字体/字号被忽略”
原因:整个混合行位于一个标记为 <w:rtl/> 的 run 中(英语和数字被反转),混合行的希伯来语 run 未携带 <w:rtl/>(短语顺序颠倒),或者 run 只设置了 w:ascii/w:sz 而从未设置复杂文字的 w:cs/w:szCs(希伯来语忽略字体/字号)。对 <w:rtl/> 的简单存在性检查在一个仍然渲染错误的文件上也会通过,因此要验证 run 结构,而不仅仅是标记。
解决方案:使用 scripts/docx_rtl.py(步骤 5):按文字系统划分 run,仅在希伯来语 run 上设置 rtl,在每个 run 上设置 w:cs + w:szCs。
错误:“希伯来语表格(.docx)渲染反了,第一列在左边”
原因:这是列顺序 bug,不是文本方向 bug。python-docx 表格在 <w:tblPr> 上没有 <w:bidiVisual/>,因此 Word 从左到右排布列,第一个逻辑列落在左边,导致整个表格读起来是反的。修复每个单元格内的文本并不会移动列。
解决方案:为每个表格设置一次 table.table_direction = WD_TABLE_DIRECTION.RTL(会生成 <w:bidiVisual/>,将视觉列顺序镜像为 RTL),并对每个单元格的文本运行按单元格的 bidi 辅助函数。两者都需要;add_rtl_table 会同时完成这两件事。将你的表头/行数据保持自然逻辑顺序,不要自己反转列列表,一旦设置了 bidiVisual,那会造成双重反转。在 Word 中验证,而不是 LibreOffice/Preview(它们对表格的镜像更宽容,会掩盖此问题)。
错误:“希伯来语表格单元格左对齐(表头/文本在左,数字在右)”
原因:在单元格段落上设置了物理的 RIGHT 对齐。OOXML 中的 w:jc 是逻辑的,不是物理的:right 表示“行尾”,而在希伯来语 <w:bidi/> 段落中行尾在左边,因此 RIGHT 对齐将希伯来语推到视觉左侧,而 LTR 数字单元格仍靠右,使表格参差不齐、不匹配。
解决方案:不要对 RTL 表格单元格设置任何显式对齐。为每个单元格段落设置 <w:bidi/>,并保持对齐未设置,RTL 段落默认从其起始边缘(视觉右侧)开始,因此表头、希伯来语文本和数字都右对齐齐平。参见 scripts/docx_rtl.py 中的 set_cell_rtl_text。
错误:“我的 Word 文件中每个希伯来语段落都左对齐”
原因:段落同时携带 <w:bidi/> 和显式右对齐(WD_ALIGN_PARAGRAPH.RIGHT,即 w:jc="right")。jc 是逻辑的,因此在 RTL 段落上“right”是行尾,即视觉左侧。
解决方案:在 RTL 段落上保持对齐未设置;它们从视觉右侧开始。scripts/docx_rtl.py 就是这样做的。
错误:"WeasyPrint: cannot load library 'libgobject-2.0-0'"或 PDF 使用了非希伯来语字体
原因:Pango 未安装或不在库路径上,或者渲染 HTML 时未提供 base_url,导致相对 @font-face URL 被忽略。
解决方案:安装 Pango(步骤 2),并将 base_url 传递给 HTML(...)(步骤 4)。