The Problem
Users need a desktop translator that works offline, respects privacy, and avoids costly cloud‑only services. Existing solutions either require a permanent server, expose API keys, or run only on a single OS. The lack of a cross‑platform, real‑time UI forces teams to stitch together separate STT/TTS tools.
What This Does
my-translator is a Tauri‑based desktop app (macOS + Windows) that captures system or microphone audio, sends 16 kHz PCM to the Soniox API for speech‑to‑text + translation, and renders the result in a lightweight overlay. Optional TTS can read the translation via Edge, Google, or ElevenLabs. All API keys are supplied by the user; no third‑party backend is involved.
Key files:
src-tauri/src/audio/microphone.rs– creates the audio stream, exposesstart/stop.src-tauri/src/commands/local_pipeline.rs– orchestrates the pipeline, writes logs (log_to_file), and performs network calls to Soniox.src/js/app.js– the single‑page UI driver, handling settings, panel mode, and invoking TTS modules (src/js/edge-tts.js,google-tts.js,elevenlabs-tts.js).src-tauri/src/settings.rs– persists user preferences and API keys to disk.
How It Is Wired
Execution begins in the Tauri runtime:
- Entry point –
src-tauri/src/lib.rscallsrun(line 22), which constructs the Tauri app and registers command callbacks. - The UI (
src/index.html+src/js/app.js) triggers thestartcommand viainvoke('start'). src-tauri/src/audio/microphone.rs::startcreates a capture object and spawnsstart_local_pipeline.src-tauri/src/commands/local_pipeline.rs::start_local_pipelinewrites a start log (log_to_file) and forwards PCM buffers tosend_audio_to_pipeline.send_audio_to_pipelineissues an HTTP POST to Soniox (the only outbound network call).- The response is parsed and passed back to the UI through the Tauri event system; the UI updates the overlay.
- If TTS is enabled, the UI invokes one of the JS TTS modules, which each call their respective provider APIs (Edge, Google, ElevenLabs).
Blast‑radius hubs – log_to_file is called from five locations, making it a high‑impact change point. The UI file src/js/app.js imports eight other JS modules, so any modification ripples widely. The Rust audio pipeline (src-tauri/src/audio/*.rs) contains deep nesting (up to 8 levels) that complicates reasoning.
No circular module dependencies were detected; the import graph is a shallow DAG, easing incremental changes.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/my-translator.git
cd my-translator
# Install JavaScript dependencies (npm is declared in package.json)
npm ci
# Build the Rust side and launch the Tauri dev window
cargo tauri dev
Configuration: edit the JSON file produced by src-tauri/src/settings.rs (located at the path returned by settings_path()) to insert your Soniox, Google, and ElevenLabs API keys. The same file stores UI preferences (panel mode, font size, selected TTS provider).
Running the built binary launches the overlay UI; use the on‑screen controls to select audio source, language pair, and optional TTS.
Real‑World Use
A remote‑learning team on Windows wants live subtitles for a bilingual lecture. They install the app, paste the Soniox key, enable “Two‑Way” mode, and set English ↔ Vietnamese. The app captures system audio, translates each speaker in real time, and displays side‑by‑side panels without any server‑side processing, keeping student data on‑device.
Code Health & Issues
- HIGH – Pin GitHub Actions to commit SHA (
.github/workflows). - HIGH – Upgrade vulnerable dependencies (
tauri@2,futures-util@0.3). - HIGH – No test suite (26 source files, 0 test files).
- MEDIUM – Enable Dependabot/Renovate for automatic updates.
- MEDIUM – Use
npm ci(orcargo install --locked) to respect lockfiles in CI. - MEDIUM – Add a dependency‑vulnerability scan step to CI.
- MEDIUM – Set
persist-credentials: falseon checkout in release workflow. - LOW – Define job timeouts in CI workflows.
- LOW – Add conventional repo files (
.editorconfig, formatter config).
Additional static findings: deep nesting in several Rust and JS files, duplicated 6‑line blocks across audio and TTS modules, and a 1 270‑line src/js/app.js that centralises most UI logic.
The Bottom Line
my-translator delivers a functional, cross‑platform real‑time translation overlay with user‑controlled API keys and no server dependency. The architecture is clear and modular, but the codebase suffers from high cognitive load, duplicated logic, and a complete lack of automated tests. It is suitable for teams comfortable extending Rust/JS code and willing to invest in refactoring and test coverage before production use.