Commit Graph
2 Commits
Author SHA1 Message Date
jaredandClaude Opus 4.8 c77ab346d3 fix(translation): address review findings
Follow-up hardening from two review passes on the on-device translation
feature:

- Privacy (HIGH): the translation cache is decrypted message plaintext,
  but logout did not clear it (unlike the search index), leaving up to
  300 cleartext bodies in localStorage on shared devices. Add
  clearTranslationCache() and call it from both logout paths
  (logoutClient and the server-forced SessionLoggedOut handler).
- Edited messages (MEDIUM): the cache key was eventId:target with no
  content dependence, so an edit reused the pre-edit translation. Fold a
  content fingerprint into the key, and re-arm the auto-translate
  one-shot when the text changes.
- Settings (LOW): coerce a persisted translateTargetLang to a supported
  curated code so the hook never targets a language the engine can't
  produce (previously only the UI clamped it).
- Chinese (LOW): restore canonical BCP-47 case (zh-Hant / zh-Hans) at
  the Translator API boundary, since normalizeLang lowercases the script
  subtag for internal keys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 16:18:27 -04:00
jaredandClaude Opus 4.8 ecb7b1a7fb feat(translation): on-device message translation
Add per-message translation that runs entirely on-device via the
Chromium built-in Translator + LanguageDetector APIs. Message text
never leaves the machine and never touches a cloud service, preserving
the E2EE guarantee. When the on-device engine is unavailable
(non-Chromium / mobile) the feature simply hides itself; there is no
network fallback.

- Engine abstraction (utils/translation): TranslationEngine interface
  plus a chromeTranslationEngine implementation (feature-detected,
  caches translator/detector instances, download-progress monitor).
  Pure lang-code helpers (normalize/sameLanguage/curated targets) with
  unit tests.
- Settings: translateTargetLang (default English) + autoTranslate
  (opt-in), with a Messages settings tile — a target-language select
  and an auto-translate switch, disabled with a note where unsupported.
- useMessageTranslation hook + shared per-event toggle atom-family and a
  persisted LRU cache so scrollback never re-translates.
- UI: a Translate / Show Original message-menu action, an inline
  "Translated from <lang> - Show original" chip, and a body swap in
  m.text/m.emote/m.notice that renders the translated text through the
  plain-text path (linkify + emoji) inside a dir=auto span for RTL.
- Auto-translate flips foreign messages whose model is already
  downloaded; first-time downloads keep the manual chip (user gesture).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 16:08:40 -04:00