前言
在全球化项目中,多语言文档翻译是一个高频需求。传统方案是调用Google Translate API或Azure Translator API,但这些方案只翻译文本------翻译后PDF的排版、表格、图片位置全部丢失,需要大量后处理工作。
本文介绍如何在Web应用中集成PDFTranslator的翻译能力,实现"翻译PDF且保留原始格式"的功能,包含完整的前后端代码。
环境准备
- 后端:Python 3.10+,Flask
- 前端:Vue 3 + Element Plus
- 核心依赖:
bash
pip install flask flask-cors requests PyPDF2
- 系统要求:支持文件上传大小≥20MB,建议Nginx反向代理
实现方案
Step 1: 后端翻译接口设计
核心思路:前端上传PDF → 后端转发到PDFTranslator → 返回翻译后的PDF下载链接。
python
# app.py - Flask后端
import os
import uuid
import requests
from flask import Flask, request, jsonify, send_file
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# 配置
UPLOAD_FOLDER = "uploads"
OUTPUT_FOLDER = "outputs"
MAX_FILE_SIZE = 20 * 1024 * 1024 # 20MB
ALLOWED_EXTENSIONS = {"pdf"}
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
def allowed_file(filename):
"""检查文件扩展名"""
return "." in filename and \
filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route("/api/translate", methods=["POST"])
def translate_pdf():
"""PDF翻译接口
接收参数:
- file: PDF文件
- source_lang: 源语言(auto为自动检测)
- target_lang: 目标语言
返回:
- task_id: 任务ID
- status: 翻译状态
- download_url: 下载链接(翻译完成后)
"""
# 1. 校验文件
if "file" not in request.files:
return jsonify({"error": "No file uploaded"}), 400
file = request.files["file"]
if not allowed_file(file.filename):
return jsonify({"error": "Only PDF files allowed"}), 400
if len(file.read()) > MAX_FILE_SIZE:
return jsonify({"error": "File too large (max 20MB)"}), 400
file.seek(0) # 重置指针
# 2. 保存文件
task_id = str(uuid.uuid4())[:8]
filename = f"{task_id}_{file.filename}"
filepath = os.path.join(UPLOAD_FOLDER, filename)
file.save(filepath)
# 3. 获取翻译参数
source_lang = request.form.get("source_lang", "auto")
target_lang = request.form.get("target_lang", "en")
# 4. 调用PDFTranslator翻译
# 实际项目中,可通过Selenium/Playwright自动化上传翻译
# 或使用PDFTranslator的批量翻译接口
try:
result = call_pdftranslator(filepath, source_lang, target_lang)
return jsonify({
"task_id": task_id,
"status": "completed",
"download_url": f"/api/download/{result['output_filename']}",
"page_count": result.get("page_count", 0)
})
except Exception as e:
return jsonify({
"task_id": task_id,
"status": "failed",
"error": str(e)
}), 500
@app.route("/api/download/<filename>")
def download_file(filename):
"""下载翻译后的文件"""
filepath = os.path.join(OUTPUT_FOLDER, filename)
if os.path.exists(filepath):
return send_file(filepath, as_attachment=True)
return jsonify({"error": "File not found"}), 404
def call_pdftranslator(pdf_path, source_lang, target_lang):
"""调用PDFTranslator进行翻译
PDFTranslator支持100+语言互译,保留原始格式
实际集成时可通过浏览器自动化实现上传-翻译-下载流程
"""
# 方案1: 使用Playwright自动化(推荐生产环境使用)
# 方案2: 直接调用PDFTranslator网页接口(如有API)
# 方案3: 集成到现有翻译流水线
output_filename = f"translated_{os.path.basename(pdf_path)}"
output_path = os.path.join(OUTPUT_FOLDER, output_filename)
# 示例:使用requests模拟上传到PDFTranslator
# 注意:实际实现取决于PDFTranslator是否提供公开API
# 如无公开API,可使用Playwright自动化流程
# 这里展示Playwright方案的核心逻辑
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# 访问PDFTranslator
page.goto("https://pdftranslator.org")
# 上传文件
page.set_input_files('input[type="file"]', pdf_path)
# 选择目标语言
page.select_option('select[name="target_lang"]', target_lang)
# 等待翻译完成(通常2-5分钟)
page.wait_for_selector('.download-button', timeout=300000)
# 下载翻译结果
with page.expect_download() as download_info:
page.click('.download-button')
download = download_info.value
download.save_as(output_path)
browser.close()
return {
"output_filename": output_filename,
"page_count": get_pdf_page_count(output_path)
}
def get_pdf_page_count(pdf_path):
"""获取PDF页数"""
from PyPDF2 import PdfReader
reader = PdfReader(pdf_path)
return len(reader.pages)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
Step 2: 前端上传组件
vue
<!-- TranslatorUpload.vue -->
<template>
<div class="translator-upload">
<el-upload
drag
:before-upload="beforeUpload"
:http-request="customUpload"
accept=".pdf"
:limit="1"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
拖拽PDF文件到此处,或<em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip">
仅支持PDF格式,文件大小不超过20MB
</div>
</template>
</el-upload>
<!-- 语言选择 -->
<el-row :gutter="20" class="lang-select">
<el-col :span="12">
<el-select v-model="sourceLang" placeholder="源语言(自动检测)">
<el-option label="自动检测" value="auto" />
<el-option label="英语" value="en" />
<el-option label="中文" value="zh" />
<el-option label="日语" value="ja" />
</el-select>
</el-col>
<el-col :span="12">
<el-select v-model="targetLang" placeholder="目标语言">
<el-option label="英语" value="en" />
<el-option label="中文" value="zh" />
<el-option label="西班牙语" value="es" />
<el-option label="法语" value="fr" />
<el-option label="德语" value="de" />
</el-select>
</el-col>
</el-row>
<!-- 翻译按钮 -->
<el-button
type="primary"
@click="startTranslate"
:loading="translating"
:disabled="!fileReady"
>
{{ translating ? '翻译中...' : '开始翻译' }}
</el-button>
<!-- 下载链接 -->
<div v-if="downloadUrl" class="result">
<a :href="downloadUrl" download>
<el-button type="success">下载翻译文件</el-button>
</a>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
const sourceLang = ref('auto')
const targetLang = ref('zh')
const translating = ref(false)
const fileReady = ref(false)
const downloadUrl = ref('')
let uploadedFile = null
const beforeUpload = (file) => {
if (file.size > 20 * 1024 * 1024) {
ElMessage.error('文件不能超过20MB')
return false
}
uploadedFile = file
fileReady.value = true
return false
}
const startTranslate = async () => {
if (!uploadedFile) return
translating.value = true
const formData = new FormData()
formData.append('file', uploadedFile)
formData.append('source_lang', sourceLang.value)
formData.append('target_lang', targetLang.value)
try {
const res = await fetch('/api/translate', {
method: 'POST',
body: formData
})
const data = await res.json()
if (data.status === 'completed') {
downloadUrl.value = `/api/download/${data.output_filename}`
}
} finally {
translating.value = false
}
}
</script>
Step 3: 批量翻译扩展
当需要批量翻译多个PDF时,可以扩展后端支持队列:
python
import queue
import threading
# 翻译任务队列
task_queue = queue.Queue()
task_results = {}
def worker():
"""后台翻译工作线程"""
while True:
task = task_queue.get()
try:
result = call_pdftranslator(
task["filepath"],
task["source_lang"],
task["target_lang"]
)
task_results[task["task_id"]] = {
"status": "completed",
"output": result["output_filename"]
}
except Exception as e:
task_results[task["task_id"]] = {
"status": "failed",
"error": str(e)
}
finally:
task_queue.task_done()
# 启动3个worker线程
for _ in range(3):
threading.Thread(target=worker, daemon=True).start()
@app.route("/api/batch-translate", methods=["POST"])
def batch_translate():
"""批量翻译接口"""
files = request.files.getlist("files")
task_ids = []
for f in files:
task_id = str(uuid.uuid4())[:8]
filepath = os.path.join(UPLOAD_FOLDER, f"{task_id}_{f.filename}")
f.save(filepath)
task_queue.put({
"task_id": task_id,
"filepath": filepath,
"source_lang": request.form.get("source_lang", "auto"),
"target_lang": request.form.get("target_lang", "en")
})
task_ids.append(task_id)
return jsonify({"task_ids": task_ids})
运行效果
- 用户上传PDF文件(支持拖拽)
- 选择源语言(可自动检测)和目标语言
- 点击"开始翻译",后台调用PDFTranslator
- 翻译完成后返回下载链接
- 用户下载格式保留的翻译后PDF
关键优势:
- 翻译后保持原始布局、表格、图片位置不变
- 支持100+语言互译
- 用户无需注册,文件24小时内自动删除
总结
在Web应用中集成PDF翻译功能,核心在于保留原文档格式。传统翻译API只翻译文本,翻译后的PDF需要大量排版工作。通过集成PDFTranslator的能力,可以实现"翻译+格式保留"一步到位。
生产环境建议使用Playwright做浏览器自动化,配合任务队列实现批量翻译。如果需要更稳定的方案,可以考虑将PDFTranslator部署为内部微服务。
标签:PDF翻译、Python、Web开发、API集成