Instant definitions, IPA pronunciation, etymology, and synonyms β fully offline.
Double-click any word on any webpage for a clean tooltip. Open the popup (Ctrl+Alt+S) to look up any word with full detail. No API keys. No internet required after setup. Works on Firefox and Chrome/Edge (Manifest V3).
| Feature | Detail | |
|---|---|---|
| π | 1.3M+ words | Full English Wiktionary β far more coverage than typical offline dictionaries |
| π | IPA + Text-to-speech | Phonetic notation (e.g. /ΛhΙl.oΚ/) + browser-native TTS, zero extra permissions |
| π | Etymology | Word origin and history from Wiktionary |
| π | Synonyms & antonyms | Shown per definition, sourced from Wiktionary sense data |
| π | Inline tooltip | Double-click any word on any webpage |
| π | Dark / Light / System theme | Follows OS preference by default, overridable in Settings |
| β‘ | Smart stemming | "running" β looks up "run"; "cats" β "cat", with a stem notice |
| πΎ | LRU cache | Last 20 lookups cached for instant re-lookup |
| β¨οΈ | Keyboard shortcut | Ctrl+Alt+S / Cmd+Alt+S β customisable in Settings |
git clone https://github.com/aetiss/dictionary_browser_extension.git
cd dictionary_browser_extension
npm installOption A β Download pre-built (~60 MB, ~30 seconds)
node scripts/download-data.jsFetches pre-processed data/*.json files from the latest GitHub release.
Option B β Build from Wiktionary source (~230 MB download, 5β10 min)
node scripts/prepare-wiktionary.jsStreams directly from kaikki.org and builds locally. Use this for the absolute latest Wiktionary data or when developing the pipeline.
Firefox
- Go to
about:debugging#/runtime/this-firefox - Load Temporary Add-on β select
manifest.json
Chrome / Edge
chrome://extensionsβ enable Developer mode- Load unpacked β select the project folder
No build step. Save a file β reload the extension β changes are live.
kaikki.org (Wiktionary extract, ~230 MB)
β
βΌ
scripts/prepare-wiktionary.js β full pipeline, runs locally or in data-release CI
β streams JSONL, miniEntry() trims to ~200 bytes/entry, stripEntry() formats
βΌ
data/{a-z,misc}.json β gitignored, ~60 MB total
β
βΌ (alternatively)
scripts/download-data.js β downloads pre-built data from GitHub release assets
| Script | Source | Words | IPA | Etymology | Antonyms | Use case |
|---|---|---|---|---|---|---|
prepare-wiktionary.js |
Wiktionary via kaikki.org | 1.3M+ | β | β | β | Local dev Β· Releases |
prepare-wordset.js |
Wordset Dictionary | 108k | β | β | β | CI E2E (fast, 30 s) |
download-data.js |
GitHub release assets | same as Wiktionary | β | β | β | Quick local setup |
The data/ directory is gitignored β it is built by a prepare script and published as a release asset (dictionary-data.tar.gz) by the data-release CI workflow on every tagged release.
Webpage
ββ content.js double-click capture Β· inline tooltip rendering
β runtime.sendMessage
βΌ
Popup (browserAction/)
ββ script.js orchestration: capture β validate β cache β lookup β render
ββ dictionary.js lazy-loads data/{letter}.json, caches in session memory
ββ util.js LRU cache Β· DOM rendering Β· validateKeyword()
Options (options/)
ββ options.js keyboard shortcut (browser.commands) Β· theme (storage)
Lookup flow:
double-click word on page
β content.js getSelectedText()
β popup runtime.sendMessage β getKeyword
β validateKeyword (reject multi-word)
β checkCache (browser.storage.local, LRU-20)
β dictionary.lookupWord(word) β lazy fetch data/{letter}.json
if miss β stemmer fallback (strips suffixes, retries)
β setDefinition(entry, stemInfo) β populates IPA, etymology, defs, syn/ant
β setCache(word, entry, stemInfo)
Stripped entry shape (data/a.json etc.):
{
"apple": {
"word": "apple",
"ipa": "/ΛΓ¦p.Ιl/",
"etymology": "From Middle English appel, from Old English Γ¦ppelβ¦",
"meanings": [
{
"def": "A common round fruit produced by the apple tree.",
"speech_part": "noun",
"example": "I ate an apple.",
"synonyms": ["pome"],
"antonyms": []
}
]
}
}npm test # 101 unit tests β no external dependencies, fast
npm run test:e2e # Playwright E2E (requires data/ to exist)
npm run test:all # bothUnit tests use Node's built-in node:test and node:vm β no Jest, no Mocha.
browserAction/
index.html popup UI
script.js orchestration + TTS handler
dictionary.js data loader (lazy per-letter fetch + session cache)
util.js LRU cache Β· DOM renderer Β· keyword validator
style.css popup styles (Solarized Earthy palette)
content.js injected into all web pages
content.css tooltip styles (scoped via dict-ext- prefix)
options/
options.html/js/css keyboard shortcut + theme settings
manifest.json MV3 manifest, gecko ID for Firefox AMO
scripts/
prepare-wiktionary.js full Wiktionary pipeline β data/
prepare-wordset.js quick Wordset pipeline β data/ (CI use)
download-data.js download pre-built data from GitHub releases
tests/
background.test.js background service worker tests
content.test.js tooltip and message handling tests
util.test.js cache, DOM rendering, keyword validation tests
prepare-wordset.test.js Wordset pipeline tests
prepare-wiktionary.test.js extractIPA, stripEntry, POS mapping tests
e2e.spec.js Playwright full-browser tests
data/ β gitignored, generated by prepare scripts
const api = globalThis.browser ?? globalThis.chrome;Firefox provides browser.* (Promise-based). Chrome provides chrome.*. The shim covers all api.runtime, api.storage, api.commands, api.tabs calls.
- Bump
versioninmanifest.jsonandpackage.json - Create and push a tag:
git tag v4.x.x && git push origin v4.x.x - Create a GitHub release for that tag
- The
data-releaseworkflow triggers automatically:- Builds Wiktionary data on a GitHub Actions runner
- Publishes
dictionary-data.tar.gzas a release asset
- Submit updated extension files to Firefox AMO and/or the Chrome Web Store
| Workflow | Trigger | Jobs |
|---|---|---|
ci.yml |
Push / PR to master |
Unit tests Β· Playwright E2E Β· Manifest lint |
data-release.yml |
GitHub release published | Build Wiktionary data Β· Upload dictionary-data.tar.gz |
E2E tests in CI use the fast prepare-wordset.js script (~30 s) so the pipeline stays quick. The full Wiktionary pipeline only runs on releases.
| Permission | Why |
|---|---|
activeTab |
Read selected text from the active tab |
storage |
Persist the 20-word LRU cache and user theme/shortcut settings |
No network access during normal use. No tracking. No telemetry.
MIT Β· Dictionary data from Wiktionary (CC BY-SA 3.0) via kaikki.org.