Dictionaries

Gukhanmun looks up hanja readings from one or more HanjaDictionary implementations. The gukhanmun crate ships with FST and CDB backends and the bundled Standard Korean Dictionary, plus the Open Korean Dictionary (우리말샘) North Korean dictionary used by the ko-kp preset.

Using the bundled dictionary

The bundled dictionary selected by the preset is included automatically. To disable every bundled dictionary and rely only on user dictionaries or fallback readings:

let converter = Builder::with_preset(Preset::KoKr)
    .no_bundled_dictionaries()
    .build()?;

Use no_bundled_stdict() or no_bundled_opendict() to disable only one bundled dictionary family. To re-enable the Standard Korean Dictionary explicitly after calling no_bundled_stdict():

builder.bundled_stdict();

Use the ko-kp preset for North Korean orthography. It disables the initial sound law and includes the bundled Open Korean Dictionary (우리말샘) North Korean (北韓語) dictionary:

let converter = Builder::with_preset(Preset::KoKp).build()?;
assert_eq!(converter.convert_text_to_string("歷史와 來日")?, "력사와 래일");

To keep the ko-kp orthographic options but disable its bundled Open Korean Dictionary data:

let converter = Builder::with_preset(Preset::KoKp)
    .no_bundled_opendict()
    .build()?;

Loading a dictionary from a file

Requires the fst or cdb feature.

use gukhanmun::FstDictionary;  // or CdbDictionary

let dict = FstDictionary::open("custom.gukfst")?;
let converter = Builder::with_preset(Preset::KoKr)
    .push_dictionary(dict)
    .build()?;

Dictionaries added with push_dictionary are consulted before the bundled dictionary. The first match across the chain wins.

Zero-copy static dictionaries

Embed a dictionary directly in your binary with include_bytes! and load it without any file I/O:

use gukhanmun::FstDictionary;

static MY_DICT: &[u8] = include_bytes!("../data/custom.gukfst");

let dict = FstDictionary::from_static_bytes(MY_DICT)?;

from_static_bytes does not copy the data; it creates a zero-copy view backed by the static slice.

Loading from owned bytes

When the bytes come from a runtime source (network, database, etc.) wrap them in an Arc<[u8]>:

use std::sync::Arc;
use gukhanmun::CdbDictionary;

let bytes: Vec<u8> = std::fs::read("custom.gukcdb")?;
let dict = CdbDictionary::from_bytes(Arc::from(bytes.as_slice()))?;

Chaining multiple dictionaries

ChainDictionary lets you compose several dictionaries with explicit priority ordering. The first dictionary in the chain that has a match wins:

use gukhanmun::{ChainDictionary, FstDictionary, CdbDictionary, HanjaDictionary};

let domain_dict = FstDictionary::open("legal.gukfst")?;
let names_dict = CdbDictionary::open("names.gukcdb")?;
let chain = ChainDictionary::from_iter([
    Box::new(domain_dict) as Box<dyn HanjaDictionary>,
    Box::new(names_dict),
]);

let converter = Builder::with_preset(Preset::KoKr)
    .no_bundled_stdict()
    .push_boxed_dictionary(Box::new(chain))
    .build()?;

Alternatively, call push_dictionary multiple times; dictionaries are probed in the order they were pushed, before the bundled dictionary.

Composing Open Korean Dictionary categories

When the opendict feature is enabled, Rust callers can load the Open Korean Dictionary general, North Korean, dialect, and archaic categories directly. The ko-kp preset includes the North Korean category automatically, but dialect and archaic data are opt-in:

use gukhanmun::{Builder, ChainDictionary, HanjaDictionary, Preset};

let chain = ChainDictionary::from_iter([
    Box::new(gukhanmun::opendict::dialect()) as Box<dyn HanjaDictionary>,
    Box::new(gukhanmun::opendict::archaic()),
]);

let converter = Builder::with_preset(Preset::KoKr)
    .push_boxed_dictionary(Box::new(chain))
    .build()?;

Building a custom dictionary

The .gukfst and .gukcdb files loaded above are compiled artifacts, built from a plain text table with the gukhanmun-mkdict tool. See Building a custom dictionary in the CLI guide for how to author and compile dictionary sources.