Asia/Shanghai
February 11, 2026

MdictLive - Modernizing the Dictionary Experience

MdictLive — 让词典体验现代化

Mingjian Shao
MdictLive - Modernizing the Dictionary Experience
A modern web reader for MDict dictionaries with React 19 SPA, dark mode, and faithful dictionary rendering.
Project Website | GitHub RepositoryMDict dictionaries (.mdx/.mdd) are a treasure trove of linguistic data, often meticulously crafted by communities. However, the available viewers are often dated, platform-locked, or lack modern web features like dark mode and responsive design.Existing web viewers typically fall into two traps:
  • Slow & Clunky: Server-side rendering that feels sluggish.
  • Broken Rendering: Trying to "sanitize" or native-render the dictionary HTML, which breaks the complex, custom CSS layouts used by high-quality dictionaries (like Oxford or Longman).
MdictLive takes a hybrid approach. I rebuilt the frontend from scratch using React 19 and Tailwind v4 to provide an app-like shell (sidebar, search, settings), while treating the dictionary content as a "black box" sovereign territory.Instead of injecting dictionary HTML directly into the React DOM (which causes CSS conflicts and security risks), MdictLive renders each entry in a sandboxed iframe. This ensures that:
  • The dictionary's custom CSS/JS works 100% as intended.
  • The main app's dark mode doesn't break the dictionary's layout.
  • Scrolling and interaction are isolated and performant.
Using Zustand, I synchronized state across the app. When you click a link inside a dictionary iframe (e.g., entry://word), the React app intercepts it, updates the global URL, and triggers a seamless navigation—making the iframe feel like a native part of the app.Every word lookup requires reading binary .mdx files, seeking to compressed blocks, and decompressing with zlib or LZO—repeated across every enabled dictionary. I added a dual-backend caching layer: an in-memory LRU cache (zero config, works out of the box) with an optional Valkey/Redis backend for power users. Repeat lookups are now instant.The backend is Python 3.11 with compiled LZO support, enabling it to read decade-old compressed dictionaries that newer libraries often fail to open. This is packaged in a multi-arch Docker image (amd64/arm64) for easy deployment on NAS systems like Unraid.
  • Frontend: React 19, Vite 7, Tailwind CSS v4, Framer Motion
  • Backend: Python 3.11, Flask, C-optimized LZO
  • Deployment: Docker, GitHub Actions, Unraid XML Template
MdictLive bridges the gap between legacy content and modern UX. It respects the original work of dictionary creators while giving users the dark mode, speed, and mobile experience they expect in 2026.
基于 React 19 重构的现代化 MDict 词典阅读器,支持暗黑模式、生词本和原生渲染。
项目主页 | GitHub 仓库MDict 词典格式(.mdx/.mdd)是语言学习者的宝库,拥有海量高质量的社区制作词典。然而,现有的阅读器大多界面陈旧、平台受限,或者缺乏暗黑模式和响应式设计等现代 Web 特性。现有的 Web 版阅读器通常存在两个极端:
  • 体验陈旧:传统的服务端渲染,操作迟滞,缺乏交互感。
  • 渲染崩坏:试图清洗或直接渲染词典 HTML,导致破坏了许多高质量词典(如牛津、朗文)复杂的自定义 CSS 布局。
MdictLive 采用了一种混合架构。我使用 React 19Tailwind v4 从头重写了前端,提供了一个类 App 的外壳(侧边栏、搜索、设置),同时将词典内容视为“黑盒”进行原样呈现。我没有将词典 HTML 直接注入 React DOM(这会导致样式冲突和安全风险),而是将每个条目渲染在沙盒 iframe 中。这确保了:
  • 词典原本的 CSS/JS 能够 100% 完美运行。
  • 主应用的暗黑模式不会破坏词典原本的排版。
  • 滚动和交互相互隔离,性能更佳。
利用 Zustand,我实现了跨层级的状态同步。当你点击 iframe 内部的词典链接(如 entry://word)时,React 应用会拦截该事件,更新全局 URL 并触发无缝导航——让 iframe 的体验如同原生应用一般流畅。每次查词都需要读取 .mdx 二进制文件、定位压缩块、用 zlib 或 LZO 解压——每本启用的词典都要重复一遍。我加入了双后端缓存层:内存 LRU 缓存(零配置,开箱即用)+ 可选的 Valkey/Redis 后端(供重度用户使用)。重复查词现在是毫秒级响应。后端采用 Python 3.11 并编译了 LZO 支持,使其能够读取许多新版库无法解压的古早压缩词典。这一切被封装在支持多架构(amd64/arm64)的 Docker 镜像中,方便在 Unraid 等 NAS 上部署。
  • 前端: React 19, Vite 7, Tailwind CSS v4, Framer Motion
  • 后端: Python 3.11, Flask, C 优化 LZO 库
  • 部署: Docker, GitHub Actions, Unraid XML 模板
MdictLive 连接了经典内容与现代体验。它在尊重词典制作者原创排版的同时,为用户提供了 2026 年应有的暗黑模式、极速响应和移动端体验。
Share this post:
Enjoy this post? Subscribe via RSS: English | 中文