The Four Components
(a) Injected Scripts — run inside each webpage
(a) Injected Scripts — run inside each webpage
Every HTTP/HTTPS page is injected with a complete copy of the Zotero translation framework. The injected bundle (defined by the
injectInclude array in gulpfile.js) includes the full translate engine, HTTP utilities, proxy support, sandbox manager, and the Zotero.Inject namespace that bootstraps everything.A Zotero.Translate.Web instance orchestrates translator detection and runs individual translators against the current page. Custom classes for translator retrieval (src/common/translators.js) and item saving (src/common/itemSaver.js) replace the desktop equivalents and proxy calls through to the background process.(b) Background Process — persistent middle-layer
(b) Background Process — persistent middle-layer
The background process (an event page in MV2 / a service worker in MV3) maintains a cache of translator metadata, performs the initial URL-match translator detection, updates the toolbar icon and badge, stores connector preferences, and routes translated items to Zotero or zotero.org.Browser-specific entry points are
src/browserExt/background.js (shared logic for the Zotero.Connector_Browser namespace) and src/browserExt/background-worker.js (the MV3 service-worker bootstrap that importScripts all background files including keep-mv3-alive.js).(c) Zotero Desktop — connector HTTP server on port 23119
(c) Zotero Desktop — connector HTTP server on port 23119
When Zotero is open it runs a connector HTTP server on port 23119. Calls to
Zotero.Connector.callMethod(endpoint) in the connector codebase translate directly into HTTP requests to this server. The server API accommodates saving items, retrieving translator metadata, checking online status, and more.Communication is always connector-initiated. Zotero cannot reach out to the connector on its own.
The Save Flow
1
User clicks the toolbar button
browser.action.onClicked fires in the background process. _browserAction(tab) is called, which checks for available translators stored in _tabInfo[tab.id].2
Background kicks off translation
Zotero.Connector_Browser.saveWithTranslator(tab, i) calls Zotero.Messaging.sendMessage("translate", [instanceID, translatorID, options], tab, null), broadcasting to all frames of that tab.3
Injected script receives the translate message
The
translate message listener registered during Zotero.Inject._addMessageListeners() fires. It checks instanceID to target the correct frame and delegates to Zotero.PageSaving.onTranslate(...).4
Translators run inside the page
Zotero.Translate.Web runs detectWeb() and then doWeb() in the translator sandbox managed by Zotero.Translate.SandboxManager. Item data is collected in the page context.5
Items are sent to Zotero (or zotero.org)
Zotero.ItemSaver (in the background) calls Zotero.Connector.callMethod("saveItems", data), which POSTs to http://127.0.0.1:23119/connector/saveItems. If Zotero is offline the fallback path through Zotero.API is taken instead.Key Source Files
Architecture Pages
Inject Scripts
How the full translation framework is injected into webpages and how
Zotero.Inject bootstraps translator detection.Background Process
The persistent middle-layer: translator cache, MV2 vs MV3 differences, offscreen documents, and the keep-alive mechanism.
Message Passing
The typed MESSAGES registry, monkey-patching, hook functions, and Chrome-specific payload chunking.
