stardance has been extended another month! the new deadline is october 31 :)

You are browsing as a guest. Sign up (or log in) to start making projects!

3h 36m 33s logged

Devlog

TL;DR

  • Translation: Experimented with local NLLB and Google Translate, weighing privacy against performance.
  • Architecture: Moved translation into an offscreen document with a dedicated Web Worker.
  • Performance: Added caching, task scheduling, and bounded concurrency.
  • OCR: Improved error handling, caching, and image processing reliability.
  • Release: Brought the core features together for Image Translate v0.1.0.

Privacy vs. performance

My original goal was to keep everything local, so users wouldn’t have to send their text to an external service. However, NLLB-200 comes with a hefty model size of around 2.4 GB, which can put serious pressure on browser memory.

I experimented with Google Translate as an alternative. It’s much lighter on the user’s device, but there’s a trade-off: text sent for translation leaves the device and is processed by a third-party service. That means giving up some privacy for convenience and lower resource usage.

Neither approach is perfect. Local inference costs memory and performance; hosted translation introduces an external data dependency. I’m still figuring out the right balance for an extension whose original motivation was privacy.

Moving heavy work out of the background

Chrome’s Manifest V3 service worker isn’t ideal for heavy inference. I moved translation into an offscreen document and added a dedicated Web Worker for model inference. The background script now mainly routes messages.

I also switched to runtime.connect ports for longer-running communication to reduce messaging failures when the service worker gets suspended.

Caching and scheduling

Repeated requests were wasting time, so I added an L1 memory cache and an L2 IndexedDB cache, using SHA-256 keys to identify repeated requests.

A priority queue, bounded concurrency, and admission control help prevent pages containing lots of images from overwhelming the extension.

Debugging wasn’t fun

I ran into WebGPU/WASM initialization failures, an OCR crash caused by getContext is not a function, and InvalidCharacterError from malformed Base64 data.

Turns out, running an ML model is only half the battle. Browser APIs, cross-origin restrictions, and memory limits can be just as frustrating.

Making OCR more reliable

I switched batch processing to Promise.allSettled, allowing individual images to fail without breaking the whole batch. OCR results are cached locally with a seven-day TTL, and the popup now tracks errors per item.

I also added script detection, a tinyld fallback, text normalization, OCR region grouping, and token protection to support the translation pipeline.

What’s next?

Image Translate v0.1.0 brings together automatic image and canvas detection, PaddleOCR, translation, hover popups, caching, domain settings, and error tracking.

The next challenge is finding a sensible balance between translation quality, memory usage, and privacy. Ideally, users should have a clear choice between local translation and hosted services rather than having that trade-off hidden from them.

0
12

Comments 0

No comments yet. Be the first!