@laisuk/opencc-fmmseg-wasm
v0.3.7
Published
WebAssembly bindings for opencc-fmmseg, a high-performance OpenCC-compatible Simplified/Traditional Chinese converter.
Maintainers
Readme
opencc-fmmseg-wasm
OpenCC FMM segmentation WebAssembly bindings for browsers and JavaScript runtimes.
This package provides high-quality Simplified Chinese ↔ Traditional Chinese conversion powered by the Rust
opencc-fmmseg engine.
Features:
- OpenCC-compatible conversion configs
- Pure WebAssembly (no native binaries)
- Browser-friendly
- TypeScript-friendly APIs
- Fast Rust backend
- FMM-based phrase segmentation
- Traditional Chinese regional variants
- Japanese Shinjitai conversion support
- Chinese script detection (
zho_check) - Optional CJK Compatibility Ideograph normalization
- In-memory Office / EPUB document conversion
- Zero-dependency Node.js CLI
Package profile:
- 0 runtime dependencies
- 1 WASM file
- 18 conversion configs
- 100% offline
Installation
npm install @laisuk/opencc-fmmseg-wasmQuick Start
import init, {
OpenccWasm,
DetofuLevelWasm
} from "@laisuk/opencc-fmmseg-wasm";
await init();
const cc = new OpenccWasm("s2t");
console.log(cc.convert("汉字", false));
// 漢字
console.log(cc.convertDetofu("儼驂騑於上路", false, DetofuLevelWasm.ExtB));
// 俨骖騑于上路Using Config Enums
import init, {
OpenccWasm,
OpenccConfigWasm
} from "@laisuk/opencc-fmmseg-wasm";
await init();
const cc = OpenccWasm.newWithEnum(
OpenccConfigWasm.S2hkp
);
console.log(cc.convert("别随便录影侵犯个人隐私权", false));
// 別隨便錄影侵犯個人私隱權Supported Configs
| Config | Enum | Description |
|---------|--------------------------|------------------------------------------------------|
| s2t | OpenccConfigWasm.S2t | Simplified Chinese → Traditional Chinese |
| s2tw | OpenccConfigWasm.S2tw | Simplified Chinese → Taiwan Traditional |
| s2twp | OpenccConfigWasm.S2twp | Simplified Chinese → Taiwan Traditional (phrases) |
| s2hk | OpenccConfigWasm.S2hk | Simplified Chinese → Hong Kong Traditional |
| s2hkp | OpenccConfigWasm.S2hkp | Simplified Chinese → Hong Kong Traditional (phrases) |
| t2s | OpenccConfigWasm.T2s | Traditional Chinese → Simplified Chinese |
| t2tw | OpenccConfigWasm.T2tw | Traditional Chinese → Taiwan Traditional |
| t2twp | OpenccConfigWasm.T2twp | Traditional Chinese → Taiwan Traditional (phrases) |
| t2hk | OpenccConfigWasm.T2hk | Traditional Chinese → Hong Kong Traditional |
| t2hkp | OpenccConfigWasm.T2hkp | Traditional Chinese → Hong Kong Traditional (phrases)|
| tw2s | OpenccConfigWasm.Tw2s | Taiwan Traditional → Simplified Chinese |
| tw2sp | OpenccConfigWasm.Tw2sp | Taiwan Traditional → Simplified Chinese (phrases) |
| tw2t | OpenccConfigWasm.Tw2t | Taiwan Traditional → Traditional Chinese |
| tw2tp | OpenccConfigWasm.Tw2tp | Taiwan Traditional → Traditional Chinese (phrases) |
| hk2s | OpenccConfigWasm.Hk2s | Hong Kong Traditional → Simplified Chinese |
| hk2sp | OpenccConfigWasm.Hk2sp | Hong Kong Traditional → Simplified Chinese (phrases) |
| hk2t | OpenccConfigWasm.Hk2t | Hong Kong Traditional → Traditional Chinese |
| hk2tp | OpenccConfigWasm.Hk2tp | Hong Kong Traditional → Traditional Chinese (phrases)|
| jp2t | OpenccConfigWasm.Jp2t | Japanese Shinjitai → Traditional Chinese |
| t2jp | OpenccConfigWasm.T2jp | Traditional Chinese → Japanese Shinjitai |
The numeric enum values match the vendored Rust backend. Existing values are unchanged; S2hkp = 17, Hk2sp = 18, T2hkp = 19, and Hk2tp = 20.
API
Constructor
const cc = new OpenccWasm("s2t");Parameters:
config(optional): OpenCC config string- default:
"s2t"
Example:
const cc = new OpenccWasm("t2s");Hong Kong phrase config example:
const cc = new OpenccWasm("s2hkp");
cc.convert("别随便录影侵犯个人隐私权", false);
// 別隨便錄影侵犯個人私隱權convert
cc.convert(text, punctuation)Parameters:
text: input stringpunctuation: whether to convert punctuation variants
Returns:
- converted string
Example:
cc.convert("汉字", false);normalizeCompat
Normalize Unicode CJK Compatibility Ideographs before conversion.
cc.normalizeCompat(text)Parameters:
text: input string
Returns:
- normalized string
Example:
const cc = new OpenccWasm("t2s");
const input = "天龍八部書裡的喬峰是契丹人";
const normalized = cc.normalizeCompat(input);
console.log(normalized);
// 天龍八部書裡的喬峰是契丹人
console.log(cc.convert(normalized, false));
// 天龙八部书里的乔峰是契丹人This is an optional pre-conversion pass for text that contains compatibility ideographs from Unicode compatibility ranges. Unmapped characters are preserved unchanged. Normal OpenCC conversion does not automatically run this pass, so call it explicitly when compatibility normalization is desired.
detofu
Replace tofu-risk rare CJK extension characters with display-compatible fallbacks.
cc.detofu(text, level)Parameters:
text: input stringlevel:DetofuLevelWasmthreshold for the CJK extension ranges to replace
Returns:
- detofu-safe string
Supported levels:
| Enum | CLI value |
|------------------------|-----------|
| DetofuLevelWasm.ExtB | ext-b |
| DetofuLevelWasm.ExtC | ext-c |
| DetofuLevelWasm.ExtD | ext-d |
| DetofuLevelWasm.ExtE | ext-e |
| DetofuLevelWasm.ExtF | ext-f |
| DetofuLevelWasm.ExtG | ext-g |
| DetofuLevelWasm.ExtH | ext-h |
| DetofuLevelWasm.ExtI | ext-i |
Example:
import init, {
OpenccWasm,
DetofuLevelWasm
} from "@laisuk/opencc-fmmseg-wasm";
await init();
const cc = new OpenccWasm("t2s");
const converted = cc.convert("儼驂騑於上路", false);
console.log(converted);
// 俨骖𬴂于上路
console.log(cc.detofu(converted, DetofuLevelWasm.ExtB));
// 俨骖騑于上路convertDetofu
Convert text and apply detofu in one call.
cc.convertDetofu(text, punctuation, level)Parameters:
text: input stringpunctuation: whether to convert punctuation variantslevel:DetofuLevelWasmthreshold for the CJK extension ranges to replace
Returns:
- converted detofu-safe string
Example:
cc.convertDetofu("儼驂騑於上路", false, DetofuLevelWasm.ExtB);
// 俨骖騑于上路setConfig
cc.setConfig("t2s");Returns:
trueif validfalseif invalid
getConfig
cc.getConfig();Returns current config string.
isValidConfig
OpenccWasm.isValidConfig("s2t");getSupportedConfigs
OpenccWasm.getSupportedConfigs();Returns all supported config strings.
Includes s2hkp, hk2sp, t2hkp, and hk2tp.
zhoCheck
Detect Chinese script type.
cc.zhoCheck(text);Returns:
| Value | Meaning |
|-------|---------------------|
| 0 | Unknown / mixed |
| 1 | Traditional Chinese |
| 2 | Simplified Chinese |
newWithCustomDicts
Construct a converter with in-memory custom dictionary pairs.
const cc = OpenccWasm.newWithCustomDicts(config, specs);Parameters:
config: OpenCC config string, such as"s2t"specs: array of custom dictionary specs
TypeScript-style spec shape:
type WasmCustomDictSpec = {
slot: string;
mode?: "Append" | "Override";
pairs: Array<[string, string]>;
};mode defaults to "Append" when omitted.
Each pairs entry is a [source, target] string tuple for the selected slot.
TypeScript example:
import init, {OpenccWasm} from "@laisuk/opencc-fmmseg-wasm";
await init();
const specs: WasmCustomDictSpec[] = [
{
slot: "STPhrases",
pairs: [
["云端", "雲端"]
]
}
];
const cc = OpenccWasm.newWithCustomDicts("s2t", specs);Practical example:
import init, {OpenccWasm} from "@laisuk/opencc-fmmseg-wasm";
await init();
const cc = OpenccWasm.newWithCustomDicts("s2t", [
{
slot: "STPhrases",
mode: "Append",
pairs: [
["帕兰蒂尔", "柏蘭蒂爾"],
["软件", "軟體"]
]
}
]);
console.log(cc.convert("帕兰蒂尔软件", false));
// 柏蘭蒂爾軟體Override example:
const cc = OpenccWasm.newWithCustomDicts("s2t", [
{
slot: "STPhrases",
mode: "Override",
pairs: [
["软件", "軟體"]
]
}
]);Override replaces the selected slot before inserting the provided pairs. It is powerful and should be used only when
the caller intentionally wants to discard built-in entries for that slot.
Custom dictionary specs identify the target dictionary slot by DictSlot name. Slot names are trimmed and normalized
case-insensitively for the known slots, so "stphrases", " STPhrases ", and "STPhrases" all select
STPhrases. Canonical names are recommended in TypeScript code and docs:
STPhrases
TSPhrases
STCharacters
TSCharacters
TWPhrases
TWPhrasesRev
HKPhrases
HKPhrasesRev
TWVariants
TWVariantsPhrases
TWVariantsRev
TWVariantsRevPhrases
HKVariants
HKVariantsPhrases
HKVariantsRev
HKVariantsRevPhrases
JPSCharacters
JPSCharactersRev
JPSPhrases
STPunctuations
TSPunctuationsSuffixes such as .txt are not accepted, even though case and surrounding whitespace are normalized. Use
"STPhrases" or "stphrases", not "STPhrases.txt".
Merge contract:
- Custom dictionaries are loaded from in-memory pairs only; no file I/O is involved.
- The embedded compressed CBOR dictionary is loaded first.
- Custom specs are applied to
DictionaryMaxlengthbeforeOpenCC::from_dictionary(...). - Conversion hot paths remain immutable after construction.
Appendmode merges into the selected slot.- Duplicate or conflicting keys use last-wins semantics.
Overridemode clears the selected slot first, then inserts the provided custom pairs.- Multiple specs are applied in array order.
This API is useful for browser apps, user-defined terminology, database-loaded terms, generated dictionaries,
localStorage or IndexedDB terms, testing, and embedded WASM environments. Customization happens at construction
time, not during conversion.
Office / EPUB Conversion
Office and EPUB conversion runs fully locally in the browser or Node.js. Files are passed in and returned as bytes; nothing is uploaded to a backend server.
This is useful for converting text inside:
docx, xlsx, pptx, odt, ods, odp, epubFile size is limited by available browser or Node.js memory, but there is no upload or server-side limit. Font
preservation is supported with the keepFont option.
Use the instance method when possible. It reuses the converter configuration and any custom dictionaries already held by
the OpenccWasm instance.
cc.convertOfficeBytes(inputBytes, format, punctuation, keepFont)Parameters:
inputBytes:Uint8Arraydocument bytesformat:docx,xlsx,pptx,odt,ods,odp, orepubpunctuation: whether to convert punctuation variantskeepFont: whether to preserve font declarations where supported
Returns:
- converted output bytes
The older free function remains available for compatibility:
convert_office_bytes(inputBytes, format, config, punctuation, keepFont)Browser Office Example
import init, {OpenccWasm} from "@laisuk/opencc-fmmseg-wasm";
await init();
const cc = new OpenccWasm("s2t");
const file = document.querySelector("input[type=file]").files[0];
const inputBytes = new Uint8Array(await file.arrayBuffer());
const outputBytes = cc.convertOfficeBytes(
inputBytes,
"docx",
true,
true
);
const blob = new Blob([outputBytes], {
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "converted.docx";
a.click();
URL.revokeObjectURL(a.href);Node.js Office Example
import fs from "fs";
import init, {OpenccWasm} from "@laisuk/opencc-fmmseg-wasm";
await init();
const cc = new OpenccWasm("s2t");
const inputBytes = fs.readFileSync("input.docx");
const outputBytes = cc.convertOfficeBytes(
inputBytes,
"docx",
true,
true
);
fs.writeFileSync("output.docx", outputBytes);Browser Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OpenCC WASM Demo</title>
</head>
<body>
<script type="module">
import init, {
OpenccWasm
} from "./pkg/opencc_fmmseg_wasm.js";
await init();
const cc = new OpenccWasm("s2t");
console.log(
cc.convert("汉字", false)
);
</script>
</body>
</html>Note
Normally,
await init();is sufficient when using the published npm package.When running directly from a local repository checkout (for example in tests or development scripts), initialize using explicit WASM bytes:
import fs from "fs"; import init from "../pkg/opencc_fmmseg_wasm.js"; const wasmBytes = fs.readFileSync( "../pkg/opencc_fmmseg_wasm_bg.wasm" ); await init({ module_or_path: wasmBytes });
Node.js CLI
The package includes a zero-dependency Node.js CLI:
opencc-fmmseg convert -i input.txt -o output.txt -c s2t -p
opencc-fmmseg convert -i input.txt -o output.txt -c t2s -p --detofu all
echo "别随便录影侵犯个人隐私权" | opencc-fmmseg convert -c s2hkp
echo "天龍八部書裡的喬峰是契丹人" | opencc-fmmseg convert -c t2s --norm-compat
// 天龙八部书里的乔峰是契丹人
echo "這個細路哥很靈活" | opencc-fmmseg convert -c hk2sp --custom-dict hkphrasesrev:append:my_hk_dict.txt
// 这个小男孩很灵活my_hk_dict.txt:
# Custom Dictionary
細路哥 小男孩opencc-fmmseg office -i input.docx -o output.docx -c s2t -p --keep-fontText Conversion Options
-i, --input <file> Input text file; stdin if omitted
-o, --output <file> Output text file; stdout if omitted
-c, --config <conversion> Conversion config (default: s2t)
-p, --punct Enable punctuation conversion
--detofu [level] Replace tofu-risk rare CJK extension chars after conversion
level: all | ext-b | ext-c | ext-d | ext-e | ext-f | ext-g | ext-h | ext-i
default when omitted value: all
--keep-ids Preserve complete IDS expressions during conversion (default: false)
-n, --norm-compat Normalize CJK Compatibility Ideographs before conversion (default: false)
-D, --custom-dict <slot:mode:file>
Load a custom dictionary.
May be specified multiple times.
Examples:
--custom-dict hkphrasesrev:append:my_hk_dict.txt
--custom-dict stphrases:override:terms.txt
--in-enc <encoding> Input encoding (default: utf8)
--out-enc <encoding> Output encoding (default: utf8)Supported conversion configs:
s2t, s2tw, s2twp, s2hk, s2hkp, t2s, t2tw, t2twp, t2hk, t2hkp,
tw2s, tw2sp, tw2t, tw2tp, hk2s, hk2sp, hk2t, hk2tp, jp2t, t2jpOffice / EPUB Options
-i, --input <file> Input Office / EPUB file
-o, --output <file> Output file
-c, --config <conversion> Conversion config (default: s2t)
-p, --punct Enable punctuation conversion
-f, --format <format> docx | xlsx | pptx | odt | ods | odp | epub
-F, --convert-filename Convert generated output filename stem (default: false)
--keep-font Preserve font-family information (default)
--no-keep-font Do not preserve font-family information
--custom-dict <slot:mode:file>
Load a custom dictionary.
May be specified multiple times.
Examples:
--custom-dict hkphrasesrev:append:my_hk_dict.txt
--custom-dict stphrases:override:terms.txtFor office, the format is inferred from the input file extension when --format is omitted.
If -o, --output is omitted, office writes:
<input-name>_converted.<ext>TypeScript Support
The package includes generated TypeScript definitions from wasm-bindgen.
The WASM-facing enum is exported as OpenccConfigWasm, alongside OpenccWasm.
OpenccConfigWasm.S2hkp, OpenccConfigWasm.Hk2sp, OpenccConfigWasm.T2hkp, and
OpenccConfigWasm.Hk2tp are available for Hong Kong phrase conversions and map to backend config IDs 17 through 20.
Performance Notes
- WebAssembly build disables Rayon parallelism by default.
- Dictionaries are embedded into the WASM binary.
- Browser caching significantly improves subsequent loads.
Related Projects
- Rust backend: https://github.com/laisuk/opencc-fmmseg
- C API: https://github.com/laisuk/opencc-fmmseg/tree/master/capi/opencc-fmmseg-capi
- .NET: https://github.com/laisuk/OpenccNet
- Python: https://github.com/laisuk/opencc_purepy
License
MIT
