ondict

command module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: MIT Imports: 38 Imported by: 0

README

简体中文 Coverage

Table of Contents


Introduction

Yet another simple dictionary application. Support multiple sources, including Longman online dictionary, and user-loaded MDX/MDD dictionary files.

视频介绍(简中)

Disclaimer

It is trying to be just a dictionary, which you may need during your English study or writing some English posts.

It is NOT a "translator", in which scenario an LLM model based tool is more suitable in modern days.

Web mode is RECOMMENDED, because both the online engine and MDX engine are based on HTML/CSS stuff. So when you need its output to be rendered as markdown, a independent parser and renderer need to written for each source, that's quite a lot of work and almost impossible.

I just write a simple markdown renderer for Longman Dictionary of Contemporary English MDX dictionary, which I uploaded in some releases, so that you can roughly use its markdown rendered output in some cases, such as working as a TUI(which has no "web core") editor plugin, or just using it in the terminal.

Other choices

There are some similar products. They are all mature products, but may not suit me(or you) in some cases. Compared to these, this application is not yet so well polished, but it has its own advantages.

  • It can serve as a CLI application, conforming to the UNIX stdout convention. So you can further process the output, or embed it into any UNIX-like CLI tools, then integrate it into your CLI/TUI based workflow very easily.
  • The output can be plain text(such as Markdown format), so feel free to render it with any renderer. You can also embed it into your extensible editor. I provide neovim integration out of the box.
  • The raw output(for MDX dictionaries especially) are just HTML/CSS/JavaScript, so your can just use it to build a server, which you can access anywhere by your browser, without having to install any other apps. E.g. Demo Website
  • Easy to cross platform. The core is written in Go.
  • It's free and open source, just fork/PR/issue it if you like!

Prerequisites

  • Go version >=1.16, and add $GOBIN in your $PATH
  • Neovim version >= 0.9.1 (recommended, because I developed it on this version, but previous versions may also use it, only some "lsp" utils (not lsp feature itself) are required. So it can also be ported to Vim with little effort theoretically, but I am not quite familiar with vim's popup feature yet)

Features

  • You can deploy it on your own server in Web/HTTP mode, no telemetry.
  • Online query support based on Longman online dictionary
  • Integrated with (n)vim, feel free to use it in whatever editor you are using!
  • In the offline mode(do not need extra online queries itself), MDX engine is supported. The online engine may be more comprehensive and updated, but they are slow since an HTTP request is made for the first time. The offline mode, however, can work without internet connection, but pre-loaded dictionary files are needed.
  • When vocab.db is built, offline definitions can also be searched by keyword through SQLite FTS.
  • Android app — a native APK that runs the full dictionary server on-device. Import your MDX files directly on the phone; the app auto-builds a SQLite cache so subsequent launches are fast.

Installation

go install github.com/ChaosNyaruko/ondict@latest

or

git clone https://github.com/ChaosNyaruko/ondict.git
make install

Initialization

After installation, you can run the initialization command to set up the configuration and download the default dictionary automatically.

ondict -init

It will guide you through:

  1. Creating the configuration directory and file.
  2. Downloading the default Longman Dictionary (MDX).
  3. Downloading the pronunciation/image data (MDD).
  4. Converting the dictionary to SQLite format for faster startup and definition search (Optional but recommended).

Android

Download the latest APK from the Releases page and install it on your phone.

Requirements: Android 11+ (API 36 target). Enable "Install from unknown sources" in your phone settings if installing outside the Play Store.

How it works

The Android app embeds the full Go dictionary server via gomobile. On launch it starts a local HTTP server on 127.0.0.1:1345 and displays the web UI in a WebView — the same interface as the desktop web mode.

Dictionary setup
  1. Open the app and tap Import Dict (or the menu button)
  2. Select your .mdx file from local storage
  3. Set the dictionary type (e.g. LONGMAN/Easy, MDX)
  4. Restart the app — on first launch with a new dictionary the app builds a SQLite cache in the background; subsequent launches load from SQLite and start in under a second
Data storage

All user data (imported dictionaries, word bank, query history) is stored in the app's private storage and survives app updates. Only uninstalling the app removes the data.

Using Docker and serving as a HTTP server in the containerFor your convenience, the config directory in the container is remapped/mounted to your host config directory, so all generated content(such as query history) will be dumped into this directory. No other pollution.

Local
docker build . -t ondict
docker run --rm --name ondict-app --publish 1345:1345 --mount type=bind,source={your $HOME/.config/ondict},target=/root/.config/ondict  ondict
Remote
docker run --rm --name ondict-app --publish 1345:1345 --mount type=bind,source={your $HOME/.config/ondict},target=/root/.config/ondict  chaosnyaruko/ondict:latest

A standalone MDX parser CLI tool

go install github.com/ChaosNyaruko/ondict/cmd/dumpdict@latest

It is used to install a "standalone" CLI tool that can decode MDX files, and dump them into a sqlite3 datebase file. See schema for more (the "vocab" table).

If you just want a decoder to parse your MDX files, this would be enough!

You can also choose the tokenizer used by the definition-search index:

dumpdict -f path/to/dict.mdx -fts-tokenizer trigram

Usage

Help

ondict 
ondict -h

Examples

Work as an HTTP server

A.K.A. Web mode, recommended.

This app can also serve as a HTTP server, allowing remote fetch and query, with cache and acceleration.

ondict -serve -listen=localhost:1345 -e=mdx

Launch a http request

curl "http://localhost:1345/?query=apple&engine=mdx&format=x"

Or just open your browser, visit localhost:1345 and you'll see!

Web Mode

If you are visiting the URL with a web browser, setting format to "html" is recommended. The browser will automatically render a more beautiful page than it is in the "CLI" interface.

The HTML server home page now has two modes:

  • Headword mode: jump directly to the entry page
  • Definition mode: search the SQLite FTS index and browse result cards

The HTML server also includes a dedicated Word Bank page at /words. Use the buttons on entry pages or definition search result cards to save words you want to learn, then open /words to review, revisit, or remove them. Word Bank is stored separately from normal query history in the Ondict config directory.

Merging databases (offline)

If you have multiple wordbank.db / history.db files from different machines (laptop + desktop, old phone + new phone), the ondict merge subcommand folds them into one with conflict resolution by update_time (last-writer-wins) and a per-row tombstone for deletions:

ondict merge wordbank --dst merged.db src1.db src2.db src3.db
ondict merge history  --dst merged.db src1.db src2.db [--dry-run]

For history, the merged count is MAX across sources (idempotent: re-merging the same source twice is a no-op).

See docs/adr/0001-wordbank-history-sync.md for the full design rationale.

Cloud sync (self-hosted)

A long-running ondict instance (your home box, NAS, VPS) can act as a sync server so a phone, laptop, or browser-only setup can converge on the same Word Bank and history. Endpoints live under /sync/v1 and use HTTP Basic Auth.

Server side (terminate TLS at your reverse proxy, e.g. Caddy / nginx):

export ONDICT_SYNC_USER=alice
export ONDICT_SYNC_PASSWORD='something-strong'
ondict -serve -listen=:1345 -sync-server -sync-data-dir=/var/lib/ondict/sync

Desktop client (one-shot or daemon):

export ONDICT_SYNC_USER=alice
export ONDICT_SYNC_PASSWORD='something-strong'
ondict sync --base-url https://sync.example.com                      # one-shot
ondict sync --base-url https://sync.example.com --loop 10m \
            --gc-tombstones-after 2160h                              # daemon, 90-day tombstone GC

Mobile (Android): mobile.ConfigureSync(baseURL, user, pass) followed by mobile.Sync() from your Activity. The Android app records its own query history starting with this release, so it propagates upstream too.

For the full deployment / migration guide (including how to convert an existing ~/.config/ondict/{wordbank,history}.db into a sync user library), see docs/sync-deployment.md.

You can also deploy it on your server, as an upstream of Nginx/, or just exposing it with a suitable ip/port.

You can run make serve locally for an easy example. My front-end skill is poor, so the page is ugly and rough, don't hate it :(.

There are still a lot of TODOs, feel free to give me PRs and contribute to the immature project, thanks in advance.

One-shot query

A one-shot query, it will take some time when you call it the first time, it needs some loading work. It will launch an local server using unix domain socket.

online engine (you don't have to specify the -e option):
ondict -q <word> [-e anything]

Gif

mdx engine (ldoce5):
ondict -q <word> -e mdx

Gif

definition search (SQLite-backed MDX):
ondict -q "kidney problem" -search-def -e mdx
One-shot query, but from remote server
ondict -q <word> -remote localhost:1345

Gif

A "repl" querier
ondict -i -e mdx

input .help for commands that can be used. Gif

Work with Neovim

See Integrated with Neovim Gif

For MacOS, work with hammerspoon

Gif

KNOWN BUGS:

If you use hammerspoon's "task" feature, i.e. "hs.task.new" and then "xx::start", some word queries will block the process, and can't see the result(because it hasn't returned yet), such as "test". But no such problems in real web mode, it only happens with hammerspoon.

Don't know why yet, the same word queries also works normally in Neovim integration, which also uses Lua as its async runtime. So I guess maybe it has something to do with the implementation, and it might be a bug of hammerspoon.

WORKAROUND

Using hs.execute instead of hs.task(Be careful with the shell-escaping), which is a "synchronous" method of executing a task. Normal query is fast enough and you won't notice the difference and will see the result "immediately". See for example

FZF-like completion

The web completion endpoint supports two modes:

  • Prefix mode (default): GET /complete?prefix=app
  • FZF-like fuzzy mode: GET /complete?prefix=apd&mode=fzf

The fuzzy mode is implemented in-process and does not require the external fzf binary.

The definition results page is served at:

  • GET /search?query=heart+attack&mode=definition&format=html

Integrated with FZF (experimental and MacOS only)

ondict -fzf

You should have FZF installed and have your ondict server listening on localhost:1345 (for now, developing) Gif

Configuration

config.json can include tokenizer settings for the definition-search index:

{
  "dicts": [
    {
      "name": "Longman Dictionary of Contemporary English",
      "type": "LONGMAN/Easy"
    }
  ],
  "search": {
    "definition_index": {
      "tokenizer": "unicode61"
    }
  }
}

Supported tokenizer values:

  • unicode61: default, best for English/token and phrase search
  • trigram: useful for substring-style matching and some CJK scenarios, but queries shorter than 3 characters are limited

How to use it in Neovim

Installation
require("lazy").setup({
  spec = {
    -- add your plugins here
    {
        "ChaosNyaruko/ondict",
        event = "VeryLazy",
        build = function(plugin)
            require("ondict").install(plugin.dir)
        end,
        dev = false,
        config = function()
            require("ondict").setup("localhost:1345") -- If you already have a running ondict server, you can just specify the address.
        end
    },
  },
  -- Configure any other settings here. See the documentation for more details.
  -- colorscheme that will be used when installing plugins.
  -- automatically check for plugin updates
  checker= { enabled = false },
})
Manually
cd ~/.local/share/nvim/site/pack/packer/start/
git clone https://github.com/ChaosNyaruko/ondict.git
cd ondict
go install .
Mapping examples
nnoremap <leader>d <cmd>lua require("ondict").query()<cr>
vnoremap <leader>d <cmd>lua require("ondict").query()<cr>
vim.keymap.set("n", "<leader>d", require("ondict").query)
vim.keymap.set("v", "<leader>d", require("ondict").query)

Offline dictionary files

Put dictionary files in $HOME/.config/ondict/dicts, support formats are:

  • "key-value" organized pairs JSON files.
  • MDX files, refer to mdict or pdawiki.

Configuration

XDG_CONFIG_HOME convention

// cd ~/.config/ondict
.
├── config.json
├── dicts
│   ├── LDOCE5++ V 1-35.mdd
│   ├── LDOCE5++ V 1-35.mdx
│   ├── LM5style.css
│   ├── LM5style_vanilla.css
│   ├── Longman Dictionary of Contemporary English.css
│   ├── Longman Dictionary of Contemporary English.mdx
│   ├── ODE_Zh.css
│   ├── ahd3af.css
│   ├── oald9.css
│   ├── oald9.mddx
│   └── oald9.mdx
├── history.db        # SQLite query history (synced)
├── history.table     # human-readable append-only log (desktop only, not synced)
├── wordbank.db       # SQLite saved-word bank (synced)
└── sync/             # only present on the sync server
    └── <user>/
        ├── wordbank.db
        └── history.db

An example of config.json

{
  "dicts": [
    {
      "name": "LDOCE5++ V 1-35",
      "type": "LONGMAN5/Online"
    },
    {
      "name": "Longman Dictionary of Contemporary English",
      "type": "LONGMAN/Easy",
      "css": "Longman Dictionary of Contemporary English"
    },
    {
      "name": "oald9",
      "css": "oald9"
    }
  ]
}

CSS loading

Each dictionary entry in config.json may carry an optional "css" field whose value is the stem (no .css extension) of a CSS file located in the dicts/ directory. When the server renders a dictionary entry as HTML it injects the matching CSS inside a <style> block so that MDX-specific formatting is applied.

CSS is resolved for every dictionary in this priority order:

  1. Explicit "css" field – e.g. "css": "oald9" loads dicts/oald9.css.
  2. Known-prefix auto-detect – dict names containing LDOCE5 automatically use LM5style.css without any config change.
  3. Global default – the top-level "default_css" key in config.json is tried as a last resort, e.g. "default_css": "LM5style".
  4. Nothing – if no CSS is resolved, or the file does not exist, the entry is rendered without extra styles.

Example with a global default:

{
  "default_css": "LM5style",
  "dicts": [
    { "name": "LDOCE5++ V 1-35", "type": "LONGMAN5/Online" },
    { "name": "oald9", "css": "oald9" }
  ]
}

TODOs

There are still a lot of TODOs, feel free to give me PRs and contribute to the immature project, thanks in advance.

LICENSE

LICENSE

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
dumpdict command
This program dumps a "MDX" format dictionary file into a sqlite database file.
This program dumps a "MDX" format dictionary file into a sqlite database file.
Package dbutil contains shared SQLite helpers used by the wordbank and history stores.
Package dbutil contains shared SQLite helpers used by the wordbank and history stores.
Package decoder provides a way to decode MDX/MDD file in a native way, rather than an external python scripts.
Package decoder provides a way to decode MDX/MDD file in a native way, rather than an external python scripts.
Package history records every word the user queries.
Package history records every word the user queries.
internal
httpserver
Package httpserver contains the shared Gin HTTP server used by both the desktop (main) and mobile entry points.
Package httpserver contains the shared Gin HTTP server used by both the desktop (main) and mobile entry points.
syncclient
Package syncclient is the client side of the cloud-sync protocol described in docs/adr/0001-wordbank-history-sync.md.
Package syncclient is the client side of the cloud-sync protocol described in docs/adr/0001-wordbank-history-sync.md.
syncserver
Package syncserver implements the cloud-sync HTTP endpoints described in docs/adr/0001-wordbank-history-sync.md.
Package syncserver implements the cloud-sync HTTP endpoints described in docs/adr/0001-wordbank-history-sync.md.
tmpl
Package tmpl exposes the embedded HTML templates so both the main server and the mobile entry point can share the same template files.
Package tmpl exposes the embedded HTML templates so both the main server and the mobile entry point can share the same template files.
Package mobile provides an entry point for gomobile to start the ondict HTTP server on Android.
Package mobile provides an entry point for gomobile to start the ondict HTTP server on Android.
Aho–Corasick algorithm Refer to https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm https://www.youtube.com/watch?v=O7_w001f58c https://www.youtube.com/watch?v=OFKxWFew_L0
Aho–Corasick algorithm Refer to https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm https://www.youtube.com/watch?v=O7_w001f58c https://www.youtube.com/watch?v=OFKxWFew_L0
Package store defines the storage interfaces used by wordbank and history, plus their SQLite-backed implementations.
Package store defines the storage interfaces used by wordbank and history, plus their SQLite-backed implementations.
Package syncmerge folds wordbank and history rows from one or more source stores into a destination store.
Package syncmerge folds wordbank and history rows from one or more source stores into a destination store.
Package wordbank exposes the user's saved word bank via a stable package-level API (Add / Remove / Contains / List / ...).
Package wordbank exposes the user's saved word bank via a stable package-level API (Add / Remove / Contains / List / ...).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL