Revayat Novel — Traducción de libro inglés → persa
Ejecute los nueve pasos a continuación en orden. Cada uno es un comando más una regla sobre qué hacer con su salida. No improvise un orden diferente y no salte un paso porque el anterior parecía correcto.
Establezca cuatro variables una vez y úselas en todas partes:
SKILL_DIR— la carpeta que contiene este archivo. En un plugin de Claude Code es${CLAUDE_PLUGIN_ROOT}/skills/revayat-novel.WORK— una carpeta de trabajo para este libro, p. ej.work/.PY— el intérprete de Python. Resuélvalo una vez;python3no existe en la mayoría de las instalaciones de Windows, por lo que una línea de comando que lo codifique funciona en dos de cada tres plataformas:- macOS / Linux:
PY=python3 - Windows:
PY=python— oPY="py -3"si el lanzador es lo que está instalado - si ninguno funciona,
doctoren el paso 1 no arrancará, y esa es la señal
- macOS / Linux:
OCR_LANG— el código de Tesseract para el idioma impreso en el libro que está traduciendo, no el idioma al que está traduciendo. Para el trabajo habitual de inglés → persa eseng. Una fuente en persa esfas; alemándeu, francésfra, árabeara. El mismo valor debe usarse en cada paso de OCR. Reconocer páginas en inglés con el modelo persa devuelve disparates con apariencia de confianza, lo cual es peor que una puntuación baja porque nada en la cadena descendente puede detectarlo.
Cada comando es $PY $SKILL_DIR/scripts/revayat-novel.py <etapa> ….
Las cinco reglas que nunca deben romperse
- Nunca invierta texto persa para que se lea de derecha a izquierda. La dirección la establece el constructor. Invertir produce un archivo que está roto en todas partes excepto en un visor.
- Nunca invente, elimine, fusione, divida o reordene un encabezado
@@ id. Devuelva exactamente los que le dieron. - Nunca elimine un marcador
[[fn:…]],**negrita**,*cursiva*o`literal`. Se cuentan; un desajuste falla el control de calidad. - Nunca edite manualmente
book.jsonpara corregir una traducción. Corrija la hoja de trabajo y vuelva a ejecutar la fusión. - Nunca acorte el libro. Sin resumir, sin saltar una oración difícil, sin suavizar. Si un paso informa contenido faltante, vuelva a ejecutar ese fragmento.
Paso 1 — Verificar las herramientas
$PY $SKILL_DIR/scripts/revayat-novel.py doctor
"ready": true→ continúe."ready": false→ ejecutepip install -r $SKILL_DIR/requirements.txt, luego ejecutedoctorde nuevo.optional_toolsmostrandonot foundestá bien por ahora. El paso 2 le dirá si realmente se necesita OCR.
Paso 2 — Extraer
$PY $SKILL_DIR/scripts/revayat-novel.py extract "<archivo de entrada>" --out $WORK --ocr-lang $OCR_LANG
$OCR_LANG es el idioma impreso en el libro, establecido una vez arriba. Equivocarse aquí no es un fallo visible: el OCR aún devuelve texto, simplemente es el texto incorrecto.
Lea el JSON que imprime y siga la tabla:
| Lo que ve | Qué hacer |
|---|---|
"kind": "digital" | nada; no se necesitó OCR |
"kind": "scanned" o "mixed" | el OCR se ejecutó automáticamente; verifique que ocr.probe_after.text_share esté por encima de 0.7 |
| un error que menciona OCRmyPDF | instálelo como dice el mensaje, luego vuelva a ejecutar este paso |
clean_scan.cleaned por encima de 0 | se eliminó una marca de agua de color de esa cantidad de páginas |
ocr.warning no es nulo | léalo; el archivo aún era utilizable, así que continúe |
page_scans_dropped por encima de 0 | esa cantidad de rásteres de página completa se reconocieron como el escaneo en sí, no como imágenes |
El limpiador nunca edita su archivo: el original permanece intacto y la copia limpia se escribe en $WORK/cleaned.pdf, con un registro por página en clean_scan de lo que se eliminó y lo que se dejó intacto. Pase --clean-scan off para omitirlo por completo, o --clean-scan force cuando sobreviva un sello.
Si el libro fue escaneado, realice estas dos pasadas adicionales ahora.
Confianza de reconocimiento — sin ella, una palabra mal leída es indistinguible de una correcta, porque ambas son palabras ordinarias del idioma de origen, ubicadas en una oración gramatical. Nada más adelante en el proceso puede diferenciarlas, y el traductor representará fielmente la incorrecta.
$PY $SKILL_DIR/scripts/revayat-novel.py ocr-sidecar \
--pdf $WORK/ocr.pdf --out $WORK --lang $OCR_LANG --book $WORK/book.json
--lang aquí es el mismo $OCR_LANG que le dio a extract. Tiene que serlo: esta pasada vuelve a reconocer las mismas páginas para determinar qué tan segura estaba el motor, por lo que un modelo diferente lee palabras diferentes y puntúa algo que el libro no dice.
Esto escribe source.ocr.json — cuadro, confianza y orden de lectura para cada palabra, agregado hasta línea, bloque y página, más qué preprocesamiento se ejecutó — y source.ocr.txt, luego sella cada bloque en book.json con la confianza de la región de la que provino. Los bloques clasificados como low son informados por qa check como ocr-low-confidence, y aceptar uno significa mirar la imagen de la página. Los umbrales predeterminados son 85 y 60 y se mueven con --high / --low.
Ilustraciones dentro de un escaneo — una página escaneada es una imagen plana, por lo que una fotografía en ella no es una imagen separada hasta que algo la encuentra:
mineru -p $WORK/cleaned.pdf -o $WORK/mineru -b pipeline -l en
$PY $SKILL_DIR/scripts/revayat-novel.py extract "<archivo de entrada>" --out $WORK \
--figures-from-mineru $WORK/mineru
MinerU -l usa sus propios códigos, no los de Tesseract: en para una fuente en inglés, arabic para escritura persa o árabe. Combínelo con el libro, de la misma manera que se combina $OCR_LANG — la detección de diseño usa la escritura para segmentar la página.
Ejecute MinerU en cleaned.pdf, no en el original, o recortará la marca de agua como si fuera una figura. Tome solo las imágenes de MinerU. Medido en un escaneo persa real, su texto reconocido devolvió las palabras y las letras dentro de ellas invertidas, mientras que Tesseract leyó la misma página correctamente — por lo que el texto sigue proviniendo de la pasada de OCR anterior y MinerU se usa solo para lo que el OCR no puede hacer, que es encontrar dónde se ubica una imagen en un ráster plano. Use --figures-page-offset N cuando MinerU se ejecutó en un rango de páginas.
Luego mire el resultado antes de continuar:
$PY $SKILL_DIR/scripts/revayat-novel.py qa check --book $WORK/book.json --allow-incomplete
Ignore untranslated-block aquí — nada está traducido todavía. Está buscando asset-missing. Si stats.text_blocks está por debajo de 20 para un libro real, la extracción falló: consulte references/extraction.md.
Paso 3 — Glosario
$PY $SKILL_DIR/scripts/revayat-novel.py glossary scan \
--book $WORK/book.json --out $WORK/glossary.json
El informe enumera needs_persian, primero los más frecuentes. Abra $WORK/glossary.json y para cada una de las primeras 20 entradas complete cuatro campos:
"target": "الیزابت بنت",
"later_form": "الیزابت بنت",
"first_form": "الیزابت بنت (Elizabeth Bennet)",
"locked": true
Cuando una entrada tiene aliases — un apellido o un nombre de pila que el libro usa por sí solo — ponga su persa en alias_targets:
"aliases": ["Ashcroft", "Margaret"],
"alias_targets": ["اشکرافت", "مارگارت"]
Donde la fuente dice solo «Ashcroft», el persa debe decir solo «اشکرافت». Dejar esto vacío hace que la verificación de desviación exija el nombre completo cada vez, lo cual es tanto peor persa como una falsa alarma.
Deje first_block_id exactamente como está — el proceso lo usa para decidir qué fragmento individual introduce el nombre. No lo edite y no decida las primeras menciones usted mismo.
Elimine las entradas que no sean nombres reales. Luego continúe.
Paso 4 — Dividir en hojas de trabajo
Una novela completa nunca debe alcanzar el contexto de un modelo, por lo que primero se divide. Hay dos formas de dividir, y la fuente decide cuál — esto no es una preferencia:
| Fuente | Ruta |
|---|---|
| PDF, nativo digital o escaneado | por página — abajo |
| EPUB, DOCX, texto plano | por presupuesto de caracteres — paso 4b |
Divida un PDF por página. Una página es un límite que el libro ya tiene: estable entre ejecuciones, la unidad que un revisor mira, y la única unidad contra la que se puede comparar una página renderizada. Una hoja de trabajo dividida por presupuesto de caracteres se rompe dondequiera que el presupuesto se agote, que no es un lugar en particular — y una página que no existe en la fuente no se puede verificar contra la fuente. Los formatos debajo de la línea no tienen páginas propias para dividir, por lo que toman la ruta del presupuesto y renuncian a esa verificación.
$PY $SKILL_DIR/scripts/revayat-novel.py pages build \
--book $WORK/book.json --out $WORK/pages --glossary $WORK/glossary.json
Esto escribe una hoja de trabajo por página de origen — page0001.md, y su traducción va en out_page0001.md a su lado. Use esos nombres, no el chunkNNNN.md del paso 5: el formato es idéntico, solo los nombres de archivo difieren, y pages next le dice exactamente qué archivo abrir, por lo que no hay nada que adivinar.
También escribe $WORK/pages/source/page-0001.pdf — cada página de origen como su propio PDF, copiado en lugar de volver a renderizar para que los cuadros, la rotación y la calidad de la imagen sean los del libro. El manifiesto registra cada uno con su SHA-256 y nombra el reference_pdf del que se leyó toda la ejecución. Lea el PDF de origen del manifiesto; es el original para un libro nativo digital y la copia OCR para un escaneo, y codificar cualquiera de los dos es incorrecto para el otro.
Cada trabajo de página lleva solo lo que necesita: las filas del glosario que se aplican en esa página, las voces que hablan allí, las palabras de las que el OCR no estaba seguro allí, y una porción limitada de las páginas vecinas marcadas como no traducir. Una página cuyo propio texto excede el presupuesto se divide en partes numeradas en lugar de truncarse — part y parts en el manifiesto lo indican — y las partes se reúnen antes de que se juzgue la página.
Un párrafo que el corte de página partió por la mitad pertenece a la página en la que comenzó y se traduce exactamente una vez; la página en la que continúa lo ve solo como contexto. Nunca traduzca un bloque que aparezca bajo el encabezado de contexto vecino — ya pertenece a la hoja de trabajo de otra página.
$PY $SKILL_DIR/scripts/revayat-novel.py pages status --pages $WORK/pages
$PY $SKILL_DIR/scripts/revayat-novel.py pages next --pages $WORK/pages
status informa el estado de cada página; next nombra la primera página que aún queda por hacer, por lo que una ejecución interrumpida se reanuda donde se detuvo en lugar de desde el principio.
El bucle de páginas
El PDF de origen es aquel del que se leyó esta ejecución: el propio del libro para un PDF nativo digital, la copia OCR para un escaneo. El manifiesto lo registró — tómelo de allí en lugar de nombrar un archivo que puede no existir.
SOURCE_PDF=$($PY -c "import json,sys;print(json.load(open(sys.argv[1]))['reference_pdf'])" $WORK/pages/manifest.json)
Una página a la vez, en este orden. Cada comando necesita lo que produjo el anterior, por lo que un paso tomado antes simplemente se niega:
P=12 # lo que sea que `pages next` acaba de nombrar
# 3. incorporar la traducción al libro
$PY $SKILL_DIR/scripts/revayat-novel.py pages merge \
--book $WORK/book.json --pages $WORK/pages --page $P --glossary $WORK/glossary.json
# 4. diseñar esa página por sí sola
$PY $SKILL_DIR/scripts/revayat-novel.py pages preview \
--book $WORK/book.json --pages $WORK/pages --page $P
# 5. compararla con la página de origen
$PY $SKILL_DIR/scripts/revayat-novel.py render-qa \
--book $WORK/book.json --work $WORK --page $P \
--docx $WORK/previews/page-0012.docx --source-pdf $SOURCE_PDF
# 6. mirar las dos imágenes (el paso 8 dice qué buscar)
$PY $SKILL_DIR/scripts/revayat-novel.py pages review \
--pages $WORK/pages --page $P \
--answer figure-placement=yes --answer script-integrity=yes \
--answer no-source-language=yes --answer hierarchy=yes \
--answer reads-as-a-book=yes --note "lo que viste"
# 7. solo ahora
$PY $SKILL_DIR/scripts/revayat-novel.py pages accept \
--book $WORK/book.json --pages $WORK/pages --page $P
Luego pages next de nuevo, hasta que diga que no queda nada.
El paso 4 no es opcional y el paso 5 lo hará por usted si lo omite — omita --docx y render-qa crea la vista previa por sí mismo. El comando explícito está ahí para cuando quiera abrir la página en Word y mirarla usted mismo.
La vista previa es una página de origen, diseñada sola. No es enfáticamente el libro completo: el persa se refluye, por lo que la página 12 de origen no se convierte en la página 12 del libro, y para la mitad de una novela la desviación es de varias páginas. Verificar la duodécima hoja del libro contra las expectativas de la página 12 informa una página correcta como si faltara todo su texto y llevara el de su vecino. La vista previa se establece con el constructor de producción — mismos estilos, fuentes, RTL, tamaño de imagen, lógica de encabezados — por lo que lo que está mirando es la composición tipográfica real del contenido real.
Una página cuyo persa es más largo que su inglés sale como dos hojas. Eso es normal, ambas se mantienen como renders/target/page-0012.png y page-0012-2.png, y el control de calidad las lee todas.
accept se niega a menos que cada puerta haya pasado realmente: lee la evidencia en lugar de tomar su palabra, por lo que una página no se puede marcar como hecha afirmándolo. Quiere cuatro cosas: persa en el libro para cada unidad que la página envió, una verificación de render QA en el registro de ejecución, un informe que todavía lo diga, y una revisión visual actual.
Reconstruir es seguro y nunca descarta una traducción. Una página cuyo texto de origen ha cambiado desde la última vez que se cortó se enumera bajo invalidated — esas, y solo esas, necesitan traducirse de nuevo. Una hoja de trabajo sobrante de una reconstrucción con un presupuesto diferente se enumera bajo orphaned: todavía está en el disco, pero nada la lee más, por lo que su traducción no llegará al libro.
Paso 4b — Cuando la fuente no tiene páginas
Solo EPUB, DOCX y texto plano. Para un PDF, use el paso 4.
$PY $SKILL_DIR/scripts/revayat-novel.py chunk build \
--book $WORK/book.json --out $WORK/chunks --glossary $WORK/glossary.json
Note el número de fragmentos. Cada uno se convierte en una tarea de traducción.
Si ya ha traducido algunas hojas de trabajo y una entrada ha cambiado desde entonces, esto se niega con "refused": "stale-worksheets" en lugar de entregarle silenciosamente hojas de trabajo que ya no coinciden con el libro.