English | 简体中文
A desktop bilingual reader for PDFs and EPUBs, built for staying in the text with sentence-by-sentence translation close at hand.
v1.2.0 · Tauri · React · TypeScript · pdf.js
readani keeps the original document on the left and the translation on the right, so you can read a foreign-language PDF or EPUB without constantly copying text into another tool.
Instead of giving you one large translated block, it works sentence by sentence, so it is easier to check meaning, names, and references without losing your place.
It is especially useful for research papers, essays, manuals, reports, and other documents where sentence-level context matters.
- Side-by-side reading layout for source and translation
- PDF-first reader with preserved EPUB support
- Sentence-by-sentence translation for more precise reading
- Source-page text selection for quick translation lookups
- Local cache for faster re-opens and repeat reads
- English-only desktop UI with light, dark, and system theme modes
- Translation requests handled by the Tauri/Rust backend, not the frontend
- Built-in presets for
OpenRouter,DeepSeek, and genericOpenAI-Compatibleendpoints
- Download a packaged build from the GitHub Releases page
- Open the app on your computer
- Launch
readani - Open a PDF or EPUB
- Keep the PDF on the left and the translation pane on the right
- Open
Settings - Add a preset
- Choose a provider
- Paste your API key
- Load models or type a model name manually
- Save
- Click
Test
This is the easiest general setup if OpenRouter is reachable from your network.
- Create an account at OpenRouter.
- Create an API key in the OpenRouter dashboard.
- In
readani, create a preset with:- Provider:
OpenRouter - API key: your OpenRouter key
- Model:
openrouter/freefor a quick free test, or another current model from OpenRouter
- Provider:
- Save the preset and click
Test.
Notes:
- OpenRouter also supports many
:freemodel variants. - OpenRouter's official FAQ says new users only get a very small free allowance, and free models have low rate limits, so they are good for testing but not ideal as a production default.
This is often the simplest alternative for mainland China users because readani has a built-in DeepSeek preset.
- Create an account and API key from DeepSeek API.
- In
readani, create a preset with:- Provider:
DeepSeek - API key: your DeepSeek key
- Model:
deepseek-chat
- Provider:
- Save the preset and click
Test.
The DeepSeek base URL is already built into the app as https://api.deepseek.com.
If OpenRouter is inconvenient, you can use OpenAI-Compatible with providers that expose an OpenAI-style Chat Completions API.
Common choices:
- Alibaba Cloud Model Studio / DashScope
- Base URL for mainland China (Beijing):
https://dashscope.aliyuncs.com/compatible-mode/v1
- Base URL for mainland China (Beijing):
- SiliconFlow
- Base URL:
https://api.siliconflow.cn/v1
- Base URL:
In readani, use:
- Provider:
OpenAI-Compatible - Base URL: the provider URL above
- API key: your provider key
- Model: click
Load models, then pick a text/chat model from the provider's list
If you want the provider's own full instructions, use these links:
- OpenRouter docs: API keys, FAQ
- DeepSeek docs: DeepSeek API docs
- DashScope docs: Get API key, OpenAI-compatible endpoint and regions
- SiliconFlow docs: API reference, Rate limits
- Use
OpenRouterif you want the easiest model switching and its website is accessible for you. - Use
DeepSeekif you want a simple built-in alternative with minimal setup. - Use
OpenAI-Compatibleif you want to connect to China-friendly platforms such as DashScope or SiliconFlow.
readani does not ship with a bundled public API key or a shared default translation service.
That is intentional:
- a shared public key would be easy to abuse
- rate limits would be unpredictable
- service quality could disappear without warning
- users would have no control over privacy, billing, or availability
For now, the most realistic "free to try" path is:
OpenRouterwithopenrouter/free, or- any provider that currently offers its own trial quota or promotional credits
If you need reliable daily use, plan on bringing your own API key.
- Left: the original PDF or EPUB
- Right: translations, reading controls, and tools
- The frontend never calls translation providers directly
- Translation requests go through the Tauri backend
- The backend stores settings and translation cache files under the app config directory
- Cached results can be reused when the same page and translation inputs match
- Uses
pdfjs-dist/legacy/build/pdf.mjs - Keeps a selectable text layer when the PDF has usable text
- Handles text-based PDFs and OCR-text PDFs best
- Image-only PDFs without usable text show a fallback instead of pretending the text exists
If you are a normal reader, you do not need this section. These commands are only for developers running the app from source.
bun install
bun run tauri devbun run buildsrc/App.tsx- main app state, routing between home and reader, shared dialogssrc/views/HomeView.tsx- landing view and recent-books entry pointsrc/components/PdfViewer.tsx- PDF viewing shellsrc/components/PdfPage.tsx- PDF page rendering and selection layersrc/components/TranslationPane.tsx- translation presentationsrc/components/settings/SettingsDialogContent.tsx- provider and translation settings UIsrc/lib/textExtraction.ts- PDF text extraction heuristicssrc/lib/pageTranslationScheduler.ts- queued translation flowsrc-tauri/src/lib.rs- Tauri commands and translation orchestrationsrc-tauri/src/providers.rs- provider request shapingsrc-tauri/src/page_cache.rs- translation cache handling
- UI copy is intentionally English-only
- Translation quality depends on the provider, model, and source document quality
- Cache identity depends on the document, source text, selected provider, model, and target language
- API keys stay in the app config area, not in the frontend bundle
- Tauri
- Rust
- React 19
- TypeScript
- Radix UI
- pdf.js
- Slate
- react-virtuoso
- Created by Gallant GUO
- Contact: glt@gallantguo.com
- Special thanks to Everett (everettjf), author of PDFRead
This repository includes bundled font assets with their own license text in src/assets/fonts/fira-sans-condensed/OFL.txt.
