Lecture bilingue (Bilingual Reading)
Aperçu
Transformez un PDF technique anglais en une version HTML bilingue (anglais-chinois) par paragraphe : chaque chapitre est un fichier HTML autonome (UTF-8, images en base64, ouvrable hors ligne), avec une table des matières repliable à gauche et un bouton flottant 🌐 en bas à droite pour basculer entre « Anglais uniquement / Chinois uniquement / Anglais-chinois », même après changement de page.
Déclenchement et saisie
- Entrée : PDF anglais (chemin local ou URL, téléchargé au préalable).
- Sortie :
index.html+ pages préliminaires/clôture +chapter-NN.html(un fichier par chapitre), le tout livré dans une archive zip. - Si le PDF contient des signets (
get_toc()), la structure des chapitres est basée sur les signets et doit être confirmée avec l'utilisateur avant la production en série. Si l'utilisateur confirme « Ne pas diviser », la production peut commencer.
Règles fondamentales (à ne pas enfreindre)
- Traduire intégralement le texte original paragraphe par paragraphe, sans résumé ni fusion.
- Un fichier par chapitre, sans diviser un chapitre ; organiser les paragraphes dans l'ordre des pages originales du livre.
- Les blocs de code (
<pre><code>) restent en anglais, non traduits ; le code contenant des accolades ne doit pas être inclus dans les f-strings. - Les paragraphes chinois ont un fond bleu clair avec une barre latérale gauche de 4px, pour les distinguer des paragraphes anglais ; les éléments de liste en chinois suivent la même règle.
- Les images sont compressées puis intégrées en base64 ; après chaque page originale traduite, ajouter une ligne de marquage de page (
page_mark(pdf_page)) affichant le numéro de page original du PDF. - Les noms de fichiers sont en minuscules avec des tirets (
chapter-01.html,front-matter.html). - Les entrées de la table des matières sont générées selon la hiérarchie des signets (niveaux l2/l3) ; les liens vers les chapitres précédent/suivant sont chaînés, et les chapitres de début/fin sont grisés.
Aperçu du flux de travail
① Définir la plage de pages → ② Extraire le texte → ③ Extraire les images → ④ Compresser et convertir en base64
→ ⑤ Lire le texte original et le traduire → ⑥ Écrire build_chN.py → ⑦ Corriger les accolades → ⑧ Exécuter la génération
→ ⁹ Chaîner la navigation → Vérifier → Livrer
Commencez par un chapitre modèle (généralement ch1) pour validation par l'utilisateur. Une fois approuvé, réutilisez book_theme.py pour la production en série sans autre confirmation. Les pages préliminaires, de clôture et index.html sont finalisées à la fin.
Étapes détaillées
① Définir la plage de pages
Entrée : table des matières du livre / numéros de chapitre. Utilisez PyMuPDF pour lire les signets :
import fitz
doc = fitz.open("book.pdf")
toc = doc.get_toc() # [[level, title, page_1based], ...]
Convertissez les numéros de page basés sur 1 en plage 0-based pour PyMuPDF. Les numéros de page des signets peuvent être décalés par rapport aux pages physiques ; basez-vous sur les signets ; listez la division des chapitres à l'utilisateur et confirmez avant de commencer.
② Extraire le texte
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 garantit l'ordre de lecture, sans confusion pour les colonnes multiples. Écrivez le texte original dans chN_raw.txt.
③ Extraire les images
Utilisez scripts/extract_assets.py :
python3 extract_assets.py book.pdf <start_page_1based> <end_page_1based> --out assets
page.get_images(full=True)déduplique par xref →extract_image(xref).- Les formats jpx (JPEG2000), RGBA, P sont convertis en RGB puis en JPEG (compatibilité navigateur).
④ Compresser et convertir en base64
Effectué dans la même étape (intégré au script) : PIL ouvre ; si largeur > 800px, redimensionner proportionnellement à 800 (LANCZOS) ; JPEG q≈68 ; base64 écrit dans assets/figN-M.txt. Chaque image compressée fait 30~80 Ko.
⑤ Lire le texte original et le traduire
- Lisez
chN_raw.txtpar sections (500~600 lignes chacune), traduisez paragraphe par paragraphe, et enregistrez les légendes d'images correspondantes. - Ignorez les blocs de code ; convertissez les tableaux en HTML
<table>; traduisez les listes élément par élément sans fusion.
⑥ Écrire le script de construction
build_chN.py commence par from book_theme import P, LI, CODE, INLINE, H, img_b64, page_mark, page, et le corps est écrit dans une f-string body. Dans la f-string, P()/LI() doivent être écrits {P(...)} pour être évalués ; les blocs de code sont extraits en tant que variables de chaîne normales CODE_X = '''...''' puis concaténés avec + CODE_X. Le modèle complet se trouve dans le docstring d'en-tête du fichier scripts/book_theme.py.
⑦ Corriger les accolades (post-traitement)
python3 scripts/fix_braces.py build_chN.py
Parcourt les lignes : pour les lignes commençant par P('/LI(', ajoute { au début de la ligne et } à la fin de la première ligne suivante se terminant par ).
Ne traite pas les lignes contenant img_b64(/page( pour éviter d'ajouter } à la fin des lignes page().
⑧ Exécuter la génération
python3 build_chN.py # Le script affiche le nom du fichier et sa taille en Ko en cas de succès
⁹ Chaîner la navigation
Les liens prev/next sont renseignés selon le numéro de chapitre (ch1 prev=front-matter.html, dernier chapitre next=None), les chapitres de début/fin utilisent un placeholder désactivé (géré dans page()).
Finalisation
- front-matter.html, closing.html (avec/sans bibliographie recommandée, à convenir avec l'utilisateur à l'avance),
index.htmlcomme entrée principale (liens vers tous les chapitres). - Archivez le tout avec
python3 -m zipfile -c bilingual_reading.zip *.htmlet livrez le zip.
Branches et gestion des exceptions
| Condition de déclenchement | Traitement |
|---|---|
| L'image est au format jpx / RGBA / P | extract_assets.py convertit automatiquement en RGB, puis en JPEG |
| Code contenant des accolades dans une f-string (dict JSON) | Ne pas l'écrire dans la f-string ; extraire en CODE_X = '''...''' puis concaténer avec + CODE_X |
{<P( mal écrit | Corriger avec sed 's/{<P(/{P(/g' |
} ajouté par erreur à la fin d'une ligne page() | fix_braces.py l'évite ; si cela arrive, supprimer manuellement le } en trop en fin de ligne |
| L'utilisateur demande « voir le résultat avant de continuer » | Ne produire que le chapitre modèle, puis attendre un retour |
| L'utilisateur demande « ne pas traduire le code » | Tous les <pre><code> restent en anglais (c'est le comportement par défaut) |
| Plus d'éléments de diagnostic | Voir references/troubleshooting.md |
Index des ressources
scripts/book_theme.py— Module partagé principal : squelette CSS/JS/page + fonctions P, LI, CODE, INLINE, H, img_b64, page_mark, page. Modifiez le style ici uniquement.scripts/extract_assets.py— Étapes ③④ : extraire les images, les compresser, les convertir en base64 et les écrire dans assets/.scripts/fix_braces.py— Étape ⑦ : corriger les accolades dans les f-strings par lots.references/style-guide.md— Détails des spécifications de style et d'interaction (couleurs, mise en page, composants, validation comparative).references/troubleshooting.md— Tableau de diagnostic et expériences réutilisables.
Liste de validation
- Le style du chapitre modèle est validé par l'utilisateur (fond bleu clair pour le chinois, éléments de liste en chinois suivant la même règle, marquage de page présent)
- Texte original intégralement traduit paragraphe par paragraphe, blocs de code non traduits, images intégrées en base64 pour une ouverture hors ligne
- Chaque HTML de chapitre s'ouvre indépendamment, la table des matières est repliable, les ancres fonctionnent
- Le bouton 🌐 cyclique à trois états persiste après changement de page (localStorage)
- Les liens prev/next des chapitres sont correctement chaînés, les boutons du premier et du dernier chapitre sont grisés
- Tous les fichiers en UTF-8, noms de fichiers en minuscules avec tirets, livrés dans une archive zip