ترجمه فایل PDF با هوش مصنوعی؛ معرفی ابزارها و ساخت مترجم PDF فارسی

در این آموزش با بهترین روش‌ها و ابزارهای ترجمه فایل PDF با هوش مصنوعی آشنا می‌شوید و یک مترجم PDF فارسی واقعی می‌سازید که متن سند را استخراج، بخش‌بندی و با API درواره ترجمه می‌کند. کد کامل Python و FastAPI، پشتیبانی از PDF اسکن‌شده، واژه‌نامه تخصصی و تولید خروجی Word یا PDF نیز ارائه شده است.

Share
ترجمه فایل PDF با هوش مصنوعی؛ معرفی ابزارها و ساخت مترجم PDF فارسی

ترجمه فایل PDF با هوش مصنوعی دیگر به کپی‌کردن دستی متن هر صفحه نیاز ندارد. ابزارهای جدید می‌توانند فایل‌های چندصفحه‌ای را دریافت و محتوای آن‌ها را به فارسی یا زبان‌های دیگر ترجمه کنند.

بااین‌حال، ترجمه PDF فقط تبدیل جمله‌های انگلیسی به فارسی نیست. یک ابزار مناسب باید بتواند:

  • متن را به‌ترتیب صحیح از PDF استخراج کند.
  • عنوان‌ها و پاراگراف‌ها را تشخیص دهد.
  • شماره صفحه را حفظ کند.
  • اصطلاحات تخصصی را یکسان ترجمه کند.
  • اعداد، نام‌ها، کدها و فرمول‌ها را تغییر ندهد.
  • فایل‌های طولانی را در چند مرحله پردازش کند.
  • PDF اسکن‌شده را با OCR بخواند.
  • خروجی Word یا PDF راست‌چین تولید کند.
  • جداول و فهرست‌ها را تا حد ممکن حفظ کند.

در این مقاله ابتدا ابزارهای ترجمه PDF را بررسی می‌کنیم و سپس یک برنامه کامل با Python، FastAPI، PyMuPDF و API درواره می‌سازیم.

ترجمه PDF با هوش مصنوعی چگونه انجام می‌شود؟

جریان کلی ترجمه یک فایل PDF متنی به این صورت است:

بارگذاری فایل PDF
        ↓
تشخیص متنی یا اسکن‌شده بودن
        ↓
استخراج متن هر صفحه
        ↓
تشخیص پاراگراف‌ها و بلوک‌ها
        ↓
بخش‌بندی متن طولانی
        ↓
ترجمه با مدل هوش مصنوعی
        ↓
اعمال واژه‌نامه تخصصی
        ↓
ساخت سند راست‌چین
        ↓
خروجی DOCX یا PDF

اگر فایل فقط شامل تصویر صفحات باشد، یک مرحله OCR نیز به فرایند اضافه می‌شود.

تفاوت ترجمه PDF متنی و PDF اسکن‌شده

PDF متنی

در PDF متنی، نوشته‌ها به‌صورت کاراکتر ذخیره شده‌اند. کاربر می‌تواند متن را انتخاب و کپی کند.

برای این نوع فایل معمولاً ابزارهایی مانند PyMuPDF، pypdf یا pdfplumber کافی هستند.

PDF اسکن‌شده

در PDF اسکن‌شده، هر صفحه یک تصویر است. متن قابل انتخاب نیست و باید ابتدا با OCR شناسایی شود.

ابزارهای مناسب:

  • Tesseract OCR
  • OCRmyPDF
  • PaddleOCR
  • EasyOCR
  • Docling
  • مدل‌های بینایی و تحلیل سند

PDF ترکیبی

بعضی صفحات متن واقعی دارند و بعضی دیگر تصویر اسکن‌شده‌اند. برنامه باید هر صفحه را جداگانه بررسی کند و فقط صفحات بدون متن را به OCR بفرستد.

بهترین ابزارهای ترجمه PDF با هوش مصنوعی

Google Translate

Google Translate امکان بارگذاری و ترجمه بعضی انواع سند را ارائه می‌کند. این روش برای ترجمه سریع اسناد عمومی مناسب است، اما کنترل محدودی روی واژه‌نامه و ساختار خروجی دارد.

DeepL

DeepL از ترجمه فایل در بعضی قالب‌ها پشتیبانی می‌کند و برای برخی زبان‌ها کیفیت مناسبی دارد. پشتیبانی زبان، حجم فایل و امکانات نسخه رایگان یا پولی باید در زمان استفاده بررسی شوند.

Adobe Acrobat

Adobe Acrobat ابزارهایی برای پردازش، تبدیل و کار با فایل‌های PDF دارد. قابلیت‌های ترجمه ممکن است بر اساس نسخه، حساب و سرویس‌های متصل متفاوت باشند.

مدل‌های زبانی عمومی

مدل‌های زبانی می‌توانند متن استخراج‌شده را با درنظرگرفتن موضوع، لحن، واژه‌نامه و ساختار سند ترجمه کنند. برای فایل‌های طولانی باید بخش‌بندی و مدیریت Context انجام شود.

LibreTranslate

LibreTranslate یک API متن‌باز ترجمه ماشینی است که امکان استقرار روی سرور شخصی را دارد. این ابزار برای ترجمه متنی و پروژه‌های نیازمند سرویس مستقل قابل بررسی است. مخزن رسمی LibreTranslate

Argos Translate

Argos Translate یک کتابخانه متن‌باز ترجمه آفلاین است. کیفیت ترجمه به مدل زبانی موجود برای جفت‌زبان موردنظر بستگی دارد.

PyMuPDF

PyMuPDF برای استخراج متن، بلوک‌های متنی، تصویر و اطلاعات صفحه استفاده می‌شود. این کتابخانه امکان دریافت متن معمولی یا بلوک‌های دارای مختصات را فراهم می‌کند. مستندات PyMuPDF

Docling

Docling برای تبدیل اسناد پیچیده به ساختار قابل پردازش طراحی شده است. در اسناد دارای عنوان، جدول، ستون‌بندی و عناصر مختلف می‌تواند از استخراج متن ساده مناسب‌تر باشد.

مزیت ساخت مترجم PDF اختصاصی

ابزار آماده برای استفاده شخصی مناسب است؛ اما محصول اختصاصی امکانات بیشتری فراهم می‌کند:

  • انتخاب آزاد مدل ترجمه
  • خروجی کاملاً فارسی و راست‌چین
  • واژه‌نامه اختصاصی هر صنعت
  • ترجمه گروهی اسناد
  • اتصال به سایت یا نرم‌افزار
  • ثبت وضعیت پردازش
  • پشتیبانی از چند قالب خروجی
  • امکان بازبینی ترجمه
  • استفاده از چند مدل برای مقایسه
  • محاسبه هزینه هر سند
  • ارائه سرویس ترجمه به مشتریان

چرا از API درواره استفاده کنیم؟

درواره یک API یکپارچه و سازگار با OpenAI برای دسترسی به مدل‌های مختلف فراهم می‌کند.

آدرس پایه:

https://api.darvareh.ir/v1

در برنامه، شناسه مدل از متغیر محیطی خوانده می‌شود. بنابراین می‌توان چند مدل را روی فایل‌های واقعی مقایسه و مدل مناسب ترجمه فارسی را انتخاب کرد.

معیارهای مقایسه:

  • کیفیت ترجمه فارسی
  • حفظ ساختار جمله
  • ترجمه درست اصطلاحات
  • حفظ نام‌ها و اعداد
  • سرعت پاسخ
  • ظرفیت Context
  • هزینه پردازش
  • ثبات ترجمه در صفحات مختلف

معماری مترجم PDF

کاربر
  ↓
Frontend
  ↓
FastAPI
  ↓
استخراج متن با PyMuPDF
  ↓
تقسیم متن به صفحه و Chunk
  ↓
ترجمه با API درواره
  ↓
ساخت فایل DOCX راست‌چین
  ↓
تبدیل اختیاری DOCX به PDF
  ↓
دانلود فایل ترجمه‌شده

کلید API فقط در Backend قرار می‌گیرد و به مرورگر کاربر ارسال نمی‌شود.

محدودیت حفظ ظاهر PDF

PDF قالبی با موقعیت ثابت است. متن انگلیسی و ترجمه فارسی معمولاً طول، جهت و شکست خط متفاوتی دارند. بنابراین حفظ دقیق و پیکسلی ظاهر فایل همیشه ممکن نیست.

سه سطح خروجی وجود دارد:

روشمیزان حفظ ظاهر
استخراج متن و ساخت سند جدیدکم تا متوسط
بازسازی بر اساس بلوک‌های صفحهمتوسط
ترجمه و جایگزینی متن در مختصات اصلیبیشتر، اما پیچیده
استفاده از ساختار سند اصلی مانند DOCXمعمولاً بهتر

در این آموزش صفحه‌بندی اصلی حفظ می‌شود، اما خروجی با قالب خوانا و راست‌چین بازسازی خواهد شد. هدف، ترجمه دقیق و قابل ویرایش است، نه کپی کامل طراحی PDF.

ساخت پروژه Python

ساختار پروژه:

pdf-ai-translator/
├── app.py
├── requirements.txt
├── .env
└── outputs/

نصب وابستگی‌ها

فایل requirements.txt:

fastapi
uvicorn[standard]
python-multipart
pymupdf
openai
python-docx
python-dotenv

ساخت محیط مجازی:

python -m venv .venv

فعال‌سازی در Linux یا macOS:

source .venv/bin/activate

فعال‌سازی در Windows:

.venv\Scripts\activate

نصب کتابخانه‌ها:

pip install -r requirements.txt

نصب LibreOffice برای خروجی PDF

برنامه ابتدا فایل DOCX می‌سازد. برای تبدیل خودکار آن به PDF می‌توان LibreOffice را روی سرور نصب کرد.

در Ubuntu یا Debian:

sudo apt update
sudo apt install libreoffice

برای نمایش صحیح فارسی، فونت مناسب مانند Vazirmatn نیز باید روی سیستم نصب شود.

اگر LibreOffice نصب نباشد، همچنان می‌توان خروجی DOCX دریافت و آن را با Word یا LibreOffice به PDF تبدیل کرد.

تنظیم متغیرهای محیطی

فایل .env:

DARVAREH_API_KEY=YOUR_API_KEY
DARVAREH_MODEL=YOUR_MODEL_ID
DARVAREH_BASE_URL=https://api.darvareh.ir/v1
MAX_FILE_SIZE_MB=25

مدل را از فهرست فعلی مدل‌های درواره انتخاب کنید.

کد کامل مترجم PDF

فایل app.py:

import os
import re
import shutil
import subprocess
import tempfile
from pathlib import Path
from typing import Literal

import fitz
from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Pt
from dotenv import load_dotenv
from fastapi import FastAPI, File, Form, HTTPException, UploadFile
from fastapi.responses import FileResponse
from openai import OpenAI
from starlette.background import BackgroundTask


load_dotenv()

DARVAREH_API_KEY = os.environ["DARVAREH_API_KEY"]
DARVAREH_MODEL = os.environ["DARVAREH_MODEL"]
DARVAREH_BASE_URL = os.getenv(
    "DARVAREH_BASE_URL",
    "https://api.darvareh.ir/v1",
)

MAX_FILE_SIZE = (
    int(os.getenv("MAX_FILE_SIZE_MB", "25"))
    * 1024
    * 1024
)

MAX_CHUNK_CHARACTERS = 7000

app = FastAPI(
    title="Persian PDF AI Translator",
    version="1.0.0",
)

client = OpenAI(
    api_key=DARVAREH_API_KEY,
    base_url=DARVAREH_BASE_URL,
)


def normalize_text(text: str) -> str:
    """پاک‌سازی فاصله‌های غیرضروری."""
    text = text.replace("\u00ad", "")
    text = text.replace("\u200f", "")
    text = text.replace("\u202a", "")
    text = text.replace("\u202b", "")
    text = re.sub(r"[ \t]+", " ", text)
    text = re.sub(r"\n{3,}", "\n\n", text)

    return text.strip()


def extract_pdf_pages(
    pdf_bytes: bytes,
) -> list[dict]:
    """استخراج بلوک‌های متنی هر صفحه."""
    try:
        pdf_document = fitz.open(
            stream=pdf_bytes,
            filetype="pdf",
        )
    except Exception as error:
        raise ValueError(
            "فایل PDF قابل خواندن نیست."
        ) from error

    pages = []

    for page_index, page in enumerate(pdf_document):
        blocks = page.get_text(
            "blocks",
            sort=True,
        )

        page_blocks = []

        for block in blocks:
            block_text = normalize_text(block[4])

            if not block_text:
                continue

            page_blocks.append(block_text)

        pages.append(
            {
                "page_number": page_index + 1,
                "blocks": page_blocks,
            }
        )

    pdf_document.close()

    total_text_length = sum(
        len(block)
        for page in pages
        for block in page["blocks"]
    )

    if total_text_length < 20:
        raise ValueError(
            "متن قابل استفاده‌ای از PDF استخراج نشد. "
            "احتمالاً فایل اسکن‌شده است و به OCR نیاز دارد."
        )

    return pages


def split_long_text(
    text: str,
    max_characters: int = MAX_CHUNK_CHARACTERS,
) -> list[str]:
    """تقسیم متن طولانی با اولویت مرز پاراگراف."""
    if len(text) <= max_characters:
        return [text]

    paragraphs = [
        paragraph.strip()
        for paragraph in text.split("\n")
        if paragraph.strip()
    ]

    chunks = []
    current_parts = []
    current_length = 0

    for paragraph in paragraphs:
        if len(paragraph) > max_characters:
            sentences = re.split(
                r"(?<=[.!?؟])\s+",
                paragraph,
            )
        else:
            sentences = [paragraph]

        for part in sentences:
            if (
                current_parts
                and current_length + len(part)
                > max_characters
            ):
                chunks.append(
                    "\n".join(current_parts)
                )

                current_parts = []
                current_length = 0

            current_parts.append(part)
            current_length += len(part) + 1

    if current_parts:
        chunks.append(
            "\n".join(current_parts)
        )

    return chunks


def translate_chunk(
    text: str,
    source_language: str,
    target_language: str,
    glossary: str,
) -> str:
    """ترجمه یک قسمت متن با مدل انتخاب‌شده."""
    glossary_instruction = (
        glossary.strip()
        if glossary.strip()
        else "واژه‌نامه‌ای ارائه نشده است."
    )

    user_prompt = f"""
متن زیر را از زبان {source_language} به زبان
{target_language} ترجمه کن.

متن:
{text}

واژه‌نامه و دستورهای اختصاصی:
{glossary_instruction}

قواعد:
- فقط ترجمه نهایی را برگردان.
- هیچ مقدمه، توضیح یا Markdown اضافه نکن.
- معنی متن را دقیق حفظ کن.
- نام اشخاص، شرکت‌ها و محصولات را با دقت نگه دار.
- اعداد، تاریخ‌ها، واحدها، URLها، ایمیل‌ها و کدها را تغییر نده.
- عنوان‌ها، پاراگراف‌ها و فهرست‌ها را تا حد امکان حفظ کن.
- اصطلاحات موجود در واژه‌نامه را دقیقاً مطابق آن ترجمه کن.
- اگر عبارتی نباید ترجمه شود، همان شکل اصلی را حفظ کن.
"""

    completion = client.chat.completions.create(
        model=DARVAREH_MODEL,
        messages=[
            {
                "role": "system",
                "content": (
                    "شما مترجم حرفه‌ای اسناد هستید و "
                    "ترجمه‌ای دقیق، طبیعی و یکدست تولید می‌کنید."
                ),
            },
            {
                "role": "user",
                "content": user_prompt,
            },
        ],
    )

    content = completion.choices[0].message.content

    if not content:
        raise ValueError(
            "مدل پاسخ ترجمه معتبری برنگرداند."
        )

    return content.strip()


def translate_pages(
    pages: list[dict],
    source_language: str,
    target_language: str,
    glossary: str,
) -> list[dict]:
    """ترجمه تمام صفحات سند."""
    translated_pages = []

    for page in pages:
        source_text = "\n\n".join(
            page["blocks"]
        )

        if not source_text.strip():
            translated_pages.append(
                {
                    "page_number": page["page_number"],
                    "text": "",
                }
            )
            continue

        chunks = split_long_text(source_text)

        translated_chunks = [
            translate_chunk(
                text=chunk,
                source_language=source_language,
                target_language=target_language,
                glossary=glossary,
            )
            for chunk in chunks
        ]

        translated_pages.append(
            {
                "page_number": page["page_number"],
                "text": "\n\n".join(
                    translated_chunks
                ),
            }
        )

    return translated_pages


def set_paragraph_rtl(paragraph) -> None:
    """فعال‌کردن جهت راست‌به‌چپ در DOCX."""
    paragraph.alignment = (
        WD_ALIGN_PARAGRAPH.RIGHT
    )

    paragraph_properties = (
        paragraph._p.get_or_add_pPr()
    )

    bidi = OxmlElement("w:bidi")
    paragraph_properties.append(bidi)


def configure_run_font(
    run,
    font_name: str = "Vazirmatn",
    font_size: int = 11,
    rtl: bool = True,
) -> None:
    """تنظیم فونت فارسی و جهت Run."""
    run.font.name = font_name
    run.font.size = Pt(font_size)

    run_properties = (
        run._element.get_or_add_rPr()
    )

    fonts = run_properties.rFonts

    if fonts is None:
        fonts = OxmlElement("w:rFonts")
        run_properties.insert(0, fonts)

    fonts.set(qn("w:ascii"), font_name)
    fonts.set(qn("w:hAnsi"), font_name)
    fonts.set(qn("w:cs"), font_name)

    if rtl:
        rtl_element = OxmlElement("w:rtl")
        run_properties.append(rtl_element)


def create_docx(
    translated_pages: list[dict],
    output_path: Path,
    target_language: str,
) -> None:
    """ساخت فایل Word از صفحات ترجمه‌شده."""
    document = Document()
    is_rtl = target_language.lower() in {
        "fa",
        "persian",
        "farsi",
        "ar",
        "arabic",
        "he",
        "hebrew",
        "ur",
        "urdu",
    }

    for page_index, page in enumerate(
        translated_pages
    ):
        paragraphs = [
            text.strip()
            for text in page["text"].split("\n\n")
            if text.strip()
        ]

        for paragraph_text in paragraphs:
            paragraph = document.add_paragraph()

            if is_rtl:
                set_paragraph_rtl(paragraph)

            run = paragraph.add_run(
                paragraph_text
            )

            configure_run_font(
                run=run,
                font_name=(
                    "Vazirmatn"
                    if is_rtl
                    else "Arial"
                ),
                font_size=11,
                rtl=is_rtl,
            )

        if page_index < len(translated_pages) - 1:
            document.add_page_break()

    document.save(output_path)


def find_libreoffice() -> str | None:
    """پیداکردن فایل اجرایی LibreOffice."""
    return (
        shutil.which("libreoffice")
        or shutil.which("soffice")
    )


def convert_docx_to_pdf(
    docx_path: Path,
    output_directory: Path,
) -> Path:
    """تبدیل DOCX به PDF با LibreOffice."""
    libreoffice = find_libreoffice()

    if not libreoffice:
        raise RuntimeError(
            "LibreOffice روی سرور نصب نیست. "
            "خروجی DOCX را انتخاب کنید."
        )

    result = subprocess.run(
        [
            libreoffice,
            "--headless",
            "--convert-to",
            "pdf",
            "--outdir",
            str(output_directory),
            str(docx_path),
        ],
        capture_output=True,
        text=True,
        timeout=180,
        check=False,
    )

    pdf_path = (
        output_directory
        / f"{docx_path.stem}.pdf"
    )

    if (
        result.returncode != 0
        or not pdf_path.exists()
    ):
        raise RuntimeError(
            "تبدیل فایل Word به PDF ناموفق بود."
        )

    return pdf_path


def cleanup_directory(
    directory_path: str,
) -> None:
    """حذف فایل‌های موقت پس از دانلود."""
    shutil.rmtree(
        directory_path,
        ignore_errors=True,
    )


@app.get("/health")
def health():
    return {
        "status": "ok",
        "model": DARVAREH_MODEL,
        "pdf_output": bool(find_libreoffice()),
    }


@app.post("/api/translate-pdf")
async def translate_pdf(
    file: UploadFile = File(...),
    source_language: str = Form("auto"),
    target_language: str = Form("Persian"),
    glossary: str = Form(""),
    output_format: Literal["docx", "pdf"] = Form(
        "docx"
    ),
):
    filename = file.filename or "document.pdf"

    if not filename.lower().endswith(".pdf"):
        raise HTTPException(
            status_code=400,
            detail="فقط فایل PDF قابل قبول است.",
        )

    pdf_bytes = await file.read()

    if not pdf_bytes:
        raise HTTPException(
            status_code=400,
            detail="فایل خالی است.",
        )

    if len(pdf_bytes) > MAX_FILE_SIZE:
        raise HTTPException(
            status_code=413,
            detail="حجم فایل بیشتر از حد مجاز است.",
        )

    if not pdf_bytes.startswith(b"%PDF"):
        raise HTTPException(
            status_code=400,
            detail="ساختار فایل PDF معتبر نیست.",
        )

    try:
        pages = extract_pdf_pages(pdf_bytes)

        translated_pages = translate_pages(
            pages=pages,
            source_language=source_language,
            target_language=target_language,
            glossary=glossary,
        )

    except ValueError as error:
        raise HTTPException(
            status_code=422,
            detail=str(error),
        ) from error

    except Exception as error:
        raise HTTPException(
            status_code=502,
            detail=f"ترجمه فایل ناموفق بود: {error}",
        ) from error

    temporary_directory = Path(
        tempfile.mkdtemp(
            prefix="pdf-translator-"
        )
    )

    safe_stem = re.sub(
        r"[^A-Za-z0-9_-]+",
        "-",
        Path(filename).stem,
    ).strip("-") or "translated-document"

    docx_path = (
        temporary_directory
        / f"{safe_stem}-translated.docx"
    )

    try:
        create_docx(
            translated_pages=translated_pages,
            output_path=docx_path,
            target_language=target_language,
        )

        if output_format == "pdf":
            output_path = convert_docx_to_pdf(
                docx_path=docx_path,
                output_directory=temporary_directory,
            )

            media_type = "application/pdf"
        else:
            output_path = docx_path

            media_type = (
                "application/vnd.openxmlformats-"
                "officedocument.wordprocessingml.document"
            )

    except Exception as error:
        cleanup_directory(
            str(temporary_directory)
        )

        raise HTTPException(
            status_code=500,
            detail=f"ساخت فایل خروجی ناموفق بود: {error}",
        ) from error

    return FileResponse(
        path=output_path,
        filename=output_path.name,
        media_type=media_type,
        background=BackgroundTask(
            cleanup_directory,
            str(temporary_directory),
        ),
    )

اجرای API

دستور زیر را اجرا کنید:

uvicorn app:app --reload

آدرس مستندات:

http://127.0.0.1:8000/docs

در این صفحه می‌توانید:

  • فایل PDF را انتخاب کنید.
  • زبان مبدأ را تعیین کنید.
  • زبان مقصد را وارد کنید.
  • واژه‌نامه تخصصی بنویسید.
  • فرمت DOCX یا PDF را انتخاب کنید.
  • فایل ترجمه‌شده را دانلود کنید.

آزمایش با curl

خروجی DOCX:

curl -X POST \
  "http://127.0.0.1:8000/api/translate-pdf" \
  -F "file=@document.pdf" \
  -F "source_language=English" \
  -F "target_language=Persian" \
  -F "output_format=docx" \
  -F "glossary=Embedding را امبدینگ ترجمه کن." \
  --output translated.docx

خروجی PDF:

curl -X POST \
  "http://127.0.0.1:8000/api/translate-pdf" \
  -F "file=@document.pdf" \
  -F "source_language=English" \
  -F "target_language=Persian" \
  -F "output_format=pdf" \
  --output translated.pdf

ساخت واژه‌نامه تخصصی

یکی از مشکلات ترجمه فایل‌های طولانی، ترجمه متفاوت یک اصطلاح در صفحات مختلف است.

برای جلوگیری از این مشکل، واژه‌نامه را همراه تمام درخواست‌ها ارسال کنید:

Artificial Intelligence = هوش مصنوعی
Machine Learning = یادگیری ماشین
Embedding = امبدینگ
Fine-tuning = فاین‌تیونینگ
Prompt = پرامپت
Token = توکن
OpenAI = ترجمه نشود
API = API

در یک محصول واقعی، واژه‌نامه می‌تواند در پایگاه داده ذخیره و برای هر پروژه انتخاب شود.

ساختار پیشنهادی:

{
  "project_id": "project-123",
  "terms": [
    {
      "source": "Large Language Model",
      "target": "مدل زبانی بزرگ",
      "case_sensitive": false
    },
    {
      "source": "Darvareh",
      "target": "درواره",
      "case_sensitive": true
    }
  ]
}

حفظ نام‌ها، اعداد و کدها

پرامپت ترجمه باید مشخص کند که موارد زیر تغییر نکنند:

  • URL
  • آدرس ایمیل
  • شماره نسخه
  • شناسه محصول
  • قطعه‌کد
  • فرمول
  • نام مدل
  • نام شرکت
  • متغیرهای برنامه‌نویسی
  • واحدهای اندازه‌گیری
  • ارجاع‌های مقاله

برای اسناد فنی می‌توان قبل از ترجمه، این عناصر را با Placeholder جایگزین کرد:

https://example.com → __URL_1__
gpt-model-id → __MODEL_ID_1__
user@example.com → __EMAIL_1__

پس از ترجمه، مقدار اصلی دوباره در متن قرار می‌گیرد. این روش احتمال تغییر ناخواسته کدها را کاهش می‌دهد.

پردازش PDF اسکن‌شده با OCR

اگر extract_pdf_pages() متن کافی پیدا نکند، برنامه خطای نیاز به OCR برمی‌گرداند.

برای OCR می‌توان از PyMuPDF و Tesseract استفاده کرد:

def extract_page_with_ocr(page) -> str:
    text_page = page.get_textpage_ocr(
        language="eng",
        dpi=300,
        full=True,
    )

    return page.get_text(
        "text",
        textpage=text_page,
    )

برای فارسی باید داده زبان فارسی Tesseract نصب شده باشد و مقدار زبان متناسب تنظیم شود.

در Ubuntu:

sudo apt install \
  tesseract-ocr \
  tesseract-ocr-eng \
  tesseract-ocr-fas

نمونه چندزبانه:

text_page = page.get_textpage_ocr(
    language="eng+fas",
    dpi=300,
)

PyMuPDF در مستندات خود امکان استفاده از get_textpage_ocr() برای صفحات تصویری را توضیح می‌دهد. راهنمای OCR در PyMuPDF

استفاده از OCRmyPDF

OCRmyPDF می‌تواند یک لایه متن قابل جست‌وجو به PDF اسکن‌شده اضافه کند.

نصب در Ubuntu:

sudo apt install ocrmypdf

اجرا:

ocrmypdf \
  -l eng+fas \
  scanned.pdf \
  searchable.pdf

پس از آن می‌توان searchable.pdf را با همان برنامه ترجمه کرد.

ترجمه جدول‌های PDF

استخراج جدول از PDF یکی از دشوارترین قسمت‌هاست. متن یک جدول ممکن است با ترتیب نامناسب استخراج شود.

ابزارهای قابل بررسی:

ابزارکاربرد
pdfplumberاستخراج متن و جدول
Camelotجدول‌های دارای خطوط مشخص
Tabulaاستخراج جدول از PDF
Doclingتحلیل ساختار سند
PaddleOCR PP-StructureOCR و تحلیل جدول
مدل بیناییدرک تصویری جدول و صفحه

برای جدول بهتر است:

  1. جدول جداگانه تشخیص داده شود.
  2. هر سلول مستقل ترجمه شود.
  3. عددها تغییر نکنند.
  4. سطر و ستون حفظ شوند.
  5. جدول با Word یا HTML بازسازی شود.

ترجمه فایل‌های بسیار طولانی

پردازش یک کتاب ۳۰۰ صفحه‌ای نباید در یک درخواست HTTP معمولی انجام شود.

معماری مناسب:

آپلود فایل
    ↓
ایجاد Job
    ↓
قرارگرفتن در صف
    ↓
استخراج متن
    ↓
ترجمه صفحه‌به‌صفحه
    ↓
ثبت میزان پیشرفت
    ↓
ساخت خروجی
    ↓
آماده‌شدن لینک دانلود

وضعیت‌های پیشنهادی:

uploaded
extracting
ocr
translating
formatting
completed
failed

پاسخ اولیه API:

{
  "job_id": "translation-7842",
  "status": "queued"
}

بررسی وضعیت:

GET /api/translation-jobs/translation-7842

خروجی:

{
  "status": "translating",
  "progress": 62,
  "completed_pages": 31,
  "total_pages": 50
}

ابزارهای مناسب صف:

  • Celery
  • RQ
  • Dramatiq
  • BullMQ
  • Redis
  • RabbitMQ

ذخیره نتیجه هر صفحه

ترجمه هر صفحه را بلافاصله ذخیره کنید. اگر ترجمه صفحه ۹۰ از یک سند ۱۰۰ صفحه‌ای با خطا مواجه شود، نباید صفحات قبلی دوباره ترجمه شوند.

ساختار پیشنهادی:

document_id
page_number
source_text_hash
source_text
translated_text
model_id
prompt_version
status
created_at

با هش متن مبدأ می‌توان تشخیص داد که یک صفحه قبلاً با همان محتوا ترجمه شده است.

مقایسه چند مدل ترجمه

برای انتخاب مدل مناسب، مجموعه آزمایشی بسازید:

  • متن عمومی
  • مقاله علمی
  • قرارداد
  • متن بازاریابی
  • مستندات فنی
  • جدول
  • متن دارای عدد و تاریخ
  • متن دارای نام محصول
  • متن محاوره‌ای
  • متن فارسی به انگلیسی

معیارهای ارزیابی:

معیارتوضیح
دقت معناییآیا مفهوم اصلی حفظ شده است؟
روانیآیا ترجمه طبیعی است؟
اصطلاحاتآیا واژه‌های تخصصی درست‌اند؟
ثباتآیا اصطلاح در تمام صفحات یکسان است؟
اعدادآیا اعداد و واحدها حفظ شده‌اند؟
ساختارآیا عنوان و فهرست باقی مانده‌اند؟
جهت متنآیا خروجی فارسی RTL است؟
سرعتزمان ترجمه هر صفحه چقدر است؟
هزینههزینه کل سند چقدر است؟

برای ارزیابی حرفه‌ای، مترجم انسانی باید بخشی از نتایج را بررسی کند.

انتخاب مدل متفاوت برای مراحل مختلف

همیشه لازم نیست تمام صفحات با قوی‌ترین مدل ترجمه شوند.

نمونه معماری:

MODEL_ROUTES = {
    "general": os.environ["FAST_TRANSLATION_MODEL"],
    "technical": os.environ["TECHNICAL_MODEL"],
    "review": os.environ["REVIEW_MODEL"],
}

فرایند:

  1. مدل سریع ترجمه اولیه را انجام می‌دهد.
  2. مدل دوم صفحات تخصصی یا مشکوک را بازبینی می‌کند.
  3. واژه‌نامه روی خروجی کنترل می‌شود.
  4. نمونه‌های انتخابی برای بررسی انسانی ارسال می‌شوند.

بازبینی خودکار ترجمه

می‌توان پس از ترجمه، یک مرحله کنترل کیفیت اضافه کرد.

پرامپت نمونه:

متن مبدأ و ترجمه فارسی را مقایسه کن.

موارد زیر را بررسی کن:
- حذف‌شدن جمله
- اضافه‌شدن اطلاعات جدید
- تغییر عدد یا تاریخ
- ترجمه نادرست اصطلاحات واژه‌نامه
- تغییر نام محصول
- جمله فارسی نامفهوم

فقط خطاهای احتمالی را به‌صورت JSON برگردان.

خروجی:

{
  "has_issue": true,
  "issues": [
    {
      "type": "number_changed",
      "source": "Version 4.2",
      "translation": "نسخه ۲.۴"
    }
  ]
}

حفظ ساختار با Markdown میانی

در اسناد ساختاریافته می‌توان ابتدا PDF را به Markdown تبدیل کرد:

PDF
 ↓
Markdown ساختاریافته
 ↓
ترجمه عنوان‌ها و پاراگراف‌ها
 ↓
تبدیل Markdown به DOCX یا PDF

مزیت Markdown:

  • عنوان‌ها مشخص‌اند.
  • فهرست‌ها حفظ می‌شوند.
  • جدول‌ها قابل تشخیص‌اند.
  • قطعه‌کدها جدا می‌مانند.
  • ترجمه ساختارمندتر می‌شود.

ابزارهایی مانند Marker و Docling برای این مسیر قابل بررسی‌اند.

ساخت رابط کاربری مترجم PDF

رابط مناسب می‌تواند شامل این گزینه‌ها باشد:

  • انتخاب فایل
  • نمایش تعداد صفحات
  • زبان مبدأ
  • زبان مقصد
  • انتخاب مدل
  • بارگذاری واژه‌نامه
  • انتخاب لحن ترجمه
  • انتخاب فرمت خروجی
  • وضعیت OCR
  • نوار پیشرفت
  • پیش‌نمایش چند صفحه
  • تأیید ترجمه
  • دانلود Word
  • دانلود PDF

حالت‌های ترجمه:

دقیق و تحت‌اللفظی
روان و طبیعی
دانشگاهی
فنی
حقوقی
بازاریابی
ساده‌سازی‌شده

لحن باید بر اساس نوع سند انتخاب شود و نباید معنی متن را تغییر دهد.

محاسبه هزینه ترجمه PDF

هزینه ترجمه به عوامل زیر بستگی دارد:

  • تعداد صفحات
  • میزان متن هر صفحه
  • مدل انتخاب‌شده
  • طول پرامپت
  • طول ترجمه
  • تعداد دفعات بازبینی
  • استفاده از OCR
  • ترجمه مجدد صفحات
  • تولید خروجی‌های چندزبانه

برای مدیریت هزینه:

  • متن تکراری Header و Footer را حذف کنید.
  • صفحات خالی را ارسال نکنید.
  • هر صفحه را فقط یک‌بار ترجمه کنید.
  • نتیجه‌ها را بر اساس هش متن Cache کنید.
  • واژه‌نامه را کوتاه و مرتبط نگه دارید.
  • مدل را متناسب با نوع سند انتخاب کنید.
  • بازبینی مدل دوم را فقط برای صفحات لازم اجرا کنید.
  • میزان مصرف هر سند را ثبت کنید.

برای جزئیات بیشتر مقاله محاسبه هزینه API هوش مصنوعی را مطالعه کنید.

خطاهای رایج ترجمه PDF

ارسال کل فایل PDF به مدل متنی

بیشتر مدل‌های متنی به متن استخراج‌شده نیاز دارند. فایل باید ابتدا پردازش شود.

تشخیص‌ندادن PDF اسکن‌شده

اگر صفحه تصویر باشد، استخراج متن معمولی خروجی خالی یا ناقص تولید می‌کند.

متن تکراری باید پیش از ترجمه تشخیص داده و فقط در جای لازم حفظ شود.

ترجمه جداگانۀ جمله‌های مرتبط

تقسیم بیش از حد متن باعث ازبین‌رفتن Context و ترجمه ناهماهنگ می‌شود.

Chunkهای بسیار بزرگ

ممکن است ظرفیت مدل یا محدودیت درخواست را پر کنند و کنترل خطا دشوار شود.

نداشتن واژه‌نامه

اصطلاح یکسان ممکن است در صفحات مختلف به چند شکل ترجمه شود.

تغییر عدد و نام

اعداد، نام مدل‌ها، شناسه‌ها و واحدها باید پس از ترجمه کنترل شوند.

انتظار حفظ صددرصدی طراحی

زبان فارسی جهت و طول متفاوتی دارد. حفظ کامل Layout به بازسازی حرفه‌ای صفحه نیاز دارد.

پردازش هم‌زمان تمام صفحات

این کار می‌تواند فشار زیادی به سرور و API وارد کند. از صف و محدودیت هم‌زمانی استفاده کنید.

بازنویسی به‌جای ترجمه

پرامپت باید مدل را به حفظ معنی و ساختار محدود کند.

مسیر توسعه محصول

مرحله اول: PDF متنی ساده

استخراج صفحه‌به‌صفحه و تولید فایل Word.

مرحله دوم: واژه‌نامه

امکان ثبت اصطلاحات ترجمه‌شده و ترجمه‌نشده اضافه شود.

مرحله سوم: خروجی PDF

LibreOffice یا موتور ساخت PDF به برنامه متصل شود.

مرحله چهارم: OCR

فایل‌های اسکن‌شده شناسایی و پردازش شوند.

مرحله پنجم: پردازش پس‌زمینه

اسناد طولانی در صف قرار گیرند.

مرحله ششم: حفظ جدول و ساختار

استخراج مبتنی بر Layout و Markdown اضافه شود.

مرحله هفتم: بازبینی ترجمه

کنترل اعداد، نام‌ها و واژه‌نامه به‌صورت خودکار انجام شود.

مرحله هشتم: حساب کاربری

تعداد صفحات، هزینه، وضعیت و فایل‌های هر کاربر ثبت شود.

مرحله نهم: مقایسه مدل‌ها

کیفیت و هزینه مدل‌های مختلف درواره روی اسناد واقعی ارزیابی شود.

ایده‌های کسب‌وکاری

  • مترجم PDF انگلیسی به فارسی
  • ترجمه مقالات دانشگاهی
  • ترجمه کاتالوگ محصول
  • ترجمه دفترچه راهنما
  • ترجمه مستندات فنی
  • ترجمه گروهی اسناد شرکت
  • ترجمه کتاب الکترونیکی
  • ترجمه رزومه و مدارک
  • ترجمه چندزبانه فایل‌های آموزشی
  • افزونه ترجمه برای سامانه مدیریت اسناد
  • سرویس API ترجمه اسناد
  • پنل ترجمه و بازبینی تیمی

پرسش‌های متداول

چگونه فایل PDF را با هوش مصنوعی ترجمه کنیم؟

ابتدا متن PDF استخراج و به بخش‌های قابل مدیریت تقسیم می‌شود. سپس هر بخش با مدل هوش مصنوعی ترجمه و خروجی در قالب Word یا PDF بازسازی می‌شود.

آیا می‌توان PDF انگلیسی را به فارسی ترجمه کرد؟

بله. برای خروجی مناسب باید جهت راست‌به‌چپ، فونت فارسی، واژه‌نامه و ساختار پاراگراف‌ها در مرحله تولید سند در نظر گرفته شوند.

آیا PDF اسکن‌شده قابل ترجمه است؟

بله، اما ابتدا باید با OCR به متن تبدیل شود. Tesseract، OCRmyPDF، PaddleOCR و مدل‌های تحلیل سند برای این کار قابل استفاده‌اند.

آیا ظاهر فایل اصلی کاملاً حفظ می‌شود؟

در اسناد ساده ممکن است ساختار تا حد خوبی حفظ شود، اما حفظ کامل Layout در فایل‌های پیچیده به تشخیص بلوک‌ها، فونت‌ها، تصاویر و بازسازی صفحه نیاز دارد.

آیا می‌توان جدول‌های PDF را ترجمه کرد؟

بله، اما جدول باید جداگانه استخراج و سلول‌به‌سلول ترجمه شود. استخراج ساده متن ممکن است ترتیب ستون‌ها را تغییر دهد.

چرا خروجی DOCX مفید است؟

فایل Word قابل ویرایش است و بازبینی ترجمه، اصلاح فونت و تنظیم صفحه‌بندی را ساده‌تر می‌کند. پس از تأیید می‌توان آن را به PDF تبدیل کرد.

چگونه ترجمه اصطلاحات را یکسان نگه داریم؟

واژه‌نامه‌ای از اصطلاحات مبدأ و ترجمه مطلوب ایجاد و همراه تمام درخواست‌ها ارسال کنید.

آیا API درواره برای ترجمه PDF قابل استفاده است؟

بله. متن استخراج‌شده از PDF به یک مدل متنی در API درواره ارسال می‌شود:

client = OpenAI(
    api_key=os.environ["DARVAREH_API_KEY"],
    base_url="https://api.darvareh.ir/v1",
)

بهترین مدل برای ترجمه فارسی کدام است؟

بهترین مدل به نوع سند بستگی دارد. چند مدل را روی مجموعه‌ای شامل متن عمومی، فنی، دانشگاهی و تجاری آزمایش و دقت، روانی، سرعت و هزینه را مقایسه کنید.

چگونه فایل ۲۰۰ صفحه‌ای را ترجمه کنیم؟

از صف پردازش، ذخیره نتیجه هر صفحه، محدودیت هم‌زمانی و امکان ادامه پردازش پس از خطا استفاده کنید.

آیا می‌توان ترجمه را قبل از دانلود بررسی کرد؟

بله. صفحات ترجمه‌شده را در پایگاه داده ذخیره و پیش‌نمایش هر صفحه را در پنل بازبینی نمایش دهید.

جمع‌بندی

ترجمه PDF با هوش مصنوعی فرایندی چندمرحله‌ای است:

  1. تشخیص نوع PDF
  2. استخراج متن یا اجرای OCR
  3. حفظ شماره صفحه و ساختار
  4. حذف متن‌های تکراری
  5. تقسیم متن طولانی
  6. اعمال واژه‌نامه
  7. ترجمه با مدل مناسب
  8. کنترل نام‌ها و اعداد
  9. ساخت فایل راست‌چین
  10. تولید خروجی Word یا PDF

در نمونه عملی این مقاله، متن PDF با PyMuPDF استخراج، با API درواره ترجمه و در قالب DOCX یا PDF فارسی بازسازی شد.

برای دریافت کلید API، مشاهده مدل‌ها و شروع اتصال برنامه، به مستندات API درواره مراجعه کنید.

مقالات مرتبط

منابع

این مقاله صرفاً با هدف آموزش و اطلاع‌رسانی تهیه شده است. پیش از استفاده عملی، مستندات رسمی سرویس‌ها و صفحه سلب مسئولیت را مطالعه کنید.

Read more