Skip to content

bishoe01/TransScan

Repository files navigation

transScan

English | 한국어

transScan hero image

transScan is a macOS menu bar translation overlay for reading foreign-language text without leaving your current app.

The app stays out of the Dock, listens for a configurable shortcut, opens a floating NSPanel, reads recently copied text from the clipboard, and translates it with Apple's Translation framework. Select the text you want, copy it, and keep the popup open while each new copy updates the translation.

Translation Model

transScan uses Apple's built-in Translation framework through TranslationSession.

  • No OpenAI, Google Translate, DeepL, or custom LLM API is used.
  • No API key is required.
  • Translation is handled by Apple's system translation engine and language packs on supported macOS versions.
  • The app creates the translation session in SwiftUI with .translationTask(engine.configuration) and passes that session into TranslationEngine.

The practical tradeoff is that translation quality, language availability, and language-pack behavior are determined by Apple's framework, not by this repository.

Current State

The MVP is implemented as a macOS-only SwiftUI/AppKit app.

  • Menu bar app with LSUIElement=YES
  • Floating always-on-top overlay built with NSPanel + SwiftUI
  • Configurable hotkey stored in UserDefaults
  • Accessibility selected-text detection with clipboard fallback
  • Source language auto-detect or manual source selection
  • Target language picker and source/target swap
  • Apple Translation framework session injection through .translationTask
  • XCTest coverage for detector, translation engine, and view model behavior

The active work is UI reliability and reading polish: overlay reopen behavior, shortcut display, long text scrolling, and real app verification. See roadmap.md and roadmap.progress.json.

Product Goal

The user should be able to read an article, PDF, or app screen, copy a sentence, press the hotkey, and immediately see a compact translation overlay without switching context.

MVP non-goals:

  • Text-to-speech
  • Translation history
  • Explanation or nuance analysis
  • iOS support

Requirements

  • macOS app development environment with Xcode
  • Apple Translation framework support on the target macOS version
  • Accessibility permission for selected-text detection

The current Xcode project uses generated Info.plist settings, LSUIElement=YES, and bundle id com.finn.transScan.

Quick Start

Open in Xcode:

open transScan.xcodeproj

Build from CLI:

xcodebuild -project transScan.xcodeproj -scheme transScan build

Run tests:

xcodebuild -project transScan.xcodeproj -scheme transScan test

How The App Works

The high-level path is:

  1. transScanApp.swift starts a MenuBarExtra and Settings scene.
  2. AppDelegate.swift registers global/local key monitors and toggles the overlay.
  3. OverlayWindowController.swift owns the floating NSPanel lifecycle.
  4. OverlayContentView.swift hosts the SwiftUI overlay and injects the Translation session with .translationTask.
  5. TextDetector.swift watches selected text with Accessibility APIs and falls back to clipboard polling.
  6. TranslationViewModel.swift debounces detected text, tracks translation state, handles language swaps, and coordinates UI updates.
  7. TranslationEngine.swift wraps Apple Translation, language persistence, language-pack preparation, and pending requests while the session is not ready.

Important architecture rule: TranslationEngine cannot create its own TranslationSession. The SwiftUI view layer must create the session through .translationTask(engine.configuration) and pass it back with engine.provideSession(session). If this connection breaks, translation requests can remain pending.

Repository Map

transScan/                         macOS app source
  transScanApp.swift               app entry point
  AppDelegate.swift                menu bar lifecycle and hotkey monitors
  OverlayWindowController.swift    NSPanel lifecycle
  OverlayContentView.swift         overlay host and Translation session injection
  TranslationViewModel.swift       translation state and UI flow
  TranslationEngine.swift          Apple Translation wrapper
  TextDetector.swift               Accessibility and clipboard text detection
  SettingsView.swift               shortcut/settings UI

transScanTests/                    XCTest coverage
docs/                              product, architecture, UI, and session notes
roadmap.md                         human-readable current state and next work
roadmap.progress.json              machine-readable handoff tracker
CLAUDE.md                          agent guardrails and project-specific rules
AGENTS.md                          Codex-facing repository guidelines

Project Documents

Read these before changing behavior:

If BrainVault notes and repository files conflict, prefer the repository files for code-coupled facts.

AI Workflow

This project should be worked on through the app source, repo-local docs, session handoff files, and macOS-specific build/debug support. Use the workflow by task type.

Normal implementation

Start by reading:

  1. CLAUDE.md
  2. AGENTS.md
  3. roadmap.md
  4. relevant files under docs/
  5. the source and tests for the feature being changed

Then make focused changes and verify with:

xcodebuild -project transScan.xcodeproj -scheme transScan build
xcodebuild -project transScan.xcodeproj -scheme transScan test

For UI behavior, also run the app and visually check the menu bar item, overlay open/close, shortcut label, settings window, and long translation text behavior.

/session-end

Use /session-end when ending a coding session, preparing handoff, or saving resumable state.

It should update:

  • CLAUDE.local.md with short next-session instructions
  • roadmap.md checkboxes
  • roadmap.progress.json
  • docs/session-logs/YYYY-MM-DD.md

Expected verification:

node -e "JSON.parse(require('fs').readFileSync('roadmap.progress.json','utf8')); console.log('roadmap.progress.json OK')"
git check-ignore -v CLAUDE.local.md || true
git status --short

The short-term handoff file should stay local and gitignored. The long-term record belongs in docs/session-logs/.

build-macos-apps

Use the build-macos-apps plugin when the task is macOS-specific:

  • build or launch the app
  • inspect schemes or app bundle behavior
  • debug menu bar, window, signing, entitlement, log, or runtime launch issues
  • create a stable script/build_and_run.sh entrypoint if repeated build/run work becomes painful

For now the repo uses direct Xcode commands. If app launch/debug becomes frequent, add a project-local run script and wire it into Codex app environment actions.

Testing Strategy

App tests live in transScanTests/.

Prefer focused XCTest coverage around:

  • text normalization and clipboard fallback
  • duplicate text suppression
  • translation engine language/session behavior
  • view model state transitions
  • shortcut and settings logic when extracted into testable units

Development Notes

  • Keep SwiftUI views view-focused.
  • Put AppKit/window/platform lifecycle code in dedicated service-style types.
  • Keep the Translation framework session bridge in the view layer.
  • Do not let language changes erase the current translation context unless the UX explicitly calls for it.
  • For shortcut work, verify both global and local app states. The current implementation uses NSEvent monitors; Carbon RegisterEventHotKey is still a possible future hardening path.
  • For overlay UI changes, check short text, long text, blank lines, scroll behavior, close/reopen, menu bar reopen, and hotkey toggle.

Commit And PR Style

Use Conventional Commit style:

feat(ui): improve overlay reading layout
fix(ui): restore overlay fade-in on reopen
test(translation): cover language swap behavior

For PRs, include:

  • short summary
  • linked issue or decision note if applicable
  • build/test results
  • screenshots or screen recordings for UI changes
  • notes about Accessibility permission or manual macOS verification

About

MacOS Overlay 번역앱

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors