
reportlab 默认字体不支持拉丁-2 编码字符(如斯洛文尼亚语中的 č、š、ž),需注册并使用包含 latin-2 字符集的 truetype 字体(如 dejavu sans 或 liberation sans),才能确保 pdf 中特殊字符正常渲染。
reportlab 默认字体不支持拉丁-2 编码字符(如斯洛文尼亚语中的 č、š、ž),需注册并使用包含 latin-2 字符集的 truetype 字体(如 dejavu sans 或 liberation sans),才能确保 pdf 中特殊字符正常渲染。
ReportLab 内置的标准字体(如 Helvetica、Times-Roman)基于 Adobe 的基本 14 字体集,仅支持 ISO-8859-1(Latin-1)编码,不包含拉丁-2(ISO-8859-2)所需的扩展字符,例如 č(U+010D)、š(U+0161)、ž(U+017E)。这就是为什么部分字符(如 š、ž)偶尔看似可显示——实则是某些 PDF 查看器对缺失字形做了容错回退(如用相近形近字替代),而 č 等更偏门的字符则直接渲染为黑方块(□)或占位符。
✅ 正确做法是:注册一个支持 ISO-8859-2 / Unicode 的开源 TTF 字体,并显式设置为 PDF 文本字体。推荐使用 DejaVu Sans 或 Liberation Sans,二者均完整覆盖 Latin-2 字符且免费可嵌入。
以下是完整可运行示例:
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import os
# 1. 注册支持 Latin-2 的字体(以 DejaVuSans.ttf 为例)
font_path = "DejaVuSans.ttf" # 确保该文件存在于工作目录或指定路径
if not os.path.exists(font_path):
raise FileNotFoundError(f"字体文件未找到: {font_path}")
pdfmetrics.registerFont(TTFont("DejaVu", font_path))
# 2. 创建 PDF 并使用注册字体
pdf = canvas.Canvas("invoice_sl.pdf")
textobject = pdf.beginText(50, 750)
# 3. 显式设置字体(字号可任意,但必须指定已注册名称)
pdf.setFont("DejaVu", 12)
# 4. 写入含拉丁-2 字符的斯洛文尼亚语文本(Unicode 原生字符串)
receipt_lines = [
"Račun je bil uspešno natisnjen.",
"Naslov: Trg OF 1, 1000 Ljubljana",
"Artikel: Kava črna, štruklji z jabolki, žlica za sladico"
]
for line in receipt_lines:
textobject.textLine(line.rstrip())
pdf.drawText(textobject)
pdf.save()
print("✅ PDF uspešno ustvarjen z vsemi latin-2 znaki.")
⚠️ 注意事项:
-
不要尝试用
encode('iso-8859-2')手动编码字符串:ReportLab 的TTFont完全基于 Unicode,应始终传入 Python 原生str(UTF-8 源码中直接写č即可); -
字体文件必须可访问且含 Latin-2 字形:可用
fonttools验证:ttx -t cmap DejaVuSans.ttf | grep -i "010d\|0161\|017e"(检查是否包含 U+010D 等码位); -
避免使用
pdf.drawString()直接写多行含换行符文本:textLine()+beginText()是更可控的方式; - 若部署到服务器,请确保字体文件随程序分发,或使用
reportlab.lib.fonts.addMapping()实现字体别名兼容。
总结:ReportLab 对非 Latin-1 字符的支持完全依赖外部字体资源。只要选用覆盖 ISO-8859-2 的高质量 OpenType/TTF 字体、正确注册并调用,即可稳定输出斯洛文尼亚语、捷克语、波兰语等中欧语言的 PDF 发票与文档——无需修改编码逻辑,只需一次字体配置,一劳永逸。










