Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mdict-conversion-tools

Small, dependency-light Python scripts for building and maintaining MDict (.mdx / .mdd) dictionaries: convert other dictionary formats into .mdx, inspect what a .mdx contains, and fix up the support files (.css, .mdd) that MDict and GoldenDict need on the desktop.

These were written while consolidating a large personal English-dictionary library. They are deliberately simple, single-file, and easy to read and adapt — not a framework.

Layout

tools/       reusable command-line utilities
examples/    worked one-off converters kept as reference (see examples/README.md)
requirements.txt

Install

python3 -m pip install -r requirements.txt

Core dependencies:

package used for
mdict-utils packing the .mdx (writer.pack / pack_mdx_txt)
readmdict reading .mdx / .mdd back (verification, extraction)
pyglossary reading StarDict .ifo, Babylon .bgl, some .dsl
pillow only for glyph-montage inspection (see examples)
mobi only for the Kindle MOBI example

Tools

tools/dsl2mdx.py — Lingvo DSL → MDX

Lenient DSL parser. Handles .dsl and dictzip/gzip .dsl.dz, auto-detects encoding, converts the common [b] [i] [mN] [ref] <<...>> markup to HTML, turns cross-references into entry:// links and alternate headwords into @@@LINK= redirects. Unknown tags are dropped rather than aborting the entry — this is the reason it exists, since pyglossary's DSL reader silently loses entries on non-standard markup.

python3 tools/dsl2mdx.py input.dsl.dz "output.mdx" "My Dictionary" "Optional description"

tools/stardict2mdx.py — StarDict / DSL / BGL → MDX

Wraps pyglossary's readers and emits a single .mdx. Give it a directory (it picks the largest .ifo / .dsl / .bgl / .mdx inside) or a direct file path. If handed an existing .mdx it just copies it along with its .css / .mdd / image siblings.

python3 tools/stardict2mdx.py ./stardict-folder "output.mdx" "Title"

tools/mdx_inspect.py — read header metadata

Prints Title / Description / Encoding / Encrypted / CreationDate for .mdx and .mdd files as JSON. Reads only the header, so it is instant on huge files.

python3 tools/mdx_inspect.py                 # every .mdx/.mdd in the cwd
python3 tools/mdx_inspect.py ./dictionaries  # recurse a folder
python3 tools/mdx_inspect.py a.mdx b.mdd     # named files

tools/audit_resources.py — find missing .css / .mdd

Samples entries across a folder tree of .mdx and reports which dictionaries reference images/audio/fonts but ship no .mdd (NEEDS-MDD), and which <link> a stylesheet that isn't next to them (NEEDS-CSS). Writes res_audit.json.

python3 tools/audit_resources.py ./dictionaries

tools/extract_css_from_mdd.py — pull stylesheets out of .mdd

Many dictionaries pack their .css inside the .mdd. This writes any such .css out next to the .mdx and prints a file-type breakdown of every .mdd.

python3 tools/extract_css_from_mdd.py ./dictionaries

tools/pair_mdd.py — rename .mdd to match its .mdx

MDict only loads a .mdd whose basename is byte-identical to the .mdx. Downloads often differ by punctuation or word order. This fuzzy-matches each unmatched .mdd to a sibling .mdx and renames it. Dry run by default:

python3 tools/pair_mdd.py ./dictionaries            # show what it would do
python3 tools/pair_mdd.py ./dictionaries --apply    # do it

MDict source-text format (what the converters emit)

headword
<definition html>
</>
alternate form
@@@LINK=headword
</>
  • One record per block, terminated by a line containing only </>.
  • @@@LINK=target makes the headword a redirect to target.
  • Internal cross-references are <a href="entry://OTHER HEADWORD">.
  • Pack with mdict_utils.writer: pack(out_mdx, pack_mdx_txt(src_txt, encoding="UTF-8"), title, desc, encoding="UTF-8").

Notes / gotchas

  • Verify after packing. Every converter re-opens the result with readmdict and prints the key count. A drop of thousands of entries usually means a headword/body regex didn't match the source's markup.
  • Encoding. DSL is frequently UTF-16; StarDict is usually UTF-8; old Babylon exports can be CP1251. dsl2mdx.py tries a list; for others pass the right one to pyglossary.
  • .mdd is the same container as .mdx — it just holds files (\path\name.ext) instead of definitions. Build one with mdict_utils.writer.pack(target, dir, title, desc, is_mdd=True).

License

MIT — see LICENSE.

About

Dependency-light Python tools for building and maintaining MDict (.mdx/.mdd) dictionaries: convert Lingvo DSL, StarDict, EPUB and MOBI into MDX; inspect headers; audit and fix .css/.mdd pairing.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages