内容中心 › 排版
一份 15 页的英文论文译完,页面上有几处空白,还有一个人名少了个字母。直觉都指向“字体缺字”。
我换了个笨办法:把译文里的每个字符拆出来,回到它所在的字体表里查一遍有没有这个字形。结果是 17,277 个字符,找不到字形的:0 个。
三步,全程只用 PyMuPDF,可复现:
1. page.get_text('dict') 拿到全部 span —— 译文 15 页共 2,515 个 span、17,277 个字符(原文同口径 3,480 个 span、38,450 个字符);
2. 每个 span 带字体名,按名字找到页面字体对象,doc.extract_font(xref) 把字体缓冲取出来;
3. fitz.Font(fontbuffer=buf).has_glyph(ord(ch)) 逐字符问一句:这个字体里到底有没有这个字形。
口径要说清:这个检查只回答“字体里有没有这个字形”,不回答“画出来好不好看”。字距、基线、错行是另一套指标,别混着用。
| 现象 | 实测数量 | 判定 |
|---|---|---|
| 字体表里找不到字形(真豆腐块) | 0 | 不是字体缺字 |
| U+0000 空字符 | 146 | 字符本身是空的 |
| 拉丁扩展字符整条消失 | 3(同一个字母 Ł) | 真丢字,但丢得干净 |
| 全角拉丁字母 / 全角数字 | 0 / 0 | 没有 |
| 全角标点 | 372(逗号 295、冒号 32、括号 42、分号 2、问号 1) | 正常中文标点 |
一眼能看出的结论:你肉眼看到的方框,几乎都不是“字体里没这个字”。这份译文里一个都没有。方框更常见的来源是阅读器找不到替代字体、或者字体名被替换后回落到了错误的字体族。
不是随机撒在页面上的。逐页分布是 p1 十五个、p2 十一个、p11 二十个、p12 十六个,最后两页各一个(那两页本来就是整页图)。
更关键的是位置:143 个在行尾,只有 3 个在行中间;它们前一个字符里,92 个是句号「。」。
这说明它不是渲染失败,而是被写进 PDF 的字符本身就是 U+0000。按句切分送翻、句末补一个分隔标记、回写时把这个标记当成正文写进了文字层——行尾、紧跟句号,两个特征都对得上。
原文第 1 页作者区有 Łukasz Kaiser,译文变成 ukasz Kaiser;第 11、12 页参考文献 [16][17] 同样的名字,同样只剩 ukasz。
原文里 U+00C0–U+024F 这段拉丁扩展字符一共出现 15 次,译文剩下 12 次,缺的恰好全是这个带斜杠的 Ł,三处全丢。
它丢得很“干净”:没有留方框,没有留空格,位置直接被后面的字母顶上来。所以靠检查方框的流程永远发现不了它。
字体种数从 34 涨到 36,不是乱码变多。 多出来的一个是中文主字体(Type0,Source Han Serif CN,Identity-H 编码),另一个是承载拉丁正文的那套;其余 34 个都带 ABCDEF+ 子集前缀,属于正常的字体子集化。
字符总数从 38,450 掉到 17,277 也别当丢字。 字符比 0.451,中文汉字数大约是原文拉丁字符数的一半,属于中英互译的正常区间。拿总字符数做丢字判据,一定会误报。
| 你看到的 | 先查什么 | 结论怎么下 |
|---|---|---|
| 方框 / 豆腐块 | 字体表里有没有这个字形 | 缺字形 0 个 → 是阅读器字体替换,不用重译 |
| 莫名空白 | 字符是不是 U+0000 或异常空格 | 集中在行尾 → 切分符被写进正文,清掉即可 |
| 少字但没痕迹 | 拉丁扩展字符集(U+00C0–U+024F)逐个点名 | 这类最该复查,因为它在页面上不留任何证据 |
第三条是这份样本里唯一需要返工的地方:三个字符、两个页面、一个人名。
下次拿到译文 PDF,别先截图圈方框。把这三个判据各跑一遍,十分钟能分清“要重译”和“不用管”,比盯着页面猜准得多。