""" PowerPoint Translation Module Translates PowerPoint files while preserving all layouts, animations, and media """ from pathlib import Path from pptx import Presentation from pptx.shapes.base import BaseShape from pptx.shapes.group import GroupShape from pptx.util import Inches, Pt from pptx.enum.shapes import MSO_SHAPE_TYPE from services.translation_service import translation_service class PowerPointTranslator: """Handles translation of PowerPoint presentations with strict formatting preservation""" def __init__(self): self.translation_service = translation_service def translate_file(self, input_path: Path, output_path: Path, target_language: str) -> Path: """ Translate a PowerPoint presentation while preserving all formatting and structure Args: input_path: Path to input PowerPoint file output_path: Path to save translated PowerPoint file target_language: Target language code Returns: Path to the translated file """ presentation = Presentation(input_path) # Translate each slide for slide in presentation.slides: self._translate_slide(slide, target_language) # Save the translated presentation presentation.save(output_path) return output_path def _translate_slide(self, slide, target_language: str): """ Translate all text elements in a slide while preserving layout Args: slide: Slide to translate target_language: Target language code """ # Translate notes (speaker notes) if slide.has_notes_slide: notes_slide = slide.notes_slide if notes_slide.notes_text_frame: self._translate_text_frame(notes_slide.notes_text_frame, target_language) # Translate shapes in the slide for shape in slide.shapes: self._translate_shape(shape, target_language) def _translate_shape(self, shape: BaseShape, target_language: str): """ Translate text in a shape based on its type Args: shape: Shape to translate target_language: Target language code """ # Handle text-containing shapes if shape.has_text_frame: self._translate_text_frame(shape.text_frame, target_language) # Handle tables if shape.shape_type == MSO_SHAPE_TYPE.TABLE: self._translate_table(shape.table, target_language) # Handle group shapes (shapes within shapes) if shape.shape_type == MSO_SHAPE_TYPE.GROUP: for sub_shape in shape.shapes: self._translate_shape(sub_shape, target_language) # Handle smart art (contains multiple shapes) # Smart art is complex, but we can try to translate text within it if hasattr(shape, 'shapes'): try: for sub_shape in shape.shapes: self._translate_shape(sub_shape, target_language) except: pass # Some shapes may not support iteration def _translate_text_frame(self, text_frame, target_language: str): """ Translate text within a text frame while preserving formatting Args: text_frame: Text frame to translate target_language: Target language code """ if not text_frame.text.strip(): return # Translate each paragraph in the text frame for paragraph in text_frame.paragraphs: self._translate_paragraph(paragraph, target_language) def _translate_paragraph(self, paragraph, target_language: str): """ Translate a paragraph while preserving run-level formatting Args: paragraph: Paragraph to translate target_language: Target language code """ if not paragraph.text.strip(): return # Translate each run in the paragraph to preserve individual formatting for run in paragraph.runs: if run.text.strip(): translated_text = self.translation_service.translate_text( run.text, target_language ) run.text = translated_text def _translate_table(self, table, target_language: str): """ Translate all cells in a table while preserving structure Args: table: Table to translate target_language: Target language code """ for row in table.rows: for cell in row.cells: self._translate_text_frame(cell.text_frame, target_language) def _is_translatable(self, text: str) -> bool: """ Determine if text should be translated Args: text: Text to check Returns: True if text should be translated, False otherwise """ if not text or not isinstance(text, str): return False # Don't translate if it's only numbers, special characters, or very short if len(text.strip()) < 2: return False return True # Global translator instance pptx_translator = PowerPointTranslator()