Building a PDF Document Translator with Python and Large Language Models

Market Context and Motivation

Translation remains a persistent requirement across industries. While human-based translation provides quality, it involves considerable expense and time. Large language models offer a competitive alternative—faster, more scalable, and increasingly accurate. However, conventional online translation tools typically demand uploading entire files, which introduces potential privacy risks when handling confidential documents.

Approaches that mitigate exposure include:

  • Using GPT via API, where documents are split into segments and streamed, avoiding full file uploads.
  • Relying on OpenAI’s contractual data handling policies.
  • Deploying private, self-hosted models for end-to-end control over sensitive content.

Product Scope and Feature Planning

The initial release (v1.0) focuses on core capabilities:

  • Parsing PDF files to extract text and tables.
  • Translating English content into Chinese.
  • Integrating OpenAI and ChatGLM backends.
  • Configuration through YAML files or command-line arguments.
  • Modular, object-oriented code design for extensibility.

A subsequent iteration (v2.0) will extend functionality:

  • Adding a graphical user interface for broader accessibility.
  • Preserving the original PDF layout after translation.
  • Exposing translation as an API service.
  • Supporting additional language pairs.

Technical Design and PDF Processing

Architectural Overview

The system follows a pipeline architecture: document ingestion, processing with pdfplumber, content segmentation, translation via model APIs, and optional reassembly. Loose coupling between components makes it straightforward to swap models or output formats.

Working with pdfplumber

The pdfplumber library, built on pdfminer.six, excels at extracting text, tables, and visual elements from machine-generated PDFs. It provides detailed access to characters, rectangles, lines, and curves, along with utilities for visual debugging. It requires Python 3.8 through 3.11 and is not suitable for scanned image-based PDFs.

Opening a PDF File

Call pdfplumber.open(source) where source can be a file path, a bytes object, or a file-like object. The call returns an instance of pdfplumber.PDF.

Advanced options include password for encrypted files and laparams to tune layout analysis, e.g., pdfplumber.open("doc.pdf", password="secret", laparams={"line_overlap": 0.7}).

The PDF and Page Objects

pdfplumber.PDF represents the whole document, with key members:

import pdfplumber

with pdfplumber.open("sample.pdf") as doc:
    print(doc.metadata)
    first_page = doc.pages[0]
    print(type(first_page))  # <class 'pdfplumber.page.Page'>

A pdfplumber.Page holds content properties such as page_number, width, and height, and exposes methods for extraction and visualization.

page = doc.pages[0]
print(f"Page dimensions: {page.width}, {page.height}")
image = page.to_image()

Extracting Text from a Page

The extract_text() method combines all character objects into a single string. Parameters x_tolerance and y_tolerance govern when spaces and line breaks are inserted. Setting layout=True attempts to mirror the visual layout using x_density and y_density to decide spacing.

text_flow = page.extract_text(layout=False)
structured_text = page.extract_text(layout=True)

Additional methods include extract_text_simple() for faster, less configurable results and extract_words() to retrieve words with bounding box data, configurable for text flow direction, blank character handling, and ligature expansion.

words = page.extract_words(
    keep_blank_chars=False,
    use_text_flow=True,
    extra_attrs=["fontname", "size"]
)

The experimental search() method supports regex or literal pattern matching across the page, returning match details with coordinates and character data.

Handling Tables in PDFs

pdfplumber's table extraction detects explicit lines and implicit alignments, merges overlapping edges, finds intersections, and constructs cell grids. Cells are grouped into tables.

Key methods on pdfplumber.Page include:

  • find_tables() — returns a list of Table objects with .cells, .rows, .bbox, and an .extract() method.
  • find_table() — returns the largest table on the page.
  • extract_tables() — returns nested list [table][row][cell] of text.
  • extract_table() — returns [row][cell] text for the largest table.

Example usage:

all_tables = page.extract_tables()
largest_table_data = page.extract_table()

import pandas as pd

headers = largest_table_data[0]
rows_data = largest_table_data[1:]
df = pd.DataFrame(rows_data, columns=headers)
print(df.head())

Visual Debugging and Image Handling

The .to_image() method creates a PageImage instance, configurable with resolution, width, height, and antialias.

# Render with higher resolution and anti-aliasing
rendered = page.to_image(resolution=150, antialias=True)

To handle embedded images, access the .images property of a page. Each entry contains position and size information. Crop the page to an image's bounding box, then render and save:

embedded_img = page.images[0]
bbox = (embedded_img["x0"], embedded_img["top"], embedded_img["x1"], embedded_img["bottom"])
cropped = page.crop(bbox)
final_image = cropped.to_image(antialias=True)
final_image.save("extracted_figure.png")

Page cropping and filtering methods (crop, within_bbox, outside_bbox, filter) enable precise content selection before extraction.

Module Organization

The translator is organized into distinct Python modules:

  • reader: wraps pdfplumber for text and table extraction.
  • translator: encapsulates API communication with OpenAI and ChatGLM.
  • config: handles YAML and CLI parsing.
  • pipeline: orchestrates reading, splitting, translating, and output assembly.

This separation enables independent testing and straightforward extension with new backends or output formats.

Tags: pdfplumber python OpenAI PDF Translation LLM

Posted on Sat, 24 Oct 2026 16:04:02 +0000 by netbros