# Zotero PDF2ZH - 常见问题与排查指南

本指南旨在帮助您解决在使用 Zotero PDF2ZH 插件时可能遇到的常见问题。

**不要在置顶 Issue 下提问**：请为每个新问题单独开一个 Issue。本issue下不回答问题。

## ⚠️ 提问前必读

在提交问题之前，请务必遵循以下步骤：

1. **更新至最新版本**：确保您的 Zotero PDF2ZH 插件和相关脚本已更新到 **v2.4.3** 或更高版本。

2. **查阅文档与现有问题**：
 - 仔细阅读本仓库的 [安装指南](https://github.com/guaguastandup/zotero-pdf2zh)。
 - 在 [Issue 区](https://github.com/guaguastandup/zotero-pdf2zh/issues%3Fq%3Dis%3Aissue) 搜索，包括已关闭的 Issue，看是否有类似问题。

3. **善用 AI 工具**：对于“虚拟环境问题、xxx下载/安装失败、本地权限问题、端口开启权限、不熟悉 Python”等基础问题，请优先使用 AI 工具寻求解决方案。

4. **提供完整错误截图**：提问时，请务必上传 **Zotero 界面弹出的错误窗口** 和 **执行 `server.py` 文件的终端报错截图**。未能提供截图的问题将直接关闭且不予回复，感谢理解💗

5. **PDF2zh 依赖包版本检查**:
    - Python 版本: `3.10 <= python <= 3.12`
    - PDF2zh 版本: `pdf2zh >= 1.9.6`
    - pdfminer.six 版本: `pdfminer.six == 20250416`

6. **完成测试**: 准备一个 PDF 文件 (例如 `xxx.pdf`)，在终端运行 `pdf2zh xxx.pdf --service bing`，等待翻译完成。

7. **检查配置文件格式**：json文件的格式要求比较严格。
    - 不允许注释。
    - 逗号必须正确。
    - Windows 路径中的 `\` 符号请改为 `\\`。
    - JSON 文件**不能为空**，即使不配置也需填入 `{}` 或 README 中的模板内容。

---

## 常见错误汇总

### 【PDF2ZH 安装/翻译效果】问题
- **翻译效果不佳/内容漏翻**：这些问题**不属于本仓库开发范围**。请前往 [PDF2zh 仓库 Issue 区](https://github.com/Byaidu/PDFMathTranslate/issues) 提问。
- **[翻译重影]((https://github.com/guaguastandup/zotero-pdf2zh/issues/63#issuecomment-2735247805))**：
 - 原因：`pdf2zh` **1.x 版本不支持 OCR**。
 - 解决方案：使用 `pdf2zh_next` 版本并开启 OCR 模式。

### 【网络连接】问题
- **报错信息**: `NetworkError when attempting to fetch resource` / `403 Forbidden`
- **确认脚本是否正在运行**：检查 `python server.py 8888` 命令是否正在执行。
- **检查插件与脚本端口一致性**：确保 Zotero 插件中 Python Server IP (如 `http://localhost:8888`) 与 `server.py` 脚本的端口一致 (例如 `8888`)。
- **检查本地端口**：确认端口未被防火墙关闭或被其他程序占用。
- **尝试 `curl` 测试**：在新终端中输入 `curl http://localhost:8888/cut`，观察 `server.py` 执行终端是否收到该网络请求。
- 成功访问示意图（左图中server显示收到了网络请求）：![Image](https://github.com/user-attachments/assets/8ae1ac76-5ac3-441d-899d-cbb131d26797)

### 【翻译失败】问题

- **依赖包版本**：参考运行条件一，确保依赖包版本正确。
- **生成翻译 PDF 失败**：如果在翻译过程正常但生成 PDF 失败，请在 Zotero 插件配置中勾选 "**跳过字体子集化**" 选项，然后重试。
- **切换翻译引擎后异常**：这通常是由于您设置的翻译服务配置错误，或服务因请求过多/API Key 错误/URL 错误/用量不足等原因拒绝服务。
- **Bing 服务异常**：很可能是请求过多导致 Bing 服务拒绝。请调小进程数，并等待一段时间后再尝试。

### 【Value Error】问题

- 遇到此类错误时，请在 Zotero 插件配置选项中开启 "**跳过字体子集化**"。
- **注意**：跳过字体子集化会使生成的 PDF 文件变大，使用后建议关闭此选项。

<img width="678" height="312" alt="Image" src="https://github.com/user-attachments/assets/5f00dab5-99f1-473d-bef8-0792cfde72d4" />

### 【下载失败】问题
- `pdf2zh` 需要从 `huggingface.co` 下载 ONNX 模型。如果无法连接，请设置 Hugging Face 国内镜像。
- **参考链接**：https://zhuanlan.zhihu.com/p/684178533 (请使用其中的“设置环境变量”方法)。

### 【找不到文件/虚拟环境】问题

- **报错信息**: `WinError: 找不到文件`
- **检查运行条件一**：确保依赖包版本正确，并且您可以在命令行中运行 `pdf2zh xxx.pdf --service bing` 完成翻译。
- **检查翻译临时路径**：默认路径为 `./translated/` (与 `server.py` 同级目录)。如果未创建，请手动创建。

### 【双栏对照模式显示 PDF 不全】
- **PDF 为单栏文件**：翻译选项请选择 "**双栏对照（单栏）**"。
- **PDF 为双栏文件**：
    - 若希望左侧英文、右侧中文 (两列形式)，请选择 "**双栏对照（双栏）**"。
    - 若希望左侧双栏英文、右侧双栏中文 (四列形式)，请选择 "**双栏对照（单栏）**"。

- **PDF 显示不全 (切割两侧留白导致)**：本插件默认会切割两侧留白。如果切割后显示不全，请将 `server.py` 中的 `split_pdf` 函数替换为以下代码：

```python
# 工具函数, 用于切割双栏pdf文件
def split_pdf(self, input_pdf, output_pdf, compare=False, babeldoc=False):
    writer = PdfWriter()
    if ('dual' in input_pdf or compare == True) and babeldoc == False:
        readers = [PdfReader(input_pdf) for _ in range(4)]
        for i in range(0, len(readers[0].pages), 2):
            original_media_box = readers[0].pages[i].mediabox
            width = original_media_box.width
            height = original_media_box.height
            left_page_1 = readers[0].pages[i]
            offset = 0
            ratio = 1
            for box in ['mediabox', 'cropbox', 'bleedbox', 'trimbox', 'artbox']:
                setattr(left_page_1, box, RectangleObject((offset, 0, width/2+offset/ratio, height)))
            left_page_2 = readers[1].pages[i+1]
            for box in ['mediabox', 'cropbox', 'bleedbox', 'trimbox', 'artbox']:
                setattr(left_page_2, box, RectangleObject((offset, 0, width/2+offset/ratio, height)))
            right_page_1 = readers[2].pages[i]
            for box in ['mediabox', 'cropbox', 'bleedbox', 'trimbox', 'artbox']:
                setattr(right_page_1, box, RectangleObject((width/2-offset/ratio, 0, width-offset, height)))
            right_page_2 = readers[3].pages[i+1]
            for box in ['mediabox', 'cropbox', 'bleedbox', 'trimbox', 'artbox']:
                setattr(right_page_2, box, RectangleObject((width/2-offset/ratio, 0, width-offset, height)))
            if compare == True:
                blank_page_1 = writer.add_blank_page(width, height)
                blank_page_1.merge_transformed_page(left_page_1, (1, 0, 0, 1, 0, 0))
                blank_page_1.merge_transformed_page(left_page_2, (1, 0, 0, 1, width / 2, 0))
                blank_page_2 = writer.add_blank_page(width, height)
                blank_page_2.merge_transformed_page(right_page_1, (1, 0, 0, 1, -width / 2, 0))
                blank_page_2.merge_transformed_page(right_page_2, (1, 0, 0, 1, 0, 0))
            else:
                writer.add_page(left_page_1)
                writer.add_page(left_page_2)
                writer.add_page(right_page_1)
                writer.add_page(right_page_2)
    else: 
        readers = [PdfReader(input_pdf) for _ in range(2)]
        for i in range(len(readers[0].pages)):
            page = readers[0].pages[i]
            original_media_box = page.mediabox
            width = original_media_box.width
            height = original_media_box.height
            w_offset = 0
            w_ratio = 1
            h_offset = 0
            left_page = readers[0].pages[i]
            left_page.mediabox = RectangleObject((w_offset, h_offset, width/2+w_offset/w_ratio, height-h_offset))
            right_page = readers[1].pages[i]
            right_page.mediabox = RectangleObject((width/2-w_offset/w_ratio, h_offset, width-w_offset, height-h_offset))
            writer.add_page(left_page)
            writer.add_page(right_page)
    with open(output_pdf, "wb") as output_file:
        writer.write(output_file)
```