雙語閱讀(Bilingual Reading)
概述
把一本英文技術 PDF 變成逐段中英對照的離線 HTML 閱讀版:每章一個自包含 HTML(UTF-8、圖片 base64 內嵌、單檔案可離線開啟),左側固定可折疊目錄, 右下角 🌐 懸浮按鈕在「僅英文 / 僅中文 / 中英對照」間循環,翻頁後保持。
觸發與輸入
- 輸入:英文版 PDF(本地路徑或 URL,先下載到本地)。
- 輸出:
index.html+ 前置/結語頁 +chapter-NN.html(一章一檔案), 最終打包 zip 交付。 - 若 PDF 帶書籤(
get_toc()),章節結構以書籤為準並先與用戶確認, 用戶確認「不拆分」後再批量生產。
核心規則(不可違反)
- 原文逐段全譯,不做概要/合併。
- 一章一檔案,不拆章;章內按原書頁順序逐段排版。
- 程式碼區塊(
<pre><code>)保留英文不翻譯;含花括號的程式碼不寫進 f-string。 - 中文段落淺藍底 + 左側 4px 色條,與英文段區分;列表項中文同規格。
- 圖片壓縮後 base64 內嵌;每譯完原書一頁後,單獨加一行頁碼標記
(
page_mark(pdf_page))顯示原 PDF 頁碼。 - 檔案名稱小寫連字號(
chapter-01.html、front-matter.html)。 - 目錄條目按書籤層級(l2/l3)生成;上下章連結串聯,首尾章置灰。
工作流程總覽
① 定頁範圍 → ② 抽文字 → ③ 抽圖片 → ④ 壓圖轉 base64
→ ⑤ 讀原文翻譯 → ⑥ 寫 build_chN.py → ⑦ 補花括號 → ⑧ 執行生成
→ ⑨ 串聯導航 → 驗證 → 交付
先做樣板章(通常 ch1)給用戶驗收樣式,確認後沉澱/複用 book_theme.py
再連續批量生產,中途無需再確認。前置/結語頁與 index.html 最後統一收尾。
步驟詳解
① 定頁範圍
輸入:全書 TOC / 章號。用 PyMuPDF 讀書籤:
import fitz
doc = fitz.open("book.pdf")
toc = doc.get_toc() # [[level, title, page_1based], ...]
按 1-based 頁碼換算為 PyMuPDF 0-based 區間。書籤頁碼與物理頁常有偏移, 以書籤為準;向用戶列出章節劃分並確認後再開工。
② 抽文字
text = "".join(doc[p].get_text("text", sort=True) for p in range(start0, end0+1))
open("chN_raw.txt", "w", encoding="utf-8").write(text)
sort=True 保證閱讀順序,多欄不混淆。每章寫 chN_raw.txt 存原文。
③ 抽圖片
用 scripts/extract_assets.py:
python3 extract_assets.py book.pdf <start_page_1based> <end_page_1based> --out assets
page.get_images(full=True)按 xref 去重 →extract_image(xref)。- jpx(JPEG2000)、RGBA、P 模式統一轉 RGB 再存 JPEG(瀏覽器相容)。
④ 壓圖轉 base64
同上一步一併完成(腳本內建):PIL 開啟;寬 >800px 等比縮到 800(LANCZOS);
JPEG q≈68 重存;base64 寫 assets/figN-M.txt。單圖壓到 30~80KB。
⑤ 讀原文並翻譯
- 分段 Read
chN_raw.txt(每次 500~600 行),逐段翻譯,並記錄圖註對應 (書中的圖,如烏鴉圖示,轉成對應文字「筆記」)。 - 程式碼段跳過翻譯;表格轉 HTML table;清單類內容也逐條翻譯不合併。
⑥ 寫建構腳本
build_chN.py 頂部 from book_theme import P, LI, CODE, INLINE, H, img_b64, page_mark, page,
正文寫在 f-string body 裡。f-string 內 P()/LI() 必須寫成 {P(...)} 才會求值;
程式碼區塊抽成普通字串變數 CODE_X = '''...''' 再用 + CODE_X 拼接。
完整範本見 scripts/book_theme.py 檔案頭 docstring。
⑦ 後處理補花括號
python3 scripts/fix_braces.py build_chN.py
遍歷行:以 P('/LI(' 開頭的行首補 {,向後找第一個以 ) 結尾的行尾補 }。
不處理 img_b64(/page( 呼叫行,避免誤把 } 加到末尾 page() 行。
⑧ 執行生成
python3 build_chN.py # 腳本列印檔案名稱與 KB 數即成功
⑨ 串聯導航
prev/next 按章號填(ch1 prev=front-matter.html,末章 next=None), 首尾章用 disabled 佔位(page() 內已處理)。
收尾
- front-matter.html、closing.html(含/不含推薦書目,先與用戶約定)、
index.html總入口(連結全部章節)。 - 用
python3 -m zipfile -c bilingual_reading.zip *.html打包,交付 zip。
分支與異常處理
| 觸發條件 | 處理方式 |
|---|---|
| 圖為 jpx / RGBA / P 模式 | extract_assets.py 統一 convert 為 RGB 再存 JPEG |
| f-string 裡含程式碼區塊花括號(JSON dict) | 不寫在 f-string 裡;抽成 CODE_X = '''...''' 再 + CODE_X 拼接 |
{<P( 誤寫 | sed 's/{<P(/{P(/g' 修正 |
批量補 } 誤加到末尾 page() 行 | fix_braces.py 已避免;仍出現則手動刪除該行尾多餘的 } |
| 用戶要求「先看效果再繼續」 | 只做樣板章,暫停等回饋 |
| 用戶要求「程式碼不翻譯」 | 所有 <pre><code> 保留英文原文(預設即如此) |
| 更多排查項 | 見 references/troubleshooting.md |
資源索引
scripts/book_theme.py— 核心共享模組:CSS/JS/頁面骨架 + P、LI、CODE、 INLINE、H、img_b64、page_mark、page 函式。改樣式只改這裡。scripts/extract_assets.py— 步驟 ③④:抽圖、壓縮、轉 base64 寫 assets/。scripts/fix_braces.py— 步驟 ⑦:批次補 f-string 花括號。references/style-guide.md— 樣式與互動規範細節(配色、佈局、元件、驗收對照)。references/troubleshooting.md— 問題排查表與可複用經驗。
驗收清單
- 樣板章樣式經用戶確認(中文淺藍底、列表項中文同規格、頁碼標記存在)
- 原文逐段全譯、程式碼區塊未翻譯、圖片 base64 內嵌可離線開啟
- 每章 HTML 可獨立開啟,目錄可折疊,錨點跳轉正常
- 🌐 按鈕三態循環,翻頁後保持(localStorage)
- 上下章連結串聯正確,首尾章按鈕置灰
- 全部檔案 UTF-8、檔案名稱小寫連字號,zip 打包交付