Skip to content

feat: on-device translation of item text (P13b-2)#140

Merged
blokzdev merged 1 commit into
mainfrom
claude/p13b2-translation
Jun 2, 2026
Merged

feat: on-device translation of item text (P13b-2)#140
blokzdev merged 1 commit into
mainfrom
claude/p13b2-translation

Conversation

@blokzdev
Copy link
Copy Markdown
Owner

@blokzdev blokzdev commented Jun 2, 2026

What & why

Second half of P13b — on-device translation. A "Translate…" action on item detail translates an item's description + transcript into the user's language, fully on-device via ML Kit. No Google Play Services — language models download over HTTPS (~30 MB each, English pivot) and run offline after — fitting GrabBit's sideloaded/de-Googled posture. Translation is ephemeral (no cache, no schema change).

Changes

  • Deps: google_mlkit_translation + google_mlkit_language_id (both MIT), recorded in docs/SPEC.md.
  • Engine seam (mirrors P13b-1 OcrEngine): TranslationEngine + MlKitTranslationEngine (Android — OnDeviceTranslator + OnDeviceTranslatorModelManager + LanguageIdentifier) + UnavailableTranslationEngine + factory/provider; graceful off-Android. Pure translateLanguageForCode (BCP↔TranslateLanguage); new translateFailed error code.
  • Flow: overflow Translate… → target-language picker (default = app language, reusing the caption-language picker) → detect source → action-driven ~30 MB pack-download confirm (Wi-Fi) → translate. A pure translateReadiness decision (unavailable/notDetected/alreadyInTarget/needsDownload/ready) drives it.
  • State: a screen-scoped autoDispose itemTranslation(itemId) controller; description + transcript render translated with a "Translated from · Show original" toggle. Added a one-shot MetadataRepository.metadataForItem.
  • Scope: description + transcript only — the derived AI/TextRank summaries stay in the source language (→ BACKLOG).

Tests

dart format clean · flutter analyze No issues · flutter test 791 passed — including engine availability + BCP mapping, the translateReadiness truth table, and the controller with a fake TranslationEngine (translate populates description/transcript + langs; Show original toggle; description-only item). No schema change.

Honest notes

  • Owed APK spot-check (VERIFICATION → P13b-2): the native ML Kit translate/language-id calls + the ~30 MB pack download can't be CI-tested; the overflow→picker→download→translated-render widget flow is APK-verified (consistent with the OCR/whisper/generation boundary).
  • Ephemeral by design — re-translating re-runs ML Kit (instant once the pack is present). Caching, translating the summaries, and a language-pack management/delete UI are logged in BACKLOG.
  • A design correction made mid-build: the controller first read the metadata via the StreamProvider.future, which timed out in ProviderContainer tests (the temporary ref.read subscription was disposed before the drift stream emitted). Switched to a one-shot metadataForItem read — correct for a command and reliably testable.

This completes P13b's translation; P13b-3 (opt-in auto-OCR on download) remains a planned follow-up.

https://claude.ai/code/session_013JoYmLCosYt5tQ8qwdbL1T


Generated by Claude Code

Second half of P13b: a "Translate…" action on item detail translates an
item's description + transcript into the user's language, fully on-device
via ML Kit. No Google Play Services — language models download over HTTPS
(~30 MB, English pivot) and run offline after — fitting the sideloaded
posture. Translation is ephemeral (no cache/schema).

- Deps: google_mlkit_translation + google_mlkit_language_id (MIT).
- Engine seam: TranslationEngine + MlKitTranslationEngine (Android,
  OnDeviceTranslator + model manager + LanguageIdentifier) +
  UnavailableTranslationEngine + factory/provider; graceful off-Android.
  translateLanguageForCode (BCP↔TranslateLanguage); translateFailed code.
- Flow: overflow Translate… → target picker (default app language, reusing
  the caption-language picker) → detect source → action-driven ~30 MB pack
  download confirm (Wi-Fi) → translate. A pure translateReadiness decision
  drives it. Screen-scoped itemTranslation(itemId) controller (autoDispose).
- UI: description + transcript render translated with a "Translated from
  <src> · Show original" toggle. One-shot MetadataRepository.metadataForItem.
- Tests: engine availability + BCP mapping, translateReadiness truth table,
  controller with a fake engine. No schema change.
- Docs: P13-PLAN P13b-2 status, VERIFICATION P13b-2, SPEC deps, BACKLOG
  (translate summaries / cache / pack-management).

https://claude.ai/code/session_013JoYmLCosYt5tQ8qwdbL1T
@blokzdev blokzdev merged commit ae9472d into main Jun 2, 2026
1 check passed
@blokzdev blokzdev deleted the claude/p13b2-translation branch June 2, 2026 07:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants