Browser Extension
The popup
Section titled “The popup”Click the toolbar icon to open the popup. The header shows the current hostname and a badge with the number of keys collected on this page.
| Control | What it does |
|---|---|
| Target Language | Free-text field with autocomplete from the languages already stored for this domain. Any code the provider understands works (de, fr, es, …). |
| Translate | Scans the page if needed, then sends unknown keys to the translation server. Results are stored and applied as they stream in. |
| Auto-translate this site | Remembers the hostname and language, and translates the page automatically on later visits. |
| Scan Page | Re-walks the DOM and refreshes the key set for this domain. |
| Apply / Revert | Applies translations already in storage for the chosen language, or restores every original string. |
| Export Keys | Downloads _keys.json containing the current key set. |
| Import | Loads a translation JSON file into storage. |
| Scanned Keys | Expandable list of the collected keys and their source text. |
The floating toolbar
Section titled “The floating toolbar”Every page also gets a small draggable circle in the bottom-right corner (a globe button). It lives
in a closed shadow root with :host { all: initial }, so the host page’s CSS cannot affect it and
its own CSS cannot leak out. Clicking it opens a compact panel with a language field, a
Translate / Revert button, an Auto: <lang> indicator when auto-translate is on, and a
status line.
The language field is pre-filled from navigator.language, so the common case is one click. Set
TOOLBAR_ENABLED = false in extension/shared/constants.js to remove the toolbar entirely.
Typical flows
Section titled “Typical flows”Server-backed (fastest)
Section titled “Server-backed (fastest)”- Start the translation server (
./server/start.sh). - Open the page, click the toolbar circle or the extension popup.
- Enter a language code and press Translate.
- Text is replaced batch by batch as the server streams results back.
- Press Revert to restore the page.
Anything the server has translated before comes back from its SQLite cache immediately — the
cached event of the SSE stream is emitted before any provider call.
Fully manual (no server)
Section titled “Fully manual (no server)”- Open the page and press Scan Page.
- Press Export Keys to download
_keys.json. - Translate the
keysobject into a translation file (by hand, or withany-i18n translate). - Press Import and select that file.
- Choose the language and press Apply.
An imported file must contain _meta.domain, _meta.language, and a translations object;
otherwise the import is rejected with a format error. See
File Formats.
Shipping translations inside the extension
Section titled “Shipping translations inside the extension”Put translation files under extension/translations/<domain>/<lang>.json and list the domains in
extension/translations/manifest.json:
{ "_meta": { "version": "1.0.0", "description": "Translation manifest for any-i18n" }, "domains": { "example.com": { "languages": ["de", "fr"], "lastUpdated": "2026-01-15T11:00:00.000Z" } }}The service worker fetches that manifest on install and on every startup and indexes the listed
files into browser.storage.local, so bundled translations behave exactly like imported ones. A
missing or empty manifest is not an error — the shipped one has no domains.
Auto-translate
Section titled “Auto-translate”Toggling Auto-translate this site stores { language, enabled: true } for the hostname. On the
next load the content script:
- scans the page,
- applies whatever is already cached for that language,
- sends the still-untranslated keys to the server, and
- applies each partial result as it arrives.
Changing the language field while the toggle is on updates the stored language.
What gets translated
Section titled “What gets translated”- Visible text nodes with at least
MIN_TEXT_LENGTH(2) characters titleandaria-labelon any elementplaceholderon<input>and<textarea>alton<img>valueon<input type="submit|button|reset">
Ignored: SCRIPT, STYLE, NOSCRIPT, IFRAME, SVG, META, LINK, HEAD, TITLE, any
subtree marked translate="no", attributes of contenteditable elements, and strings made only of
digits, punctuation, or symbols.
Layout safety
Section titled “Layout safety”Translations are usually longer than the source. Two mechanisms limit the damage:
- the server annotates each string with a target maximum length and asks for concise phrasing
- translated elements receive
data-anyi18nand a defensive stylesheet withoverflow-wrap,word-break,white-space: normal, andmin-width: 0
Reverting removes the marker attributes again.
Permissions
Section titled “Permissions”storage, activeTab, and scripting, plus host_permissions for
http://localhost:39418/*. Content scripts match <all_urls> at document_idle — they need to run
everywhere by design, but the only network request the extension ever makes goes to the translation
server on your own machine.