Privacy-first email translation — Ollama (local/self-hosted), LibreTranslate (self-hosted or public), or Google Translate as a fallback
Fork of zoott28354/thunderbird-translator Extended with compose translation, auto-translate, local LibreTranslate support, and a native toolbar UI.
- 🔒 Privacy-first — translate on your own machine or private network; your emails stay under your control
- 🏠 Ollama — local or self-hosted; zero external connections, works fully offline
- 🖥️ LibreTranslate — self-hosted on your own server, or use a public instance
- 🌐 Google Translate — zero-config fallback only; email text is sent to Google's servers. Not suitable for private or sensitive emails — use Ollama or LibreTranslate instead
- 🤖 Supports all Ollama models — translategemma, Llama, Mistral, and more
- 📨 Translate received emails — inline replacement with one-click restore
- ✍️ Translate while composing — select text in the compose window and translate it in place
- ⚡ Auto-translate — optionally translate every email automatically when opened
- 🌍 15 target languages — English, Dutch, German, French, Spanish, Italian, Portuguese, Russian, Japanese, Chinese, Korean, Arabic, Turkish, Polish, Filipino
- 💾 Persistent settings — service and language remembered per-service
- 🌐 Multilingual interface — 7 UI languages: 🇬🇧 English, 🇮🇹 Italian, 🇩🇪 German, 🇫🇷 French, 🇪🇸 Spanish, 🇵🇹 Portuguese, 🇷🇺 Russian
- Thunderbird 128 or later (ESR and non-ESR)
- Ollama — must be installed and running (local machine or private server); see setup
- LibreTranslate — must be reachable (local machine, private server, or public instance); see setup
- Download
thunderbird-translator.xpifrom Releases - In Thunderbird: Menu → Tools → Add-ons
- Click the gear icon ⚙️ → Install Add-on from file…
- Select the
.xpifile and confirm
- In Thunderbird: Ctrl+Shift+A → gear icon → Debug Add-ons
- Click Load Temporary Add-on…
- Select
manifest.jsonfrom the project folder
Default service is Google Translate. On a fresh install, email text is sent to Google's servers until you configure Ollama or LibreTranslate. If you are translating private or sensitive emails, set up one of those services first and switch the active service in Preferences.
Open Menu → Tools → Add-ons → Thunderbird Translator → Preferences.
| Field | Default | Notes |
|---|---|---|
| Server URL | http://localhost:11434 |
Change if Ollama runs on another machine |
| Model | — | Select from installed models; click ↻ to refresh |
| API Key | (blank) | Required only if Ollama is behind an auth proxy |
Test Connection — verifies reachability and lists available models.
Local machine — install from ollama.ai, then pull a model:
ollama pull translategemma
Private server — see the Ollama Docker documentation.
| Field | Default | Notes |
|---|---|---|
| Server URL | https://libretranslate.com |
Replace with your own instance URL |
| API Key | (blank) | Required by some instances; leave blank for open ones |
Test Connection — calls /languages on the configured URL to verify reachability.
Self-hosted — see LibreTranslate on GitHub for installation options (local or server).
Public instances — use https://libretranslate.com or any other public instance. Some require an API key.
A Translate button appears in the message toolbar (next to Reply, Forward, etc.).
- Open an email
- Right-click the Translate button to select your target language (once set, it is remembered per service)
- Click the Translate button — the email body is replaced inline
- Click again to restore the original
Enable Auto-translate via the right-click context menu to translate every email automatically when opened. A badge on the toolbar button shows progress:
A Translate button appears in the compose toolbar.
- Write or paste text in the compose body
- Select the text you want to translate
- Right-click the Translate button to set the target language if needed
- Click the Translate button — selected text is replaced in place (undo works)
| Mode | Data sent externally |
|---|---|
| Ollama (local) | Nothing — 100% on your machine |
| Ollama (self-hosted) | Nothing — stays on your private network |
| LibreTranslate (self-hosted) | Nothing — stays on your private network |
| LibreTranslate (public) | Email text only, to the configured instance |
| Google Translate | Email text only, to Google servers |
No tracking, no analytics. API keys and settings are stored locally in Thunderbird's own storage — never transmitted.
messagesRead— reads email content for translationmessagesModify— replaces displayed text with translationcompose— injects translation script into compose windowsstorage— saves your settings locallytabs— identifies the active window for popup communication*://*/*— required because Ollama and LibreTranslate URLs are user-configurable; the extension only contacts the URLs you set in preferences
When using Ollama or LibreTranslate, you can confirm no email text leaves your network:
- In Thunderbird, right-click the toolbar and open Developer Tools, or go to Tools → Developer Tools
- Select the Network tab
- Translate an email
- Inspect the requests — you should see only traffic to your configured URL (e.g.
http://localhost:11434or your homelab IP); nothing togoogle.comor any external service
The extension's full source is on GitHub. All translation calls are in background.js — three fetch() call sites: translateWithOllama(), translateWithGoogle(), and translateWithLibreTranslate(), routed by a single switch in translateText(). There are no background network calls, analytics, or telemetry.
Note: this only applies when Ollama or LibreTranslate is the active service. Google Translate always contacts Google's servers — see the Security table.
Some Ollama versions or configurations block requests from browser extensions. Set OLLAMA_ORIGINS=moz-extension://* before starting Ollama and restart it.
Run ollama pull translategemma (or whichever model is selected in settings).
- Verify the URL in settings matches your instance (e.g.
http://192.168.1.10:5000) - If your instance requires an API key, enter it in the API Key field
- Click Test Connection to confirm reachability before translating
Highlight text in the compose body before clicking the Translate button in the popup.
- Prompt injection mitigation — Ollama translate and detect prompts now XML-escape email content before substitution; default prompts wrap the text in
<text>tags to separate instruction from data - Badge lifecycle fix —
...badge now correctly cleared when navigating to a new email before translation completes - Race condition guard — concurrent translate calls (double-click, rapid button press) are now blocked until the current translation finishes
- Port cleanup — pending requests reject immediately on content script disconnect instead of waiting for the 30-second timeout
- Never/Always auto-translate toggle — context menu item shows the detected source language and lets you toggle it into the exemption list; updates dynamically per email; shows "Detecting language…" while translation is in progress
- Language exemptions for auto-translate — emails in excluded languages are translated first, source language is detected, then the translation is silently reverted if the language is on the never-translate list
- Separate detection model — Ollama uses a dedicated detection model and prompt (defaults to the translation model); configurable separately in Options
- Custom translation and detection prompts — both prompts are editable in the Advanced section of Options; support
{TEXT},{TARGET_LANG},{TARGET_CODE},{SOURCE_LANG},{SOURCE_CODE}variables; clear to restore built-in defaults - Translate Model / Detection Model labels — renamed "Model" field to "Translate Model" to distinguish from the new Detection Model field
- Toggle disabled during translation — Never/Always auto-translate button is grayed out while auto-translate is running; re-enables once detection is complete
- Per-service language menus (read and compose independently)
- Translation cache invalidated when target language changes
- Inline status messages on Options page (replaces alert popups)
- Dead popup code removed
- Right-click context menu on toolbar button (read and compose)
- Direct toggle UX — translate/restore without a popup
- Per-service target language — each service remembers its own language choice
- SVG icons (dark and light variants)
- Target language shown in toolbar button title
- Translated subject bar — sticky bar at the top of the email body showing the translated subject; respects dark mode; removed on revert
- Compose translation — select text in compose window and translate in place
- Native toolbar UI — action buttons in read and compose toolbars replace injected toolbar
- Auto-translate — optional per-email auto-translation with badge progress indicator
- Self-hosted LibreTranslate — configurable URL + optional API key; test connection button
- Ollama API key support for proxied/remote instances
- Injected toolbar in message view — service selector, language selector, Translate/Restore buttons
- Dark mode support
- Source language detection and translation cache
- Dynamic Ollama URL; service dropdown in toolbar
- Simplified options page; fork authorship
- Deterministic tab/preview routing
messageDisplayScriptsprogrammatic registration (Thunderbird 128–147+)
- Initial release: Ollama, Google Translate, LibreTranslate; context menu UI; 7 UI locales
MIT — free to use, modify, and distribute. Original work by zoott28354.




