Skip to content

JavaScript API

The JavaScript bindings are distributed as @odict/node on npm. They are native extensions built with NAPI-RS and also support the browser via WASI.

Terminal window
npm install @odict/node

Requires Node.js 12+. Native binaries are included for all major platforms (macOS, Linux, Windows, ARM64, WASI).

import { readFile } from "node:fs/promises";
import { compile, OpenDictionary } from "@odict/node";
// Compile XML to a buffer
const xml = await readFile("my-dictionary.xml", "utf-8");
const data = compile(xml);
const dictionary = new OpenDictionary(data);
const results = dictionary.lookup("hello");
console.log(results[0].entry.term); // "hello"

Compiles an ODXML string into binary .odict data. Returns a Buffer that can be passed to new OpenDictionary().

import { compile } from "@odict/node";
const data = compile(`
<dictionary>
<entry term="hi">
<ety><sense><definition value="greeting"/></sense></ety>
</entry>
</dictionary>
`);

The main class for working with compiled dictionaries.

Creates a dictionary from compiled binary data (as returned by compile()) or directly from an XML string.

import { compile, OpenDictionary } from "@odict/node";
// From compiled buffer
const data = compile(xmlString);
const dictionary = new OpenDictionary(data);
// Directly from XML string
const dictionary = new OpenDictionary(xmlString);

OpenDictionary.load(dictionary: string, options?: LoadOptions): Promise<OpenDictionary>

Section titled “OpenDictionary.load(dictionary: string, options?: LoadOptions): Promise<OpenDictionary>”

Loads a dictionary from a file path or remote identifier. Returns a Promise.

  • If dictionary is a path to a .odict file, it loads from disk.
  • If it matches the format org/lang (e.g. wiktionary/eng), it downloads from the remote registry.
import { OpenDictionary } from "@odict/node";
// Load from file
const dictionary = await OpenDictionary.load("./my-dictionary.odict");
// Load from remote registry
const dictionary = await OpenDictionary.load("wiktionary/eng");
// Load with options
const dictionary = await OpenDictionary.load("wiktionary/eng", {
configDir: "./config",
remote: { caching: true, retries: 3 },
});
PropertyTypeDescription
minRanknumber | nullThe minimum rank value across all entries, or null if no entries have ranks
maxRanknumber | nullThe maximum rank value across all entries, or null if no entries have ranks

save(path: string, options?: SaveOptions): void

Section titled “save(path: string, options?: SaveOptions): void”

Saves the dictionary to disk as a .odict file.

dictionary.save("output.odict");
dictionary.save("output.odict", {
compress: { quality: 11, windowSize: 22 },
});

lookup(query: string | string[], options?: LookupOptions): LookupResult[]

Section titled “lookup(query: string | string[], options?: LookupOptions): LookupResult[]”

Looks up one or more terms by exact match.

ParameterTypeDefaultDescription
querystring | string[]Term(s) to look up
options.splitnumberMinimum word length for compound splitting
options.followbooleanFollow see cross-references until an entry with etymologies is found
options.insensitivebooleanEnable case-insensitive matching
// Simple lookup
const results = dictionary.lookup("cat");
// Multiple terms
const results = dictionary.lookup(["cat", "dog"]);
// Follow cross-references, case-insensitive
const results = dictionary.lookup("RaN", {
follow: true,
insensitive: true,
});
// results[0].entry.term === "run"
// results[0].directedFrom?.term === "ran"
// Compound word splitting
const results = dictionary.lookup("catdog", { split: 3 });

split(query: string | string[], options?: SplitOptions): LookupResult[]

Section titled “split(query: string | string[], options?: SplitOptions): LookupResult[]”

Splits one or more compound terms into component dictionary entries. Unlike lookup(query, { split }), this does not try the whole query first.

ParameterTypeDefaultDescription
querystring | string[]Term(s) to split
options.minLengthnumberMinimum character length for each segment
options.followbooleanFollow see cross-references
options.insensitivebooleanEnable case-insensitive matching
const splitResults = dictionary.split("catdog", { minLength: 3 });
const insensitiveResults = dictionary.split("CATdog", {
minLength: 3,
insensitive: true,
});

Returns all terms defined in the dictionary, sorted alphabetically.

const words = dictionary.lexicon();
// ["cat", "dog", "run", ...]

Creates a full-text search index for the dictionary.

dictionary.index();
dictionary.index({ overwrite: true, memory: 50_000_000 });

search(query: string, options?: SearchOptions): Entry[]

Section titled “search(query: string, options?: SearchOptions): Entry[]”

Runs a full-text search. Requires an index (call index() first).

dictionary.index();
const results = dictionary.search("domesticated mammal");
const results = dictionary.search("greeting", { limit: 5 });

tokenize(text: string, options?: TokenizeOptions): Token[]

Section titled “tokenize(text: string, options?: TokenizeOptions): Token[]”

Tokenizes text and matches each token against the dictionary. Supports Chinese, Japanese, Korean, Thai, Khmer, German, Swedish, and Latin-script languages.

const tokens = dictionary.tokenize("the cat ran");
for (const token of tokens) {
console.log(token.lemma, token.entries);
}
// With options
const tokens = dictionary.tokenize("DOG cat", {
insensitive: true,
follow: true,
});

interface LookupResult {
entry: Entry;
directedFrom?: Entry;
}
interface Entry {
term: string;
rank?: number;
seeAlso?: string;
etymologies: Etymology[];
media: MediaURL[];
}
interface Etymology {
id?: string;
pronunciations: Pronunciation[];
description?: string;
senses: Sense[];
}
interface Sense {
pos: EnumWrapper;
lemma?: string;
definitions: Array<Definition | Group>;
tags: string[];
translations: Translation[];
forms: Form[];
}
interface Definition {
id?: string;
value: string;
examples: Example[];
notes: Note[];
}
interface Group {
id?: string;
description: string;
definitions: Definition[];
}
interface Example {
value: string;
translations: Translation[];
pronunciations: Pronunciation[];
}
interface Note {
id?: string;
value: string;
examples: Example[];
}
interface Pronunciation {
kind?: EnumWrapper;
value: string;
media: MediaUrl[];
}
interface MediaUrl {
src: string;
mimeType?: string;
description?: string;
}
interface Token {
lemma: string;
language?: string;
entries: LookupResult[];
kind: string;
script: string;
start: number;
end: number;
}
interface EnumWrapper {
name: string;
variant: string;
value: string;
}
interface LoadOptions {
configDir?: string;
remote?: RemoteLoadOptions;
}
interface RemoteLoadOptions {
outDir?: string;
caching?: boolean;
retries?: number;
}
interface SaveOptions {
compress?: CompressOptions;
}
interface CompressOptions {
quality?: number;
windowSize?: number;
}
interface LookupOptions {
split?: number;
follow?: boolean;
insensitive?: boolean;
}
interface IndexOptions {
directory?: string;
memory?: number;
overwrite?: boolean;
}
interface SearchOptions {
directory?: string;
threshold?: number;
autoindex?: boolean;
limit?: number;
}
interface TokenizeOptions {
follow?: boolean;
allowList?: string[];
insensitive?: boolean;
}

The @odict/node package also supports browser environments via WASI. Import from the browser entry point:

import { compile, OpenDictionary } from "@odict/node/browser";