Bilingual Reading
Overview
Turn an English technical PDF into an offline HTML reading edition with paragraph-by-paragraph Chinese-English comparison: each chapter is a self-contained HTML file (UTF-8, images base64-embedded, single files that open offline), with a fixed collapsible left-side table of contents, and a floating 🌐 button in the bottom-right corner that cycles through 'English only / Chinese only / Chinese-English comparison', with the selection persisting across page turns.
Trigger & Input
- Input: English PDF (local path or URL; download locally first).
- Output:
index.html+ front-matter/closing pages +chapter-NN.html(one file per chapter), finally packaged into a zip for delivery. - If the PDF has bookmarks (
get_toc()), the chapter structure should follow the bookmarks; first confirm with the user. If the user confirms 'no splitting', then batch produce.
Core Rules (Not to Be Violated)
- Fully translate every paragraph of the original text; do not summarize or merge.
- One file per chapter; do not split chapters within; arrange paragraphs in the original page order.
- Code blocks (
<pre><code>) keep English and are not translated; code containing curly braces is not written inside f-strings. - Chinese paragraphs have a light blue background + a 4px left color bar to distinguish them from English paragraphs; list items in Chinese follow the same specifications.
- Images are compressed and base64-embedded; after every completed original page, add a separate line as a page number marker (
page_mark(pdf_page)) showing the original PDF page number. - File names are lowercase with hyphens (
chapter-01.html,front-matter.html). - Table of contents entries are generated according to bookmark levels (l2/l3); previous/next chapter links are chained; the first and last chapter links are grayed out.
Workflow Overview
① Determine page range → ② Extract text → ③ Extract images → ④ Compress & convert to base64
→ ⑤ Read original text & translate → ⑥ Write build_chN.py → ⑦ Fix curly braces → ⑧ Run generation
→ ⑨ Chain navigation → Verify → Deliver
First create a sample chapter (usually ch1) for the user to review the style; after confirmation, solidify/reuse book_theme.py and then batch produce continuously without further confirmation. Finalize front-matter/closing pages and index.html at the very end.
Detailed Steps
① Determine Page Range
Input: Full TOC / chapter numbers. Use PyMuPDF to read bookmarks:
import fitz
doc = fitz.open("book.pdf")
toc = doc.get_toc() # [[level, title, page_1based], ...]
Convert 1-based page numbers to PyMuPDF 0-based ranges. Bookmark page numbers often have an offset from physical pages; rely on bookmarks; list the chapter divisions to the user and confirm before starting work.
② Extract Text
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 ensures reading order and avoids confusion in multi-column layouts. Save the original text as chN_raw.txt for each chapter.
③ Extract Images
Use scripts/extract_assets.py:
python3 extract_assets.py book.pdf <start_page_1based> <end_page_1based> --out assets
page.get_images(full=True)deduplicates by xref →extract_image(xref).- jpx (JPEG2000), RGBA, and P modes are uniformly converted to RGB and then saved as JPEG (for browser compatibility).
④ Compress & Convert to base64
Done together with the previous step (built into the script): PIL opens; if width >800px, proportionally resize to 800 (LANCZOS); re-save as JPEG with q≈68; write base64 to assets/figN-M.txt. Each image compressed to 30~80KB.
⑤ Read Original Text & Translate
- Read
chN_raw.txtin segments (500~600 lines each), translate paragraph by paragraph, and record corresponding image captions (e.g., a crow diagram in the book should be converted to the textual note "笔记"). - Skip translation for code segments; convert tables to HTML
<table>; translate list-type content line by line without merging.
⑥ Write Build Script
At the top of build_chN.py, include from book_theme import P, LI, CODE, INLINE, H, img_b64, page_mark, page; the main body is written in the f-string body. Inside the f-string, P()/LI() must be written as {P(...)} to be evaluated; extract code blocks as plain string variables CODE_X = '''...''' and concatenate using + CODE_X. See the complete template in the docstring at the top of scripts/book_theme.py.
⑦ Post-process to Fix Curly Braces
python3 scripts/fix_braces.py build_chN.py
Iterate through lines: for lines starting with P('/LI(', prepend { at the beginning; find the next line ending with ) and append } at the end. Do not process img_b64(/page( invocation lines to avoid mistakenly adding } after the final page() line.
⑧ Run Generation
python3 build_chN.py # The script prints the filename and size in KB on success
⑨ Chain Navigation
Fill in prev/next links by chapter number (ch1 prev=front-matter.html, last chapter next=None); use disabled placeholders for the first and last chapters (handled within page()).
Final Steps
- front-matter.html, closing.html (with or without recommended reading list; agree with the user first),
index.htmlas the main entry (linking all chapters). - Package using
python3 -m zipfile -c bilingual_reading.zip *.htmland deliver the zip.
Branches & Exception Handling
| Trigger Condition | Handling Method |
|---|---|
| Image is jpx / RGBA / P mode | extract_assets.py uniformly converts to RGB before saving as JPEG |
| Code block contains curly braces (JSON dict) inside f-string | Do not write inside the f-string; extract as CODE_X = '''...''' and concatenate with + CODE_X |
{<P( wrongly written | Fix with sed 's/{<P(/{P(/g' |
Batch-adding } mistakenly adds to the final page() line | fix_braces.py already avoids this; if it still occurs, manually remove the extra } at the end of that line |
| User asks to 'see the effect before continuing' | Only create the sample chapter; pause and wait for feedback |
| User asks not to translate code | All <pre><code> keep the original English (default behavior) |
| More troubleshooting items | See references/troubleshooting.md |
Resource Index
scripts/book_theme.py— Core shared module: CSS/JS/page skeleton + P, LI, CODE, INLINE, H, img_b64, page_mark, page functions. Modify styles only here.scripts/extract_assets.py— Steps ③④: Extract images, compress, convert to base64, write to assets/.scripts/fix_braces.py— Step ⑦: Batch fix f-string curly braces.references/style-guide.md— Style and interaction specification details (color scheme, layout, components, acceptance comparison).references/troubleshooting.md— Problem troubleshooting table and reusable experience.
Acceptance Checklist
- Sample chapter style confirmed by user (Chinese paragraphs with light blue background, list items in Chinese with same specification, page number markers present)
- Original text fully translated paragraph by paragraph, code blocks not translated, images base64-embedded and openable offline
- Each chapter HTML opens independently, table of contents is collapsible, anchor navigation works correctly
- 🌐 button cycles through three states, persists across page turns (localStorage)
- Previous/next chapter links are correctly chained, first and last chapter buttons are grayed out
- All files UTF-8, file names lowercase with hyphens, packaged as zip for delivery