Skip to main content

ablaut logo

ablaut

A fast, correct German verb conjugator.


crates.io PyPI npm CI license

Try it in the browser


The name is the German term for the vowel gradation in singen, sang, gesungen: Jacob Grimm formalized its seven classes in 1819, and they still describe every strong verb in the language.

Highlights

  • Measured correctness. Every generated form is validated against two machine-readable gold standards: 99.2% agreement with UniMorph deu (194k forms) and 98.0% with the Wiktextract extraction (794k forms, including analytic tenses and the perfect auxiliary). Where the two sources agree with each other, ablaut has zero known errors; every remaining disagreement is ruled on in a published adjudication log with references to standard grammars.
  • Generalizes to unseen verbs. A rule engine with a curated exception lexicon, not a lookup table: novel verbs (googeln, downloaden) conjugate correctly. On verbs outside its lexicon, agreement with UniMorph is 99.55%.
  • Fast and small. No I/O, no runtime data files, no dependencies in the core crate. A complete conjugation table (100+ forms) takes microseconds; the entire engine compiles to a 106 KB WebAssembly binary (about 45 KB gzipped).
  • Permissively licensed. MIT OR Apache-2.0, including the lexicon: no ShareAlike obligations.

Usage

Rust

cargo add ablaut
use ablaut::{AnalyticTense, Mood, Number, Person, Tense, Verb};

let v = Verb::from_infinitive("aufstehen")?;

v.conjugate(Tense::Present, Mood::Indicative, Person::First, Number::Singular);
// "stehe auf"
v.conjugate(Tense::Preterite, Mood::Indicative, Person::Third, Number::Singular);
// "stand auf"
v.analytic(AnalyticTense::Perfect, Mood::Indicative, Person::First, Number::Singular);
// "bin aufgestanden"
v.past_participle();          // "aufgestanden"
v.zu_infinitive();            // "aufzustehen"
v.imperative(Number::Singular); // Some("steh auf"); None for modals

The full paradigm as one struct: ablaut::table::Table::build(&v).

Python

pip install ablaut
import ablaut

c = ablaut.conjugate("aufstehen")
c.present[0]        # "stehe auf"
c.perfect[0]        # "bin aufgestanden"
c.auxiliary         # "sein"
c.zu_infinitive     # "aufzustehen"
c.imperative        # [None, None] for modals

Wheels are abi3 (Python 3.11+); no Rust toolchain needed.

WebAssembly

wasm-pack build --target web -- --features wasm
import init, { conjugate } from "./pkg/ablaut.js";
await init();
const c = conjugate("aufstehen");
c.present[0];       // "stehe auf"
c.zuInfinitive;     // "aufzustehen"

Coverage

All synthetic and analytic forms of standard German:

  • Tenses and moods: Präsens, Präteritum, Perfekt, Plusquamperfekt, Futur I/II, Konjunktiv I and II in all tenses (the würde-form is Futur I Konjunktiv II), processual and statal passive
  • Non-finite and imperative: both participles, zu-infinitive, perfect infinitive, imperatives including the adhortative (stehen wir auf!) and polite (stehen Sie auf!) forms
  • All five inflection classes: weak (the productive default), strong (ablaut, with 2/3sg stem alternation: sprichst, hältst), mixed (dachte), preterite-present (the modals and wissen: ich kann, no imperative), and suppletive (sein, werden, tun)
  • The prefix system: separable (stehe auf, aufgestanden, aufzustehen), inseparable (verstanden), fused compounds that never split (lobsingen: lobsang, lobgesungen), multiword lemmas (Rad fahren: fahre Rad, Rad gefahren), and per-lexeme rulings for dual-behavior prefixes (umarmen vs untertauchen)
  • Orthographic surface rules: e-epenthesis (arbeitest, bewillkommnest), s-coalescence (du lässt), schwa elision (ich sammle), the Latinate -ieren participle (studiert but geschmiert), and per-lexeme perfect auxiliaries (aufstehen: sein)

The exception lexicon (data/verbs.tsv, about 900 human-readable rulings) is compiled into the binary.

How correctness is verified

src/bin/golden.rs diffs every generated form against the gold data (scripts/fetch_unimorph.sh, scripts/fetch_kaikki.sh) and CI fails if accuracy regresses below pinned thresholds. scripts/cross_oracle.py cross-examines the two oracles against each other: they agree on 98.9% of their 195k shared slots, and triaging ablaut's mismatches against that agreement separates genuine bugs from gold-data errors.

The method has found real errors in the gold data itself, documented in docs/adjudications.tsv: UniMorph gives the Konjunktiv II of nennen as nannte (correct: nennte) and marks wisse! as nonexistent; Wiktionary assigns wachen the auxiliary sein and conjugates entgelten weak. One caveat: both oracles derive from Wiktionary, so their agreement is strong but not fully independent evidence.

Design

The architecture is a productive default rule plus a finite table of stored exceptions, which is precisely the dual-mechanism model of inflection (Marcus, Pinker et al., 1995) for which German morphology is the canonical test case. Features follow the UniMorph schema. docs/design.md maps the whole domain in four layers and doubles as the design spec.

License

MIT OR Apache-2.0.

Data provenance: the exception lexicon is independently curated factual data about standard German (principal parts, prefix behavior, auxiliaries), hand-verified row by row. UniMorph (CC BY-SA 3.0) and Wiktextract (CC BY-SA) are used as test oracles only: fetched at development time, never shipped.

Metadata

Release files for ablaut 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for ablaut 0.1.4
File Interpreter ABI Platform
ablaut-0.1.4-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
ablaut-0.1.4-cp311-abi3-manylinux_2_34_x86_64.whl CPython 3.11 abi3 Linux glibc 2.34+ x86-64 Details
ablaut-0.1.4-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details

Total release size: 771.6 kB

Release files / ablaut-0.1.4-cp311-abi3-win_amd64.whl

Download URL ablaut-0.1.4-cp311-abi3-win_amd64.whl
Size 177.9 kB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
99899bcf64d090008930e35fcb02a3423a6d619cb17a0b2888071ed2e56b4792
BLAKE2b-256 checksum
How to use checksums
4b3e906651eb58bc1a04a4b08b8b8ebff8fec4e0c61cfd4b49d0fa62e9eb9e93
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / ablaut-0.1.4-cp311-abi3-manylinux_2_34_x86_64.whl

Download URL ablaut-0.1.4-cp311-abi3-manylinux_2_34_x86_64.whl
Size 315.2 kB
Tags CPython 3.11 Linux glibc 2.34+ x86-64 abi3
SHA-256 checksum
How to use checksums
e90f03808ff1b148a20b2c5801406b93ecfb980fb1433f5d1ce7be5b05e32ff6
BLAKE2b-256 checksum
How to use checksums
8072c47288aed874edfc59b2aae6c5b850785ae6cc9a815d97aa8245c65c91e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / ablaut-0.1.4-cp311-abi3-macosx_11_0_arm64.whl

Download URL ablaut-0.1.4-cp311-abi3-macosx_11_0_arm64.whl
Size 278.5 kB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f4d5869305e69f079d76b01e9fdbd9a7dcb695ee32c1e5a6610f1d42cffe254a
BLAKE2b-256 checksum
How to use checksums
502cc8f09d387db309619456c09693c65fbee0cf20fbdc550b9aaaee02c60a73
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release history Release notifications | RSS feed

0.11.0

3 release files

0.10.0

3 release files

0.9.0

3 release files

0.8.0

3 release files

0.7.0

3 release files

This release

0.1.4 This release

3 release files

0.1.3

3 release files

0.1.2

3 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page