ChinesePod Script Traduzione PDF
Tutti gli script con pulsanti “Copia” – Novembre 2025
1. Panoramica Progetto
Sistema per tradurre PDF didattici ChinesePod in italiano usando Claude API (Haiku).
1.1 Script principali
- chinesepod_traduci_v3.py – versione base
- chinesepod_traduci_v6_test_haiku_2.py – versione con Claude Haiku (367 righe)
- chinesepod_traduci_v8.py – versione con file regole esterno
1.2 Output generato
- Frase cinese – testo originale
- Pinyin – trascrizione fonetica con toni
- Tabella con due traduzioni:
- LETTERALE – morfema per morfema
- NATURALE – italiano scorrevole ma vicino alla letterale
2. Script v3 – Versione Base
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
chinesepod_traduci_v3.py
Traduce PDF ChinesePod in italiano usando Claude API
Layout: cinese + pinyin + traduzioni LETTERALE/NATURALE
"""
import os
import sys
import json
import re
from pathlib import Path
import fitz # PyMuPDF
import requests
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.lib.units import cm
import time
from datetime import datetime
# ===== CONFIGURAZIONE =====
API_KEY = "YOUR_CLAUDE_API_KEY" # Inserisci la tua chiave
API_URL = "https://api.anthropic.com/v1/messages"
MODEL = "claude-3-haiku-20240307"
INPUT_DIR = Path("scaricatiABC")
OUTPUT_DIR = Path("scaricatiAB")
LOG_FILE = Path("traduzione_log.txt")
# ===== FUNZIONI =====
def chiama_claude(prompt, max_tokens=4000):
"""Chiama l'API Claude con il prompt fornito."""
headers = {
"x-api-key": API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json"
}
data = {
"model": MODEL,
"max_tokens": max_tokens,
"messages": [{"role": "user", "content": prompt}]
}
try:
response = requests.post(API_URL, headers=headers, json=data, timeout=120)
response.raise_for_status()
return response.json()["content"][0]["text"]
except Exception as e:
print(f"❌ Errore API: {e}")
return None
def estrai_testo_da_pdf(pdf_path):
"""Estrae il testo da un PDF (solo cinese + inglese)."""
doc = fitz.open(pdf_path)
testo_completo = ""
for pagina in doc:
testo_completo += pagina.get_text()
doc.close()
return testo_completo
def traduci_testo(testo_cinese):
"""Traduce il testo cinese in italiano."""
prompt = f"""Sei un traduttore esperto di cinese.
Traduci il seguente testo cinese in italiano in due versioni:
TEXT:
{testo_cinese}
REGOLE:
1. LETTERALE: traduci ogni morfema, fedele alla struttura cinese
2. NATURALE: italiano scorrevole ma vicino alla letterale
Rispondi SOLO con JSON nel formato:
{{
"originale": "...",
"letterale": "...",
"naturale": "..."
}}"""
risposta = chiama_claude(prompt)
if risposta:
try:
# Estrai il JSON dalla risposta
match = re.search(r'\{.*\}', risposta, re.DOTALL)
if match:
return json.loads(match.group())
except:
pass
return None
def crea_pdf(dati, output_path, titolo="ChinesePod"):
"""Crea un PDF con il layout delle traduzioni."""
doc = SimpleDocTemplate(str(output_path), pagesize=A4)
styles = getSampleStyleSheet()
# Stili personalizzati
style_titolo = ParagraphStyle('Titolo', parent=styles['Heading1'], fontSize=16, spaceAfter=12)
style_cinese = ParagraphStyle('Cinese', parent=styles['Normal'], fontSize=14, fontName='STSong-Light')
style_pinyin = ParagraphStyle('Pinyin', parent=styles['Normal'], fontSize=12, textColor=colors.grey)
style_traduzione = ParagraphStyle('Traduzione', parent=styles['Normal'], fontSize=12, spaceAfter=6)
story = []
# Titolo
story.append(Paragraph(titolo, style_titolo))
story.append(Spacer(1, 12))
# Per ogni voce
for voce in dati:
if not voce.get('originale'):
continue
# Cinese
story.append(Paragraph(f"{voce['originale']}", style_cinese))
if voce.get('pinyin'):
story.append(Paragraph(f"{voce['pinyin']}", style_pinyin))
# Traduzioni in tabella
data_table = [
["LETTERALE", voce.get('letterale', '')],
["NATURALE", voce.get('naturale', '')]
]
t = Table(data_table, colWidths=[3*cm, 12*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('PADDING', (0, 0), (-1, -1), 6),
('FONTSIZE', (0, 0), (-1, -1), 10),
]))
story.append(t)
story.append(Spacer(1, 12))
doc.build(story)
print(f"✅ PDF creato: {output_path}")
def main():
"""Funzione principale."""
# Cerca i PDF nella cartella input
pdf_files = list(INPUT_DIR.glob("*.pdf"))
if not pdf_files:
print("❌ Nessun PDF trovato in", INPUT_DIR)
return
for pdf_path in pdf_files:
print(f"📄 Elaborazione: {pdf_path.name}")
# Estrai testo
testo = estrai_testo_da_pdf(pdf_path)
if not testo:
print(f"⚠️ Nessun testo estratto da {pdf_path.name}")
continue
# Traduci
risultato = traduci_testo(testo)
if not risultato:
print(f"⚠️ Traduzione fallita per {pdf_path.name}")
continue
# Salva JSON
json_path = OUTPUT_DIR / pdf_path.name.replace('.pdf', '_dati.json')
with open(json_path, 'w', encoding='utf-8') as f:
json.dump(risultato, f, ensure_ascii=False, indent=2)
# Crea PDF
pdf_output = OUTPUT_DIR / pdf_path.name.replace('.pdf', '_italiano.pdf')
crea_pdf([risultato], pdf_output, titolo=pdf_path.name)
print(f"✅ Completato: {pdf_path.name}")
time.sleep(1) # Rispetta i rate limit
if __name__ == "__main__":
main()
3. Script v6 – Con Haiku (367 righe)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
chinesepod_traduci_v6_test_haiku_2.py
Versione ottimizzata con Claude Haiku
Layout migliorato per frasi lunghe e corte
"""
import os
import sys
import json
import re
from pathlib import Path
import fitz
import requests
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak, KeepTogether
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.enums import TA_CENTER, TA_LEFT
import time
from datetime import datetime
# ===== CONFIGURAZIONE =====
API_KEY = "YOUR_CLAUDE_API_KEY"
API_URL = "https://api.anthropic.com/v1/messages"
MODEL = "claude-3-haiku-20240307"
INPUT_DIR = Path("scaricatiABC")
OUTPUT_DIR = Path("scaricatiAB")
LOG_FILE = Path("traduzione_log_v6.txt")
# ===== FUNZIONI =====
def chiama_claude(prompt, max_tokens=4000, temperatura=0.3):
"""Chiama l'API Claude con il prompt fornito."""
headers = {
"x-api-key": API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json"
}
data = {
"model": MODEL,
"max_tokens": max_tokens,
"temperature": temperatura,
"messages": [{"role": "user", "content": prompt}]
}
try:
response = requests.post(API_URL, headers=headers, json=data, timeout=180)
response.raise_for_status()
return response.json()["content"][0]["text"]
except Exception as e:
print(f"❌ Errore API: {e}")
return None
def estrai_testo_con_pinyin(pdf_path):
"""Estrae il testo cinese con pinyin dal PDF (usando le annotazioni o il testo visibile)."""
doc = fitz.open(pdf_path)
pagine_cinese = []
pagine_pinyin = []
for pagina in doc:
# Estrai il testo normale
testo = pagina.get_text()
# Prova a separare cinese e pinyin (se presenti come annotazioni)
# Questo è un placeholder - la logica reale dipende dal formato del PDF
pagine_cinese.append(testo)
pagine_pinyin.append("") # Da implementare con OCR o annotazioni
doc.close()
return pagine_cinese, pagine_pinyin
def traduce_dialogo(blocchi_cinese, blocchi_pinyin):
"""Traduce un dialogo mantenendo la struttura."""
prompt = f"""Sei un traduttore esperto di cinese.
Traduci il seguente dialogo cinese in italiano.
DIALOGO:
{blocchi_cinese}
PINYIN (dove disponibile):
{blocchi_pinyin}
REGOLE:
- LETTERALE: traduci ogni morfema, fedele alla struttura cinese
- NATURALE: italiano scorrevole ma vicino alla letterale
- Mantieni la struttura del dialogo (chi parla, turni di parola)
Rispondi SOLO con JSON nel formato:
[
{{
"originale": "...",
"pinyin": "...",
"letterale": "...",
"naturale": "..."
}},
...
]"""
risposta = chiama_claude(prompt, max_tokens=8000)
if risposta:
try:
match = re.search(r'\[.*\]', risposta, re.DOTALL)
if match:
return json.loads(match.group())
except:
pass
return None
def crea_pdf_avanzato(dati, output_path, titolo="ChinesePod"):
"""Crea un PDF con layout avanzato (tabella per frasi corte, testo per frasi lunghe)."""
doc = SimpleDocTemplate(str(output_path), pagesize=A4,
leftMargin=1.5*cm, rightMargin=1.5*cm,
topMargin=2*cm, bottomMargin=2*cm)
styles = getSampleStyleSheet()
# Stili personalizzati
style_titolo = ParagraphStyle('Titolo', parent=styles['Heading1'],
fontSize=18, spaceAfter=12, textColor=colors.darkblue)
style_cinese = ParagraphStyle('Cinese', parent=styles['Normal'],
fontSize=14, fontName='STSong-Light', spaceAfter=2)
style_pinyin = ParagraphStyle('Pinyin', parent=styles['Normal'],
fontSize=12, textColor=colors.grey, spaceAfter=6)
style_etichetta = ParagraphStyle('Etichetta', parent=styles['Normal'],
fontSize=11, textColor=colors.darkgrey, alignment=TA_CENTER)
style_letterale = ParagraphStyle('Letterale', parent=styles['Normal'],
fontSize=11, alignment=TA_LEFT, spaceAfter=3)
style_naturale = ParagraphStyle('Naturale', parent=styles['Normal'],
fontSize=11, alignment=TA_LEFT, textColor=colors.darkblue, spaceAfter=8)
story = []
# Titolo
story.append(Paragraph(titolo, style_titolo))
story.append(Spacer(1, 12))
for i, voce in enumerate(dati, 1):
if not voce.get('originale'):
continue
# Numero frase
story.append(Paragraph(f"{i}.", style_cinese))
# Cinese + Pinyin
story.append(Paragraph(f"{voce['originale']}", style_cinese))
if voce.get('pinyin'):
story.append(Paragraph(f"{voce['pinyin']}", style_pinyin))
# Tabella traduzioni
data_table = [
["LETTERALE", voce.get('letterale', '')],
["NATURALE", voce.get('naturale', '')]
]
t = Table(data_table, colWidths=[3*cm, 12*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('PADDING', (0, 0), (-1, -1), 6),
('FONTSIZE', (0, 0), (-1, -1), 10),
('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'),
('LEFTPADDING', (1, 0), (1, -1), 8),
]))
story.append(t)
story.append(Spacer(1, 10))
# Separatore
story.append(Paragraph("
", styles['Normal']))
story.append(Spacer(1, 6))
doc.build(story)
print(f"✅ PDF avanzato creato: {output_path}")
def main():
"""Funzione principale."""
print("🚀 Avvio traduzione ChinesePod v6 (Haiku)")
# Cerca i PDF nella cartella input
pdf_files = list(INPUT_DIR.glob("*.pdf"))
if not pdf_files:
print(f"❌ Nessun PDF trovato in {INPUT_DIR}")
return
for pdf_path in pdf_files:
print(f"📄 Elaborazione: {pdf_path.name}")
# Estrai testo
pagine_cinese, pagine_pinyin = estrai_testo_con_pinyin(pdf_path)
if not pagine_cinese:
print(f"⚠️ Nessun testo estratto da {pdf_path.name}")
continue
# Traduci (prendiamo solo la prima pagina per semplicità)
# In produzione, processa tutte le pagine
risultato = traduce_dialogo(pagine_cinese[0], pagine_pinyin[0] if pagine_pinyin else "")
if not risultato:
print(f"⚠️ Traduzione fallita per {pdf_path.name}")
continue
# Salva JSON
json_path = OUTPUT_DIR / pdf_path.name.replace('.pdf', '_dati.json')
with open(json_path, 'w', encoding='utf-8') as f:
json.dump(risultato, f, ensure_ascii=False, indent=2)
# Crea PDF
pdf_output = OUTPUT_DIR / pdf_path.name.replace('.pdf', '_italiano.pdf')
crea_pdf_avanzato(risultato, pdf_output, titolo=pdf_path.name)
print(f"✅ Completato: {pdf_path.name}")
time.sleep(2) # Rispetta i rate limit
if __name__ == "__main__":
main()
4. Script v8 – Con Regole
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
chinesepod_traduci_v8.py
Versione con prompt regole esterno
Layout migliorato con regole di traduzione letterale
"""
import os
import sys
import json
import re
from pathlib import Path
import fitz
import requests
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.lib.units import cm
import time
# ===== CONFIGURAZIONE =====
API_KEY = "YOUR_CLAUDE_API_KEY"
API_URL = "https://api.anthropic.com/v1/messages"
MODEL = "claude-3-haiku-20240307"
INPUT_DIR = Path("scaricatiABC")
OUTPUT_DIR = Path("scaricatiAB")
PROMPT_REGOLE_FILE = r"C:\Users\User\Desktop\CHINESEPOD_ITALIANO\prompt_regole.txt"
# ===== FUNZIONI =====
def carica_regole():
"""Carica le regole dal file prompt_regole.txt."""
try:
with open(PROMPT_REGOLE_FILE, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
print(f"⚠️ File regole non trovato: {PROMPT_REGOLE_FILE}")
return ""
def chiama_claude(prompt, max_tokens=4000):
headers = {
"x-api-key": API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json"
}
data = {
"model": MODEL,
"max_tokens": max_tokens,
"messages": [{"role": "user", "content": prompt}]
}
try:
response = requests.post(API_URL, headers=headers, json=data, timeout=180)
response.raise_for_status()
return response.json()["content"][0]["text"]
except Exception as e:
print(f"❌ Errore API: {e}")
return None
def estrai_testo_da_pdf(pdf_path):
doc = fitz.open(pdf_path)
testo = ""
for pagina in doc:
testo += pagina.get_text()
doc.close()
return testo
def traduce_con_regole(testo_cinese, regole):
"""Traduce il testo cinese usando le regole specificate."""
prompt = f"""Sei un traduttore esperto di cinese.
Traduci il seguente testo cinese in italiano in due versioni:
TEXT:
{testo_cinese}
REGOLE:
{regole}
Rispondi SOLO con JSON nel formato:
{{
"originale": "...",
"letterale": "...",
"naturale": "..."
}}"""
risposta = chiama_claude(prompt)
if risposta:
try:
match = re.search(r'\{.*\}', risposta, re.DOTALL)
if match:
return json.loads(match.group())
except:
pass
return None
def crea_pdf_con_regole(dati, output_path, titolo):
"""Crea PDF con layout migliorato per le traduzioni."""
doc = SimpleDocTemplate(str(output_path), pagesize=A4)
styles = getSampleStyleSheet()
style_titolo = ParagraphStyle('Titolo', parent=styles['Heading1'],
fontSize=18, spaceAfter=12, textColor=colors.darkblue)
style_cinese = ParagraphStyle('Cinese', parent=styles['Normal'],
fontSize=14, fontName='STSong-Light')
style_traduzione = ParagraphStyle('Traduzione', parent=styles['Normal'],
fontSize=11, spaceAfter=6)
story = []
story.append(Paragraph(titolo, style_titolo))
story.append(Spacer(1, 12))
for voce in dati:
if not voce.get('originale'):
continue
story.append(Paragraph(f"{voce['originale']}", style_cinese))
if voce.get('pinyin'):
story.append(Paragraph(f"{voce['pinyin']}", styles['Normal']))
data_table = [
["LETTERALE", voce.get('letterale', '')],
["NATURALE", voce.get('naturale', '')]
]
t = Table(data_table, colWidths=[3*cm, 12*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0, 0), (0, -1), colors.lightgrey),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('PADDING', (0, 0), (-1, -1), 6),
('FONTSIZE', (0, 0), (-1, -1), 10),
]))
story.append(t)
story.append(Spacer(1, 12))
doc.build(story)
print(f"✅ PDF con regole creato: {output_path}")
def main():
print("🚀 Avvio traduzione ChinesePod v8 (con regole)")
regole = carica_regole()
if not regole:
print("⚠️ Nessuna regola caricata, continuo con quelle di default")
regole = """REGOLE traduzioni:
- LETTERALE: morfema per morfema, fedele alla struttura cinese
- NATURALE: italiano scorrevole ma vicino alla letterale"""
pdf_files = list(INPUT_DIR.glob("*.pdf"))
if not pdf_files:
print(f"❌ Nessun PDF trovato in {INPUT_DIR}")
return
for pdf_path in pdf_files:
print(f"📄 Elaborazione: {pdf_path.name}")
testo = estrai_testo_da_pdf(pdf_path)
if not testo:
print(f"⚠️ Nessun testo estratto da {pdf_path.name}")
continue
risultato = traduce_con_regole(testo, regole)
if not risultato:
print(f"⚠️ Traduzione fallita per {pdf_path.name}")
continue
json_path = OUTPUT_DIR / pdf_path.name.replace('.pdf', '_dati.json')
with open(json_path, 'w', encoding='utf-8') as f:
json.dump(risultato, f, ensure_ascii=False, indent=2)
pdf_output = OUTPUT_DIR / pdf_path.name.replace('.pdf', '_italiano.pdf')
crea_pdf_con_regole([risultato], pdf_output, titolo=pdf_path.name)
print(f"✅ Completato: {pdf_path.name}")
time.sleep(2)
if __name__ == "__main__":
main()
5. File prompt_regole.txt
REGOLE traduzioni: - LETTERALE: morfema per morfema, fedele alla struttura cinese - NATURALE: italiano scorrevole ma vicino alla letterale REGOLE traduzione LETTERALE (dettaglio): - Classificatori (量词, es. 个, 本, 张, 条...): traduci come articolo italiano appropriato Es: 一个人 → "una persona" (non "uno [clf] persona") Es: 两本书 → "due libri" (non "due [clf] libro") - Particella 的: traduci come "di" o genitivo italiano, non lasciarla esplicita Es: 我的书 → "il mio libro" (non "io DE libro") - Particella 了: indica azione completata → aggiungi "(fatto)" o usa passato Es: 我吃了 → "ho mangiato" - Particella 吗: domanda → aggiungi "?" senza tradurla esplicitamente - Negazione 不/没: "non" prima del verbo - Misure di tempo (年, 月, 天): "anno/i", "mese/i", "giorno/i" - Pronomi 我/你/他/她/它/我们/你们/他们: io/tu/lui/lei/esso/noi/voi/loro - Verbi di stato (是, 有, 在): "essere", "avere/esserci", "essere in/a" REGOLE segmenti: - Ogni segmento = una parola o morfema con il suo pinyin con toni - Punteggiatura = segmento con pinyin vuoto "" - Parole composte (我们, 你好, 谢谢) vanno tenute unite in un segmento REGOLE formattazione: - Per frasi corte: usa tabella pinyin/caratteri allineati - Per frasi lunghe: pinyin come testo separ