fix(pdf): corriger la mise en page et l'affichage des traductions en persan et RTL
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m30s

- Prioriser les polices couvrant l'alphabet latin et arabo-persan (DejaVu Sans, Arial) afin d'eviter les debordements et caracteres manquants

- Decouper et mettre en miroir le texte ligne par ligne pour preserver l'ordre vertical de lecture du haut vers le bas

- Ignorer les fonds de diapositives pleine page pour eviter de tronconner les phrases sur fond colore

- Supporter les listes avec alinea pour fusionner les phrases longues sans coupure de mots

- Ajouter fonts-dejavu-core au conteneur Docker de production
This commit is contained in:
2026-09-02 21:22:22 +02:00
parent f93b13b53f
commit cae09fc512
3 changed files with 163 additions and 29 deletions

View File

@@ -1183,3 +1183,45 @@ class TestLtrNormalization:
assert "Helvetica" not in fonts, fonts
assert "?" not in text
assert any(0xFB50 <= ord(c) <= 0xFEFF for c in text)
@pytest.mark.skipif(_host_rtl_font() is None, reason="no Arabic-capable font on this host")
def test_rtl_multiline_order_preserved(self, tmp_path):
"""Multi-line RTL text must wrap lines top-to-bottom so the start
of the paragraph appears on the first line, not upside-down."""
import fitz
src = tmp_path / "src_multiline.pdf"
doc = fitz.open()
page = doc.new_page(width=300, height=200)
# Narrow box to force text into multiple lines
page.insert_textbox(
fitz.Rect(50, 50, 250, 150),
"1. Première étape d'installation avec des instructions détaillées.",
fontsize=12, fontname="helv",
)
doc.save(str(src))
doc.close()
fa_text = "1. مرحله اول نصب با دستورالعمل های دقیق و کامل برای ساعت هوشمند."
translator = PDFTranslator(
provider=MockTranslationProvider({
"1. Première étape d'installation avec des instructions détaillées.": fa_text
})
)
out = tmp_path / "out_multiline.pdf"
translator.translate_file(src, out, "fa")
doc2 = fitz.open(str(out))
page_dict = doc2[0].get_text("dict")
doc2.close()
lines = [
"".join(s["text"] for s in l["spans"])
for b in page_dict["blocks"] if "lines" in b
for l in b["lines"]
]
assert len(lines) >= 2
# The number '1.' and start of text must appear on the FIRST line
assert "1." in lines[0] or "1" in lines[0]
# Must not contain overflow marker
assert "[translation overflow]" not in " ".join(lines)