Communitygithub.com

asadeisa/compétences-arabes-bureau

Compétences d'agent pour la génération correcte de contenu arabe/RTL en PDF, Word et PowerPoint — avec aperçu PNG pour vérification visuelle.

Qu'est-ce que compétences-arabes-bureau ?

Cette compétence résout les problèmes complexes de rendu arabe et RTL dans les documents PDF générés par programmation avec ReportLab. Le code naïf produit un texte arabe visuellement incorrect : lettres déconnectées, lignes inversées, et paragraphes désordonnés. La compétence fournit un constructeur `ArabicPDF` qui intègre les corrections nécessaires : reshape des caractères avec `arabic-reshaper`, ordre bidirectionnel avec `python-bidi` et une base de direction explicite, coupure de ligne manuelle pour éviter le réordonnancement, miroir des caractères pour les parenthèses, et isolation des termes latins. Elle inclut aussi une fonction d'aperçu `preview()` pour générer des images PNG des pages, car l'extraction de texte ne peut pas détecter les défauts d'ordre et de forme. La compétence est conçue pour être utilisée avec Claude Code ou d'autres agents IA, et son code est compatible avec tout environnement Python disposant des dépendances listées. Il est crucial de noter que cette approche de pré-reshapage est spécifique à ReportLab et ne doit pas être appliquée à Word ou PowerPoint, qui nécessitent du texte Unicode brut en ordre logique.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Génération de PDF arabe / RTL

Le code ReportLab naïf produit un arabe subtilement mais totalement erroné : les lettres apparaissent déconnectées, les mots dans une ligne s'affichent à l'envers et les lignes dans un paragraphe s'échangent leurs places. Rien de tout cela n'est visible dans le texte extrait — uniquement à l'affichage. Cette compétence intègre un constructeur qui a déjà résolu ces problèmes.

Utilisez scripts/arabic_pdf.py plutôt que d'écrire la logique de reshapage à partir de zéro. Chaque mode d'échec ci-dessous a été découvert en le rencontrant dans un document réel.

Dépendances

pip install reportlab arabic-reshaper python-bidi pypdfium2

pypdfium2 n'est nécessaire que pour l'aperçu, mais l'aperçu n'est pas optionnel — voir Vérification ci-dessous.

Construire un document

Importez le constructeur soit en copiant scripts/arabic_pdf.py à côté de votre script de génération, soit en ajoutant le dossier scripts/ de cette compétence à 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(
    ["البند", "التفصيل"],                     # colonne la plus à droite en premier
    [["الواجهة الخلفية", "Python — FastAPI"],
     ["قاعدة البيانات", "PostgreSQL — SQLAlchemy"]],
    [5.0, 11.0],                              # largeurs de colonnes en cm
)

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

preview("report.pdf")     # un PNG par page

Ajustez le chemin si la compétence se trouve ailleurs — rien d'autre dans le constructeur ne dépend de son emplacement d'installation.

Les méthodes s'enchaînent, donc pdf.heading(...).para(...) fonctionne aussi.

MéthodeObjectif
title / subtitleEn-tête de document centré
headingEn-tête de section en gras, aligné à droite
paraParagraphe de corps
bullets(items, marker="–")Une ligne alignée à droite par élément
table(header, rows, widths_cm)Tableau RTL ; ordre de lecture naturel en entrée, colonnes inversées en sortie
spacer(pts) / page_break()Contrôle de la mise en page
save()Écrit le fichier, renvoie le chemin

Le texte des cellules et des paragraphes peut contenir \n pour forcer un saut de ligne.

Vérification — toujours générer et regarder

Après save(), appelez preview() et visualisez les PNG avec l'outil Read. L'extraction de texte ne peut pas détecter les défauts RTL, car les caractères sont tous présents et corrects ; seuls leur ordre et leur forme sont erronés. Vérifiez spécifiquement :

  • Est-ce que le premier mot de chaque paragraphe se trouve en haut à droite ?
  • Les termes latins (PostgreSQL, FastAPI) se trouvent-ils à leur place au milieu de la phrase, plutôt que de sauter à l'extrémité gauche de la ligne ?
  • Les lettres sont-elles connectées, ou séparées comme ا ل س ل ا م ?
  • Y a-t-il des boîtes noires pleines ? La police ne possède pas ces glyphes — choisissez-en une autre.
  • Les parenthèses sont-elles orientées correctement — (20 فأكثر) et non )20 فأكثر( ?
  • Les paires dans les termes latins sont-elles intactes — Array<String>, DECIMAL(5,2) ?
  • Une ligne de tableau a-t-elle été orpheline sur la page suivante ?

Corriger un défaut que vous n'avez jamais recherché coûte bien plus tard, lorsque le document est déjà chez son destinataire.

Comment la correction est obtenue

Utile pour adapter le constructeur ou déboguer un document étrange.

  1. Reshapage — arabic_reshaper mappe les caractères à leurs formes de présentation positionnelles pour que les lettres se connectent.
  2. Bidi avec une direction de base explicite — get_display(..., base_dir="R"). Sans base_dir, la direction est déduite du premier caractère fort, donc une ligne commençant par un mot latin est disposée de gauche à droite et l'arabe qui suit se place mal. C'est la cause la plus courante de « presque correct mais certaines lignes sont mélangées ».
  3. Retour à la ligne manuel — le texte reshapé est en ordre visuel. Si ReportLab le coupe, les mots qu'il pousse à la ligne suivante sont logiquement les premiers, donc les lignes sont mélangées. Le constructeur coupe d'abord, reshape chaque ligne séparément, et les joint avec <br/> pour que ReportLab ne recoupe jamais. Une marge de sécurité de 8pt couvre les différences de mesure ; une ligne qui dépasse d'un point suffit à l'inverser.
  4. Miroir — get_display réordonne mais n'applique jamais la règle bidi L4, qui dit qu'un caractère en miroir disposé de droite à gauche est dessiné comme son partenaire. Sans lui (20 فأكثر) revient avec les deux parenthèses échangées et leurs glyphes originaux, et imprime )20 فأكثر(. prepare() les substitue d'abord, donc le réordonnancement déplace le glyphe correct.
  5. Îlots latins — < et > sont en miroir mais ne sont pas des parenthèses appariées Unicode, donc la règle qui maintient DECIMAL(5,2) ensemble ne les couvre pas ; le > de Array<String> prend la direction de l'arabe après lui et est projeté de l'autre côté. Chaque segment latin est enveloppé dans LRI…PDI et les isolateurs sont supprimés après le réordonnancement, pour que rien d'invisible n'atteigne le PDF.
  6. Échappement après le reshapage — ReportLab nécessite l'échappement de &, <, >, mais échapper d'abord envoie &lt; dans le processus bidi comme quatre caractères et son ; final est éjecté de l'autre côté de la ligne. Shapez, puis échappez.
  7. Colonnes de tableau inversées — ReportLab dispose les colonnes de gauche à droite, donc le constructeur les inverse, vous permettant de passer les colonnes dans l'ordre de lecture naturel.
  8. KeepTogether sur les tableaux — empêche une ligne isolée de se retrouver sur une nouvelle page.

Les points 4–6 sont de la même classe de défauts que les séquences de parenthèses divisées décrites dans arabic-docx, atteints depuis la direction opposée : là, une paire ne doit pas être séparée entre les séquences, ici une paire ne doit pas être à moitié en miroir. Tout caractère en miroir doit être résolu avec son partenaire.

Polices

register_fonts() recherche une police capable d'afficher l'arabe : Arial puis Tahoma sur Windows, Arial sur macOS, Noto Naskh Arabic puis DejaVu Sans sur Linux. Pour utiliser une police spécifique (Amiri et Cairo conviennent bien aux documents formels) :

from arabic_pdf import register_fonts
register_fonts("/chemin/Amiri-Regular.ttf", "/chemin/Amiri-Bold.ttf")   # avant ArabicPDF(...)

Les polices intégrées de ReportLab n'ont pas de couverture arabe, donc un TTF doit être enregistré — c'est pourquoi une police manquante apparaît comme des boîtes noires plutôt qu'une erreur.

Ne jamais transposer cette approche à Word ou PowerPoint

C'est la limite la plus importante dans toute la famille de compétences RTL.

ReportLab / PillowWord / PowerPoint
Moteur de texteaucunmoteur bidirectionnel complet
Attenddes glyphes finaux en ordre visuelUnicode brut en ordre logique
Techniquereshape + bidi + coupure manuelleindicateurs de direction dans le XML

Le pré-reshapage est nécessaire ici et destructeur là-bas : Word et PowerPoint s'occupent du reshapage au moment du rendu, donc leur donner des formes de présentation les fait reshaper une seconde fois — glyphes cassés et texte qui ne peut plus être recherché, copié ou vérifié orthographiquement. Les deux approches sont opposées, pas des variations.

Utilisez arabic-docx pour les .docx et arabic-pptx pour les .pptx. Ne portez pas de code entre les trois sans relire pourquoi ils diffèrent.

Remarques

  • arabic_digits("38") → "٣٨" lorsque les chiffres arabo-indiens sont souhaités. Purement cosmétique ; les chiffres occidentaux sont tout à fait normaux dans l'écriture technique arabe.
  • Conservez un formatage sobre par défaut — texte noir, filets fins. Les documents académiques et officiels arabes sont plus crédibles ainsi, et les utilisateurs qui demandent « simple » le pensent vraiment.
  • Les mêmes mécanismes gèrent le persan, l'ourdou et l'hébreu ; seule la police doit couvrir l'écriture.

Ce qui fait que l'arabe généré semble généré

Ce n'est pas le vocabulaire — ce sont les ajouts. Chaque habitude ci-dessous indique au lecteur comment le document a été écrit plutôt que son sujet, et un lecteur qui édite à la main les supprime tous. Écrivez la phrase, pas le récit de son écriture.

HabitudeAu lieu deÉcrivez
Raconter l'acte d'écrire« الشروط ثلاثة، نذكرها صراحة فيما يلي »« الشروط ثلاثة : »
Pointer vers une autre section« …ونعود إلى هذه النقطة لاحقاً »Supprimez la phrase
Étiquettes de version ou statut dans un titre« الخطة (النسخة الثانية — معتمدة) »« الخطة »
Argumenter contre une option que personne n'a soulevée« نحفظ المسار فقط. تخزين الملف كاملاً يضخّم الحجم بلا فائدة. »« نحفظ المسار فقط. »
Justifier un choix par ce que le brief a omis« لم يرد ذلك في الطلب، غير أن طبيعة العمل تفرضه. »« طبيعة العمل تفرض ذلك. »
Première personne du singulier« وأستطيع لاحقاً تحليل الحالات »« ويمكن لاحقاً تحليل الحالات »
Réaffirmer un fait que le document a déjà donnéRépétition de l'information dans une autre sectionSupprimez la répétition

L'arabe formel préfère l'impersonnel ou le pluriel à « أنا » ; le singulier ressemble à une note pour soi-même plutôt qu'à un document.

Skills associés