fix(direction): le sens du document traduit suit la langue cible, dans les deux sens
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 3m3s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 3m3s
Persan -> francais : le document traduit restait en lecture de droite a gauche, heritee de la source. Trois causes : - PDF : regression du renommage precedent — le choix d'alignement testait la fonction is_rtl (toujours vraie) au lieu du parametre : tout texte traduit s'alignait a droite, quelle que soit la cible. Corrige + test epinglant l'alignement gauche pour une cible latine. - Word : les marques RTL heritees (bidi, rtl, bidiVisual, notes et commentaires compris) sont desormais retirees quand la cible est latine ; retrait fait sur une liste figee (l'iterateur lxml sautait des elements pendant la suppression). - Excel : les feuilles heritees d'un affichage droite-a-gauche sont remises en lecture gauche-a-droite pour une cible latine. - PowerPoint : les attributs rtl herites sont retires pour une cible latine (alignements visuels conserves). 3 tests de bout en bout nouveaux : document RTL traduit vers le francais ressort en lecture gauche-a-droite dans les trois formats.
This commit is contained in:
@@ -121,6 +121,46 @@ def _apply_rtl_to_presentation(presentation: Presentation) -> None:
|
||||
_set_pptx_paragraph_rtl(paragraph)
|
||||
|
||||
|
||||
def _unset_pptx_paragraph_rtl(paragraph) -> None:
|
||||
"""Drop a paragraph's inherited RTL direction (Latin targets).
|
||||
|
||||
Translating a Persian/Arabic source into a Latin target must not keep
|
||||
the source's rtl="1" marks: with rtl gone the paragraph falls back to
|
||||
the natural left-to-right direction. Alignment attributes are left
|
||||
untouched (algn is visual in DrawingML — centered stays centered).
|
||||
"""
|
||||
pPr = paragraph._p.find(f"{{{_NS_A}}}pPr")
|
||||
if pPr is not None and pPr.get("rtl") == "1":
|
||||
pPr.attrib.pop("rtl", None)
|
||||
|
||||
|
||||
def _apply_ltr_to_presentation(presentation: Presentation) -> None:
|
||||
"""Strip inherited RTL direction from all slides and notes (Latin targets)."""
|
||||
for slide in presentation.slides:
|
||||
for shape in slide.shapes:
|
||||
_apply_ltr_to_shape(shape)
|
||||
if slide.has_notes_slide and slide.notes_slide.notes_text_frame is not None:
|
||||
for paragraph in slide.notes_slide.notes_text_frame.paragraphs:
|
||||
_unset_pptx_paragraph_rtl(paragraph)
|
||||
|
||||
|
||||
def _apply_ltr_to_shape(shape) -> None:
|
||||
"""Recursively strip RTL from a shape (handles groups and tables)."""
|
||||
if shape.has_text_frame:
|
||||
for paragraph in shape.text_frame.paragraphs:
|
||||
_unset_pptx_paragraph_rtl(paragraph)
|
||||
|
||||
if shape.shape_type == MSO_SHAPE_TYPE.TABLE:
|
||||
for row in shape.table.rows:
|
||||
for cell in row.cells:
|
||||
for paragraph in cell.text_frame.paragraphs:
|
||||
_unset_pptx_paragraph_rtl(paragraph)
|
||||
|
||||
if shape.shape_type == MSO_SHAPE_TYPE.GROUP:
|
||||
for sub_shape in shape.shapes:
|
||||
_apply_ltr_to_shape(sub_shape)
|
||||
|
||||
|
||||
def _apply_rtl_to_shape(shape) -> None:
|
||||
"""Recursively apply RTL to a shape (handles groups and tables)."""
|
||||
if shape.has_text_frame:
|
||||
@@ -468,9 +508,14 @@ class PowerPointTranslator:
|
||||
index=i,
|
||||
)
|
||||
|
||||
# Apply RTL layout when the target language is written right-to-left.
|
||||
# Normalize the direction to the TARGET language: RTL targets
|
||||
# switch to right-to-left, Latin targets strip the rtl marks
|
||||
# inherited from an RTL source (Persian → French must read
|
||||
# left-to-right, not keep the source's layout).
|
||||
if is_rtl(target_language):
|
||||
_apply_rtl_to_presentation(presentation)
|
||||
else:
|
||||
_apply_ltr_to_presentation(presentation)
|
||||
|
||||
# CJK font hint so the target script renders with a proper
|
||||
# typeface instead of shape-dependent fallbacks.
|
||||
|
||||
Reference in New Issue
Block a user