Menu bar app macOS cho dịch realtime theo ngữ cảnh qua phím tắt toàn hệ thống.
Open-source client. Backend tham chiếu nằm trong repo riêng (closed-source). Client chỉ nói chuyện với HTTP endpoint qua docs/api-contract.md, nên có thể ghép với mọi backend tự xây miễn là tuân thủ contract.
- Inbound: bôi đen text trong app bất kỳ, bấm
Option-D, app giả lậpCommand-C, gửi text lên backend, hiển thị bản dịch tiếng Việt bằng floating HUD tại vị trí chuột. - Outbound Keigo: gõ tiếng Việt trong ô chat, bấm
Command-Return, app chọn dòng hiện tại, copy, dịch sang tiếng Nhật công sở. Mặc định hiện preview HUD; bấmTabđể sửa bản dịch,Returnđể gửi,Escđể hủy và phục hồi clipboard. - Outbound Casual: giống outbound nhưng dùng
Option-Returnvà persona tiếng Nhật giao tiếp bạn bè (auto-send, không preview). - Menu bar app chạy nền bằng AppKit/SwiftUI.
- Global hotkeys bằng Carbon
RegisterEventHotKey. - Automation bằng
CGEvent, clipboard bằngNSPasteboard. - Settings UI để cấu hình backend endpoint, bearer token và glossary.
- API key + glossary lưu trong macOS Keychain (
kSecAttrAccessibleAfterFirstUnlock); migration một-lần từUserDefaultscũ. - Focus-guard: nếu app frontmost thay đổi giữa hotkey và paste, workflow bị abort và clipboard được restore.
- First-launch setup cho Accessibility và Input Monitoring; hotkeys chỉ được đăng ký sau khi setup hoàn tất.
- HTTPS-only enforcement cho remote endpoint;
http://chỉ được cho phép trên loopback (localhost,127.0.0.1,::1).
Mở app lần đầu rồi cấp:
- System Settings -> Privacy & Security -> Accessibility
- System Settings -> Privacy & Security -> Input Monitoring
Accessibility là quyền quan trọng nhất cho thao tác giả lập phím. Input Monitoring được hiển thị theo yêu cầu MVP và hữu ích cho các workflow hotkey/input sâu hơn.
swift build
swift run ContextualMacTranslatorNếu chạy trong môi trường sandbox bị lỗi cache SwiftPM, chạy trực tiếp trong terminal macOS bình thường.
swift test48 test Swift Testing cho Keychain store, credential migration, clipboard polling, focus guard, preview HUD, endpoint policy, SettingsStore và persona policy.
Sau khi mở app:
- Mở Settings từ menu bar.
- Endpoint mặc định:
http://127.0.0.1:8765/translate(loopback sang backend chạy local). Remote endpoint phải dùnghttps://. - Nếu backend yêu cầu bearer auth, dán token vào field "API Key". Token được lưu trong Keychain (không trong UserDefaults).
- Glossary là mảng
term = preferredTranslationmỗi dòng một cặp; cũng lưu trong Keychain. Dòng bắt đầu bằng#là comment. Có sẵn glossary IT khởi đầu (EN/VI → JP, ~140 thuật ngữ chuẩn nghiệp cho BrSE) tạiexamples/it-glossary-en-ja.txt— copy các dòng cần dùng vào Settings.
Client gửi Authorization: Bearer <token> khi field API key có giá trị, bỏ qua header nếu rỗng.
Backend tham chiếu (Python stdlib, đa provider) được phát hành tách rời tại repo translator-server. Xem ../docs/api-contract.md để tự xây backend khác.
Provider hỗ trợ trong reference backend: Gemini API, Ollama local, Google Translate Basic, OpenAI-compatible, mock (echo). Khi chạy backend public (non-loopback), server bắt buộc set TRANSLATOR_TOKEN hoặc explicit TRANSLATOR_ALLOW_REMOTE=1.
scripts/package_app.sh release
open ".build/app/Contextual Mac Translator.app"scripts/package_installer.sh
open ".build/installer/Contextual-Mac-Translator-v0.3.1-macos-arm64.pkg"Installer hiện là package unsigned cho local testing; public distribution vẫn cần Developer ID signing + notarization.
scripts/package_dmg.sh
open ".build/dmg/Contextual-Mac-Translator-v0.3.1-macos-arm64.dmg"DMG hiện là unsigned local-testing artifact; public distribution vẫn cần Developer ID signing + notarization.
Bundle ID hiện tại là placeholder app.lookerlab.translator. Trước khi phân phối public phải:
- Đăng ký Apple Developer Program và sinh "Developer ID Application" certificate.
- Đổi
CFBundleIdentifiertrongscripts/package_app.shvàkeychainServicetrongSources/ContextualMacTranslator/SettingsStore.swiftsang reverse-DNS thực sự sở hữu. - Bổ sung
codesign --options runtime --timestamp+xcrun notarytool submit --wait+xcrun stapler staplevào pipeline đóng gói.
- Outbound chọn text từ con trỏ về đầu dòng bằng
Command-Shift-Left; phù hợp với chat input một dòng. App nhiều dòng hoặc editor custom có thể cần selection strategy riêng. - Client chấp nhận response dạng
translation,translatedText,outputText,output_text, hoặc OpenAI-stylechoices[]. - Chưa có cấu hình tùy biến hotkey trong UI; hotkeys đang cố định theo brief.
- Certificate pinning, signing/notarization và Sparkle update channel: M2/M3 roadmap (xem docs/deliver-report.md).
- ../docs/PRD.md — yêu cầu sản phẩm.
- ../docs/define-spec.md — định nghĩa milestone + acceptance criteria.
- ../docs/develop-report.md — báo cáo build M1.
- ../docs/deliver-report.md — báo cáo deliver M1, danh sách finding, lộ trình M2/M3.
- ../docs/smoke-test-runbook.md — runbook smoke test thủ công.
- ../docs/api-contract.md — contract HTTP với backend.
