Skip to content

SandyAbasman/desktopTranslator-

Repository files navigation

Desktop Translator

Highlight any text anywhere on your OS, press Ctrl+T, get an instant translation popup near your cursor.

Built with Electron + React + TypeScript, generated from a single translation-app.plain spec via the codeplain renderer.


Features

  • Global hotkeyCtrl+T works in any app: browser, Slack, PDF, terminal, IDE.
  • Smart popup — frameless, always-on-top, positioned beside the cursor.
  • 26+ languages with automatic source-language detection.
  • Two providers — free MyMemory by default, optional OpenAI (gpt-4o-mini) with your API key.
  • Local cache + history — repeated phrases are instant; last 50 translations saved.
  • Themes — light, dark, or follow system.
  • One-click copy, swap source ↔ target, retry on error.
  • Cross-platform: macOS / Windows / Linux.

Quick start

Requirements

Tool Version
Node.js 18+
npm 9+
OS macOS, Windows, or Linux

On Linux you also need xdotool for the copy-keystroke simulation:

sudo apt install xdotool   # Debian/Ubuntu

Install

git clone https://github.com/SandyAbasman/codeplain.git
cd codeplain
npm install
npm install --prefix dist

Run

npm start

This kills any stale Vite/Electron processes, builds the React popup, then launches Vite (http://localhost:3000) and Electron together. First launch takes ~10 seconds.

You'll see a tray icon in the menu bar and the message:

Desktop Translator running. Press Ctrl+T to translate highlighted text.

How to use

  1. Highlight text in any app — a sentence in a webpage, an error message in your terminal, a chat line.
  2. Press Ctrl+T (same shortcut on all platforms — not Cmd on macOS).
  3. The popup appears beside your cursor with the source text and translation.
  4. Use the dropdown to change target language (re-translates automatically).
  5. Click to swap languages, 📜 for history, ⚙️ for settings, or Esc to close.
  6. The translation is auto-copied — paste anywhere.

Popup auto-hides after 10 seconds. Try it with test-translation.txt in this repo.

Tray menu

Right-click the tray icon:

  • Show Translator — open the popup without grabbing new text.
  • Test Translation (from clipboard) — translate whatever's on the clipboard.
  • Settings — open the settings window.
  • Quit — stop the app.

macOS permission

On the first Ctrl+T, macOS will ask for Accessibility permission (so Electron can simulate Cmd+C to capture the selection).

  • System Settings → Privacy & Security → Accessibility
  • Add and enable Electron (or Terminal if you're running from terminal).

Without it the popup will open but the source text will be empty.


Settings & providers

Click ⚙️ in the popup to open settings:

Setting Default Notes
Provider mymemory Free, ~5,000 chars/day per IP
OpenAI API key (empty) Required to switch to openai
Default target language en Used when popup first opens
Theme system light, dark, or follow OS

Settings persist in localStorage.

Hitting a rate limit?

MyMemory returns HTTP 429 after ~5,000 chars/day (anonymous). You'll see:

API rate limit exceeded: Please try again later.

Options:

  • Wait a few minutes (burst limit) or 24h (daily quota).
  • Switch the provider to OpenAI in settings and paste a key.

Project layout

.
├── main.js                  # Electron main process (window, tray, hotkey)
├── preload.js               # Context bridge → window.electronAPI
├── settings.html            # Settings window
├── translation-app.plain    # The single spec the app is generated from
├── test-translation.txt     # Sample multilingual text for testing
├── dist/                    # React popup (Vite + TS)
│   ├── src/
│   │   ├── App.tsx
│   │   ├── popup-main.tsx       # Popup entry point
│   │   ├── components/
│   │   │   ├── TranslationPopup.tsx
│   │   │   ├── HistoryDrawer.tsx
│   │   │   └── SettingsDrawer.tsx
│   │   └── services/
│   │       ├── TranslationEngine.ts
│   │       └── StorageService.ts
│   ├── popup.html
│   └── vite.config.ts
└── plain_modules/           # Generated artifacts (don't edit by hand)

Scripts

Script What it does
npm start Stop stale processes → build popup → launch Vite + Electron
npm run dev Same as start, without the stop-all step
npm run dev:vite Vite dev server only (dist/)
npm run dev:electron Electron only (Vite must already be on :3000)
npm run stop:vite Kill whatever is on port 3000
npm run stop:electron Kill running Electron processes
npm run stop:all Both of the above
npm test --prefix dist Vitest unit + component tests

Troubleshooting

Popup is blank / large white window

  • Quit from the tray, then npm run stop:all && npm start. An old Electron build is probably still running.

Port 3000 is already in use

  • npm run stop:vite && npm start.

A JavaScript error occurred in the main process: write EIO

  • Already patched — pull latest. The app now swallows EIO from headless launches.

Popup opens but source text is empty (macOS)

Hotkey doesn't fire

  • Another app may have grabbed Ctrl+T (some browsers reopen closed tabs). Quit that app or change the shortcut in main.js:
    globalShortcut.register("Control+Shift+T", handleHotkey);

Tech stack


License

MIT — do whatever, just don't sue.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors