Pyphen

A pure Python library that hyphenates text using Hunspell dictionaries, covering 50+ languages.

Library
PyPI
v0.18.1
230stars
GPL-2.0-or-later OR LGPL-2.1-or-later OR MPL-1.1

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
68/100Good
Development Activity72
Maintenance52
Community68
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture74
Code Quality78
Innovation55
Learning Curve90

Pyphen is a pure Python module that hyphenates words using the same Hunspell hyphenation dictionaries LibreOffice ships with. It was forked from the discontinued python-hyphenator project to give WeasyPrint a dependency-free way to break words correctly when justifying text for PDF and print output, and it has since become a general-purpose hyphenation utility for any Python project that needs language-aware line breaking.

The library bundles dozens of LibreOffice’s .dic pattern files directly in the package, so there’s no external dictionary download or system package to install. It exposes a small, direct API: instantiate a Pyphen object for a language (with automatic locale fallback, e.g. nl_NL_variant1 resolves to nl_NL), then call inserted(), wrap(), positions(), or iterate() depending on whether you want hyphens inserted inline, a fitted line-wrap split, or the raw hyphenation break points. It also supports loading a custom .dic file directly by path for languages outside the bundled set.

What You Get

  • A Pyphen class that loads a language’s hyphenation dictionary and exposes inserted(), wrap(), positions(), and iterate() for different hyphenation needs
  • Dozens of bundled LibreOffice Hunspell dictionaries (hyph_*.dic files) covering major and minority languages, with no separate download step
  • Automatic locale fallback via language_fallback(), so a specific variant like sr-Latn resolves down to an available dictionary such as sr_Latn or sr
  • Support for loading a custom dictionary file by path or Path object for languages not included in the bundled set
  • Configurable left/right minimum-character constraints to control how close to a word’s edges a hyphen break is allowed
  • A wrap() method purpose-built for line-fitting: returns the longest hyphenated first part that fits within a given character width

Common Use Cases

  • Justifying paragraph text in PDF or print output, as WeasyPrint does, so lines break at linguistically correct points instead of overflowing or leaving large gaps
  • Wrapping long words in fixed-width UI elements (terminal output, labels, narrow columns) using wrap() to find the best fit within a character budget
  • Pre-processing text for typesetting pipelines that need hyphenation points annotated before layout, using positions() or iterate() to enumerate all valid breaks
  • Building multilingual document generators that need correct hyphenation across many locales without bundling separate language tooling per language

Under The Hood

Architecture The library is a single module (pyphen/__init__.py) built around two classes: HyphDict, which parses a Hunspell .dic pattern file into a dictionary of hyphenation patterns keyed by character sequence, and Pyphen, the public-facing class that wraps a HyphDict and applies left/right boundary constraints. Loaded dictionaries are cached process-wide in a module-level hdcache dict keyed by file path, so repeated instantiation for the same language is cheap. Hyphenation itself runs a sliding-window pattern match (HyphDict.positions) that scores every substring of a word against the loaded pattern set and keeps the maximum score at each character boundary, per the standard Hunspell/TeX hyphenation algorithm — a pattern-matching design rather than a rule-based or ML approach, which keeps behavior close to the reference LibreOffice implementation.

Tech Stack Pyphen has zero runtime dependencies beyond the Python standard library — it uses importlib.resources (with a pathlib.Path fallback for older environments) to locate its bundled dictionary files, and plain re for pattern parsing. It targets Python 3.10+ on both CPython and PyPy, builds via flit_core, and is distributed as a single wheel with the dictionary files as package data. Optional extras (sphinx/sphinx_rtd_theme for docs, pytest/ruff for testing and linting) are declared but never required at runtime.

Code Quality Tests live in tests/test_pyphen.py and run under pytest, covering the public API surface directly: insertion, wrapping, iteration, locale fallback, missing-dictionary error handling, custom dictionary loading by filename and Path, left/right boundary tuning, non-standard hyphenation alternatives, uppercase handling, and a smoke test that loads every bundled dictionary. Coverage is tracked via tool.coverage config in pyproject.toml, and ruff enforces a fairly strict lint rule set (E, W, F, I, N, RUF, UP, and more) with single-quote string style. There is no type-hinting/mypy layer, but the module is small and its public surface is narrow, which limits the practical risk of that gap.

API Design The public API is deliberately minimal — one constructor and four methods — and every method is documented with a runnable docstring example, which keeps the learning curve very low for a first-time user. Sensible defaults (locale fallback, a module-wide dictionary cache, left=2/right=2 boundary defaults matching common typesetting conventions) mean most callers only ever need Pyphen(lang=...) and inserted() or wrap(), with the lower-level positions()/iterate() methods available for callers building their own layout logic on top.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search