Communitygithub.com

asadeisa/arabic-office-skills

Habilidades del agente para generar correctamente PDF, Word y PowerPoint en árabe/RTL, con vista previa PNG para verificación visual.

¿Qué es arabic-office-skills?

Este conjunto de habilidades (skill) está diseñado para que asistentes de IA como Claude Code, Cursor o Codex generen documentos PDF con texto árabe y otros idiomas de escritura de derecha a izquierda (RTL) de manera correcta. La generación ingenua de PDFs con bibliotecas como ReportLab produce errores sutiles pero graves: letras desconectadas, palabras en orden inverso dentro de una línea, o párrafos completos intercambiados. Este skill proporciona un constructor (`ArabicPDF`) que resuelve estos problemas aplicando reshaping, bidireccionalidad (bidi) con dirección base explícita, y ajuste de línea manual, evitando que ReportLab reordene el texto incorrectamente. Incluye además una función `preview()` que genera imágenes PNG de cada página para verificación visual obligatoria, ya que la extracción de texto no puede detectar estos defectos. El skill también documenta las diferencias críticas con la generación de documentos Word y PowerPoint, donde el enfoque es completamente opuesto: mientras que en PDF se debe proporcionar texto preformateado en orden visual, en Office se debe enviar texto Unicode en orden lógico sin reshaping. Incluye una tabla de hábitos de escritura que hacen que el árabe generado parezca artificial, con consejos para mejorar la naturalidad del texto.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add asadeisa/arabic-office-skills

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Generación de PDF en árabe / RTL

El código ingenuo de Reportlab produce un árabe sutil y profundamente incorrecto: las letras aparecen desconectadas, las palabras dentro de una línea corren hacia atrás y las líneas dentro de un párrafo intercambian lugares. Nada de esto es visible en el texto extraído, solo en una representación visual. Este skill incluye un constructor que ya tiene estos problemas resueltos.

Usa scripts/arabic_pdf.py en lugar de escribir lógica de reshaping desde cero. Cada modo de falla a continuación se encontró al probarlo en un documento real.

Dependencias

pip install reportlab arabic-reshaper python-bidi pypdfium2

pypdfium2 solo es necesario para la vista previa, pero la vista previa no es opcional; consulta Verificación a continuación.

Construir un documento

Importa el constructor copiando scripts/arabic_pdf.py junto a tu script de generación, o agregando la carpeta scripts/ de este skill a sys.path:

import pathlib, sys
sys.path.insert(0, str(pathlib.Path.home() / ".claude" / "skills" / "arabic-pdf" / "scripts"))
from arabic_pdf import ArabicPDF, preview

pdf = ArabicPDF("report.pdf", doc_title="عنوان المستند", page_numbers=True)

pdf.title("عنوان المستند")
pdf.subtitle("سطر فرعي")

pdf.heading("أولاً — المقدمة")
pdf.para("فقرة عربية تتضمن مصطلحات لاتينية مثل PostgreSQL و FastAPI.")

pdf.heading("ثانياً — جدول")
pdf.table(
    ["البند", "التفصيل"],                     # primera columna a la derecha
    [["الواجهة الخلفية", "Python — FastAPI"],
     ["قاعدة البيانات", "PostgreSQL — SQLAlchemy"]],
    [5.0, 11.0],                              # anchos de columna en cm
)

pdf.bullets(["نقطة أولى", "نقطة ثانية"])
pdf.save()

preview("report.pdf")     # un PNG por página

Ajusta la ruta si el skill se encuentra en otro lugar; nada más en el constructor depende de dónde esté instalado.

Los métodos se encadenan, por lo que pdf.heading(...).para(...) también funciona.

MétodoPropósito
title / subtitleEncabezado centrado del documento
headingEncabezado de sección en negrita alineado a la derecha
paraPárrafo del cuerpo
bullets(items, marker="–")Una línea alineada a la derecha por elemento
table(header, rows, widths_cm)Tabla RTL; orden de lectura natural de entrada, columnas invertidas de salida
spacer(pts) / page_break()Control de diseño
save()Escribe el archivo, devuelve la ruta

El texto de las celdas y párrafos puede contener \n para forzar un salto de línea.

Verificación: siempre renderiza y observa

Después de save(), llama a preview() y revisa los PNG con la herramienta Read. La extracción de texto no puede detectar defectos RTL, porque los caracteres están todos presentes y correctos; solo su orden y forma son incorrectos. Verifica específicamente:

  • ¿La primera palabra de cada párrafo está en la parte superior derecha?
  • ¿Los términos latinos (PostgreSQL, FastAPI) están donde deben estar en medio de la oración, en lugar de saltar al extremo izquierdo de la línea?
  • ¿Las letras están unidas o separadas como ا ل س ل ا م?
  • ¿Aparecen cuadros negros sólidos? La fuente carece de esos glifos; elige otra.
  • ¿Los corchetes están orientados correctamente? (20 فأكثر) no )20 فأكثر(?
  • ¿Los pares dentro de términos latinos están intactos? Array<String>, DECIMAL(5,2)?
  • ¿Una fila de tabla quedó huérfana en la página siguiente?

Arreglar un defecto que nunca buscaste cuesta mucho más tarde, cuando el documento ya está con su destinatario.

Cómo se logra la corrección

Útil al adaptar el constructor o depurar un documento extraño.

  1. Shaping — arabic_reshaper asigna a los caracteres formas de presentación posicionales para que las letras se conecten.
  2. Bidi con dirección base explícita — get_display(..., base_dir="R"). Sin base_dir, la dirección se infiere del primer carácter fuerte, por lo que una línea que comienza con una palabra latina se diseña de izquierda a derecha y el árabe después de ella queda mal. Esta es la causa más común de "mayormente correcto pero algunas líneas están desordenadas".
  3. Ajuste de línea manual — el texto reshaped está en orden visual. Si Reportlab lo ajusta, las palabras que empuja a la siguiente línea son las lógicamente primeras, por lo que las líneas salen mezcladas. El constructor ajusta primero, reshapea cada línea por separado y las une con <br/> para que Reportlab nunca reajuste. Un margen de seguridad de 8pt cubre diferencias de medición; una línea que desborda por un punto es suficiente para invertirla.
  4. Espejado — get_display reordena pero nunca aplica la regla bidi L4, que dice que un carácter reflejado diseñado de derecha a izquierda se dibuja como su contraparte. Sin ella, (20 فأكثر) vuelve con los dos paréntesis en posiciones intercambiadas y sus glifos originales, e imprime )20 فأكثر(. prepare() los sustituye primero, por lo que el reordenamiento mueve el glifo correcto.
  5. Islas latinas — < y > están reflejados pero no son corchetes emparejados en Unicode, por lo que la regla que mantiene DECIMAL(5,2) unido no los cubre; el > de Array<String> toma la dirección del árabe que lo sigue y se lanza al lado lejano. Cada tramo latino se envuelve en LRI…PDI y los aislantes se eliminan nuevamente después del reordenamiento, para que nada invisible llegue al PDF.
  6. Escapado después del shaping — Reportlab necesita que &, <, > se escapen, pero escapar primero envía &lt; a través del paso bidi como cuatro caracteres y su ; final se expulsa al lado lejano de la línea. Primero se reshapea, luego se escapa.
  7. Columnas de tabla invertidas — Reportlab coloca las columnas de izquierda a derecha, por lo que el constructor las invierte, permitiéndote pasar las columnas en orden de lectura natural.
  8. KeepTogether en tablas — evita que una fila solitaria quede varada en una nueva página.

Los puntos 4–6 son la misma clase de defecto que las ejecuciones de corchetes divididos descritas en arabic-docx, abordados desde la dirección opuesta: allí un par no debe dividirse entre ejecuciones, aquí un par no debe reflejarse a medias. Cualquier carácter reflejado debe resolverse junto con su contraparte.

Fuentes

register_fonts() busca una fuente compatible con árabe: Arial luego Tahoma en Windows, Arial en macOS, Noto Naskh Arabic luego DejaVu Sans en Linux. Para usar una fuente específica (Amiri y Cairo son adecuadas para documentos formales):

from arabic_pdf import register_fonts
register_fonts("/ruta/Amiri-Regular.ttf", "/ruta/Amiri-Bold.ttf")   # antes de ArabicPDF(...)

Las fuentes integradas de Reportlab no tienen cobertura de árabe, por lo que se debe registrar un TTF; esta es la razón por la que una fuente faltante se muestra como cuadros negros en lugar de un error.

Nunca lleves este enfoque a Word o PowerPoint

Este es el límite más importante en toda la familia de habilidades RTL.

Reportlab / PillowWord / PowerPoint
Motor de textoningunomotor bidireccional completo
Esperaglifos finales en orden visualUnicode en orden lógico sin procesar
Técnicareshape + bidi + ajuste manualindicadores de dirección en el XML

El pre-shaping es requerido aquí y destructivo allí: Word y PowerPoint shapesan en tiempo de renderizado, por lo que entregarles formas de presentación hace que eshapeen una segunda vez: glifos rotos y texto que ya no se puede buscar, copiar ni revisar ortográficamente. Los dos enfoques son opuestos, no variaciones.

Usa arabic-docx para .docx y arabic-pptx para .pptx. No portes código entre los tres sin releer por qué difieren.

Notas

  • arabic_digits("38") → "٣٨" cuando se desean números arábigo-indios. Puramente cosmético; los dígitos occidentales son perfectamente normales en la escritura técnica árabe.
  • Mantén el formato moderado por defecto: texto negro, reglas finas. Los documentos académicos y oficiales en árabe se leen como más creíbles de esa manera, y los usuarios que piden "simple" lo dicen en serio.
  • El mismo mecanismo maneja persa, urdu y hebreo; solo la fuente debe cubrir la escritura.

Qué hace que el árabe generado se lea como generado

No el vocabulario, sino las adiciones. Cada hábito a continuación le dice al lector algo sobre cómo se escribió el documento en lugar de sobre su tema, y un lector que edita a mano los elimina todos. Escribe la oración, no el relato de escribirla.

HábitoEn lugar deEscribe
Narrar el acto de escribir«الشروط ثلاثة، نذكرها صراحة فيما يلي»«الشروط ثلاثة:»
Señalar otra sección«…ونعود إلى هذه النقطة لاحقاً»احذف العبارة
Etiquetas de versión o estado en un título«الخطة (النسخة الثانية — معتمدة)»«الخطة»
Argumentar contra una opción que nadie planteó«نحفظ المسار فقط. تخزين الملف كاملاً يضخّم الحجم بلا فائدة.»«نحفظ المسار فقط.»
Justificar una elección por lo que omitió el resumen«لم يرد ذلك في الطلب، غير أن طبيعة العمل تفرضه.»«طبيعة العمل تفرض ذلك.»
Primera persona del singular«وأستطيع لاحقاً تحليل الحالات»«ويمكن لاحقاً تحليل الحالات»
Repetir un hecho que el documento ya proporcionóتكرار المعلومة في قسم آخراحذف التكرار

El árabe formal prefiere lo impersonal o el plural sobre «أنا»; el singular se lee como una nota para uno mismo en lugar de un documento.

Skills relacionados