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, exposes start/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:

  1. Entry point – src-tauri/src/lib.rs calls run (line 22), which constructs the Tauri app and registers command callbacks.
  2. The UI (src/index.html + src/js/app.js) triggers the start command via invoke('start').
  3. src-tauri/src/audio/microphone.rs::start creates a capture object and spawns start_local_pipeline.
  4. src-tauri/src/commands/local_pipeline.rs::start_local_pipeline writes a start log (log_to_file) and forwards PCM buffers to send_audio_to_pipeline.
  5. send_audio_to_pipeline issues an HTTP POST to Soniox (the only outbound network call).
  6. The response is parsed and passed back to the UI through the Tauri event system; the UI updates the overlay.
  7. 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 (or cargo install --locked) to respect lockfiles in CI.
  • MEDIUM – Add a dependency‑vulnerability scan step to CI.
  • MEDIUM – Set persist-credentials: false on 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.