Paper Translate is a browser PDF viewer for scanned math papers. It shows the original page on the left and an English translation on the right, using either local Ollama models or qwen/qwen3-vl-32b-instruct via OpenRouter.
- Frontend: React + Vite +
pdf.js - Backend: local Express server
- Models:
- local Ollama:
qwen3.5:0.8b,qwen3.5:2b,qwen3.5:4b - hosted OpenRouter:
qwen/qwen3-vl-32b-instruct
- local Ollama:
- Math rendering: KaTeX
- Node 20+
- npm
- Optional: an OpenRouter API key
- Optional: Ollama running locally
npm installIf you want hosted OpenRouter inference, create api.txt in the project root with this exact format:
"openrouter"="YOUR_OPENROUTER_KEY"api.txt is ignored by git.
You can also use an environment variable instead:
export OPENROUTER_API_KEY="YOUR_OPENROUTER_KEY"Start the backend:
npm run dev:serverStart the frontend in another terminal:
npm run dev:webOpen:
http://localhost:5173- Upload a PDF or page image
- Choose the source language: French or German
- Choose a model:
- local Ollama for private/local usage
qwen/qwen3-vl-32b-instructfor the strongest hosted result
- Press
tor clickTranslate Current Page - Press
Escto leave split view - Enable
Show rawto inspect the exact model output and prompts
- Translation is page-based and manual
- The best hosted model currently configured is
qwen/qwen3-vl-32b-instruct - The right pane uses a readable flow layout based on model structure, not strict page reconstruction
- Formulas are rendered with KaTeX when possible
- A simple in-memory rate limiter protects public demos from light abuse
Run tests:
npm testBuild everything:
npm run buildLanguage evaluation helpers are also available:
npm run check:language -- --text "This is English."
npm run eval:pdf-language -- --pdf translation_samples/german_paper.pdf --source German --samples 5A CI workflow is included to run tests and builds on pushes and pull requests.
GitHub Pages is not configured here because live translation requires a backend and an API key. You can still host the frontend separately later if you point it at a hosted backend.
This project can be deployed to a Hugging Face Docker Space.
- Create a new Hugging Face Space
- Choose
Dockeras the SDK - Add a Space secret:
OPENROUTER_API_KEY
- Push this repository to the Space
The included Dockerfile builds the frontend and backend together and serves the built app from the Express server on port 7860.
- the app needs a backend for translation requests
- the API key must stay server-side
- Docker Spaces support private secrets and server processes
If your OpenRouter key has a small monthly cap, you should still be careful with public demos.
Current lightweight protections:
- in-memory request rate limit per client/IP
- manual page-by-page translation only
For a stricter public demo later, consider limiting uploads or serving only sample PDFs.