Files
office_translator/_bmad-output/implementation-artifacts/spec-rendu-fidele-langues-rtl.md
sepehr f22f645fab
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m37s
feat(rtl): rendu droite-a-gauche complet pour Word, PowerPoint, Excel et PDF
- source unique RTL_LANGUAGES/is_rtl dans core/languages.py (fin des 3 copies)
- Word: bidi partout (corps, tableaux bidiVisual, notes/fin/commentaires,
  zones de texte, 6 zones d'en-tetes/pieds), insertion OOXML ordonnee,
  polices cs elargies aux 11 langues
- PowerPoint: alignements explicites preserves, notes du presentateur,
  indice de police <a:cs> insert a sa place
- Excel: feuilles affichees de droite a gauche, feuilles graphiques ignorees
- PDF: faconnage bidi (arabic-reshaper + python-bidi), polices par ecriture
  (arabe/hebreu), TTF enregistree pour le PDF recompose
- 46 tests nouveaux (tests/test_translators/test_rtl_layout.py), 253 au total
2026-09-01 20:22:46 +02:00

11 KiB

title, type, created, status, review_loop_iteration, baseline_commit, context
title type created status review_loop_iteration baseline_commit context
Rendu fidèle des traductions pour les langues RTL (persan, arabe, hébreu…) feature 2026-09-01 done 0 fddd7b7428

Intent

Problem: Un document traduit vers une langue de droite à gauche sort dégradé : Excel ignore totalement le sens, PowerPoint force l'alignement à droite même sur les titres centrés et oublie les notes du présentateur, les tableaux Word ne sont pas inversés (ni notes de bas de page, ni zones de texte), et le PDF n'applique ni le façonnage des lettres arabes ni de police adaptée (lettres déconnectées, ordre inversé, carrés). Pour un lecteur persanophone ou arabophone, le résultat est parfois illisible.

Approach: Source de vérité unique pour le RTL dans core/languages.py, puis corrections ciblées dans les 4 traducteurs : direction et alignement corrects sans écraser les alignements explicites, inversion des tableaux, couverture des zones oubliées (notes, zones de texte), et pour le PDF façonnage bidi (arabic-reshaper + python-bidi) avec police couvrant l'écriture arabe.

Boundaries & Constraints

Always: Comportement inchangé pour toute cible non-RTL ; alignements explicites (centré, justifié) jamais écrasés ; aucun texte re-traduit ni altéré (seuls direction/alignement/indices de police sont ajoutés) ; RTL_LANGUAGES n'existe plus qu'une fois ; si arabic-reshaper/python-bidi manquent ou échouent, la traduction réussit quand même (texte tel quel + log d'avertissement).

Ask First: Ajouter une dépendance autre que arabic-reshaper et python-bidi ; modifier le Dockerfile (le paquet fonts-noto de Debian devrait déjà fournir Noto Naskh Arabic — vérifier dans l'image avant tout changement).

Never: Pas de refonte de la collecte des runs (fusion des runs PowerPoint / notes Word = chantier différé) ; pas de retentative automatique sur les contrôles qualité (différé) ; pas de modification des providers, de l'interface ni du frontend ; pas d'inversion des images ou graphiques vectoriels.

I/O & Edge-Case Matrix

Scenario Input / State Expected Output / Behavior Error Handling
Word cible RTL docx : corps, tableau, note de bas de page, zone de texte w:bidi sur tous les paragraphes, w:bidiVisual sur les tableaux, w:sectPr/w:bidi N/A
PPTX titre centré, cible ar algn="ctr" existant rtl="1" posé, algn reste "ctr" ; si algn absent ou "l"algn="r" N/A
PPTX avec notes diapositive avec notes du présentateur notes traduites ET passées en RTL N/A
Excel cible he xlsx multi-feuilles sheet_view.rightToLeft = True sur chaque feuille N/A
PDF mode mise en page, cible fa/ar pdf avec blocs de texte texte façonné avant insertion, police couvrant l'arabe, alignement à droite Police introuvable → police actuelle + warning ; bibliothèque absente → texte non façonné + warning ; jamais d'échec
PDF scanné / mode texte, cible RTL OCR ou mode text_only reportlab : police TTF enregistrée, wordWrap="RTL" sur le style Pas de TTF → Helvetica + warning (dégradation documentée)
Cible non-RTL (fr, zh…) tous formats Aucun attribut RTL ajouté, sortie identique à aujourd'hui N/A
Code régional fa-IR, ar-EG is_rtl() normalise le préfixe → RTL appliqué N/A

Code Map

  • core/languages.py -- LANGUAGE_NAMES l.12-123, language_name() l.126-137 : y ajouter RTL_LANGUAGES (frozenset) et is_rtl(code).
  • translators/word_translator.py -- copie RTL_LANGUAGES l.30-32 (supprimer) ; CS_FONTS l.45-50 (ar/he/fa/ur seulement) ; _set_paragraph_rtl l.126-153 (modèle : w:jc touché seulement sans alignement explicite) ; _apply_rtl_to_document l.156-182 (corps + tableaux + en-têtes/pieds ; manque w:bidiVisual, zones de texte, notes) ; déclencheur l.422-424 ; notes/comments réécrits en ZIP post-save l.811-995 (parts sans RTL).
  • translators/pptx_translator.py -- copie l.28-30 (supprimer) ; _set_pptx_paragraph_rtl l.57-71 (algn="r" inconditionnel — bug) ; _apply_rtl_to_presentation l.74-78 (pas de has_notes_slide) ; _apply_ea_font_hints l.114-158 (modèle exact pour <a:cs>) ; notes collectées l.313-319 ; déclencheur l.399-401.
  • translators/excel_translator.py -- translate_file l.141-175 ; aucun support RTL (0 occurrence) ; sauvegarde en fin de méthode.
  • translators/pdf_translator.py -- copie l.63-64 (supprimer) ; _FONT_SEARCH_PATHS l.115-134 (aucune police arabe) ; _get_font_path l.187-196 (première trouvée, insensible au script) ; alignement RTL l.903 ; insert_textbox l.1017-1049 (pas de façonnage) ; _generate_clean_pdf l.1434-1516 (reportlab, aucune police enregistrée).
  • requirements.txt + pyproject.toml (dependencies l.7+) -- dépendances dupliquées : mettre les deux à jour.
  • docker/backend/Dockerfile l.30-40 -- fonts-noto installé (vérifier le chemin de Noto Naskh Arabic dans l'image avant tout ajout).
  • tests/test_translators/ -- modèles : test_word_translator.py, test_pptx_translator.py, test_excel_translator.py, test_b3_pdf_fixes.py.
  • services/quality/script_detector.py -- lecture seule (distingue déjà arabe/persan — réutilisable plus tard, hors périmètre).

Tasks & Acceptance

Execution:

  • core/languages.py -- Ajouter RTL_LANGUAGES ({ar, he, fa, ur, ku, ps, ug, sd, yi, dv, ckb}) et is_rtl(code) -> bool (casse et préfixe régional ignorés) -- source unique, fin des 3 copies.
  • translators/word_translator.py -- Importer depuis core.languages ; _apply_rtl_to_document : w:bidiVisual sur chaque w:tbl du corps et des en-têtes/pieds (XPath .//w:tbl, couvre l'imbriqué), bidi/rtl sur les paragraphes des w:txbxContent ; réécriture ZIP (l.811-995) : w:bidi sur les w:pPr de footnotes.xml/endnotes.xml/comments.xml quand cible RTL ; CS_FONTS élargi à ps, ku, sd, ug, yi, dv, ckb (Arial).
  • translators/pptx_translator.py -- Importer ; algn="r" seulement si algn absent ou "l" ; _apply_rtl_to_presentation traite aussi notes_text_frame quand has_notes_slide ; ajouter _apply_cs_font_hints (modèle _apply_ea_font_hints) posant <a:cs typeface="Arial"> pour les cibles RTL.
  • translators/excel_translator.py -- Importer is_rtl ; avant sauvegarde : ws.sheet_view.rightToLeft = True par feuille quand cible RTL.
  • translators/pdf_translator.py -- Importer ; chemins Noto Naskh Arabic / Noto Sans Arabic (Linux) + C:/Windows/Fonts/arial.ttf ; _get_font_path prend la langue et choisit une police couvrant l'arabe pour les cibles RTL ; _shape_rtl(text) (import protégé, fallback texte tel quel + warning) appliquée aux blocs du mode mise en page et à _generate_clean_pdf ; dans ce dernier : pdfmetrics.registerFont de la TTF si présente + wordWrap="RTL" + fontName.
  • requirements.txt + pyproject.toml -- Ajouter arabic-reshaper et python-bidi (versions pinnées comme le reste).
  • tests/test_translators/test_rtl_layout.py -- Couvrir la matrice : docx (bidi corps/note, bidiVisual), pptx (algn conservé/posé, notes, <a:cs>), xlsx (rightToLeft), pdf (façonnage, police, fallback sans bibliothèque), is_rtl("fa-IR")/is_rtl("fr").

Acceptance Criteria:

  • Given un docx avec tableau et note de bas de page, when traduction vers fa, then w:bidi sur corps/note/zone de texte et w:bidiVisual sur le tableau.
  • Given un pptx avec un titre algn="ctr", when traduction vers ar, then le titre garde algn="ctr" et reçoit rtl="1".
  • Given un xlsx de 3 feuilles, when traduction vers he, then les 3 sheet_view.rightToLeft sont vrais.
  • Given un pdf textuel traduit vers fa, when mode mise en page, then texte façonné inséré et police arabe sélectionnée si présente.
  • Given une traduction vers fr, then aucun attribut RTL ajouté (sortie inchangée).

Spec Change Log

Verification

Commands:

  • python -m pytest tests/test_translators/test_rtl_layout.py -v -- expected: tous les tests passent.
  • python -m pytest tests/test_translators/ tests/test_language_validation.py -q -- expected: aucune régression.
  • python -c "import arabic_reshaper, bidi.algorithm; print('ok')" -- expected: ok.

Suggested Review Order

Source de vérité des langues

  • Liste unique partagée par les 4 traducteurs, fin des 3 copies locales languages.py:142

  • Normalisation casse/préfixe régional (fa-IR, AR → RTL ; fr, None → non) languages.py:147

Word — direction et ordre OOXML

PowerPoint — alignements et polices

Excel — sens des feuilles

PDF — façonnage et polices

Périphérie

  • 46 tests couvrant la matrice (docx/pptx/xlsx/pdf + endnotes/comments/chartsheet) test_rtl_layout.py:1

  • Dépendances façonnage (requirements.txt + pyproject.toml + uv.lock alignés) requirements.txt:11