conlang
A partial-spec constructed-language generator.
You describe only what you care about — phonology, syllable shapes, a handful of words — and the generator samples the rest from typologically-plausible defaults. Same spec plus same seed always produces byte-identical output, and sampled entries can be locked so they survive re-sampling.
spec (YAML) ──▶ generate ──▶ model (canonical JSON) ──▶ render ──▶ dictionary + grammar sketch
│
├── lint (machine-checkable invariants)
└── bench (plausibility scorecard vs. Kah)
The model JSON is the single source of truth; the dictionary, grammar sketch, and every other view are rendered from it.
Install
pip install conlanggen
The distribution is conlanggen, but the import package and the command are both
conlang — import conlang, conlang generate.
Quickstart
# Generate from the example spec and render a Markdown dictionary.
conlang generate --spec spec\example.yaml --render
# Happy with it? Freeze it into an explicit spec so the values stick.
conlang accept --model out\veshtari.json
Output lands in out/: a model JSON and a rendered .md. Then:
conlang lint --model out\veshtari.json
conlang render --model out\veshtari.json --out out\veshtari.md
Documentation
- Getting started — install, first language, freeze it.
- Spec reference — every
spec/*.yamlkey. - Feature guide — phonotactics, scripts, data packs, the benchmark,
evolve, and syntax. - The translation pipeline — translate the fixed story end to end.
- Domain glossary and architecture decisions.
- Stability and the changelog.
Guarantees and lint rules
Reproducibility is the one hard guarantee: spec + seed ⇒ identical bytes.
Everything else is reported by lint as errors or warnings, and a broken
language is still generated (conlangers want to explore broken states).
| rule | severity | meaning |
|---|---|---|
schema |
error/warning | schema version present and known (a recognised older version warns; an unknown one errors) |
lexeme.root |
error | lexeme has a non-empty root |
phonotactics.lexeme |
error | every root is a legal word |
phonotactics.word |
error | every inflected form is a legal word |
lexicon.homophones |
warning | two roots collide (Kah has polysemy too) |
morphology.paradigm |
warning | a word is missing a form for a category its class realises |
morphology.class |
error | a word names an inflection class the language does not define |
lexicon.nonempty |
warning | the lexicon is empty |
orthography.unknown |
warning | the spelling map names a symbol that is not in the inventory |
orthography.collision |
warning | two symbols would spell the same thing |
script.coverage |
warning | the script does not cover every segment/syllable it must |
Every rule above has a test in tests/test_lint.py, tests/test_lint_invariants.py,
or tests/test_morphology.py.
Stability
Starting with 1.0.0, the model schema, the conlang command line, and the Spec
format are stable; within 1.x we make only additive, backwards-compatible changes. See
STABILITY.md for the promise and how deprecation works.
Development
.\.venv\Scripts\python.exe -m pytest
.\.venv\Scripts\python.exe -m ruff check .
.\.venv\Scripts\python.exe -m mypy src
The package layout:
src/conlang/
model/ canonical pydantic schema (the source of truth)
sampling/ deterministic RNG, inventory presets, concepts, defaults
phonology/ tokenization, syllabification, legality checks
lexicon/ seeded root generation, stable per-item seeding
morphology/ affixes, inflection classes, and word-form assembly
soundchange/ ordered sound changes; derive a daughter language
syntax/ word order, alignment, clause linearisation, place structure
script/ writing systems (glyphs)
render/ Markdown dictionary + grammar sketch
lint/ machine-checkable invariants
bench/ Kah adapter + scorecard
cli.py thin command-line view over the library
Roadmap
Shipped so far (1.0 froze the core; 1.1 adds adverbial clauses):
- Phonology — inventory, phonotactics, seeded word generation.
- IPA inventories — declare the inventory phonemic (
ipa: true) and derive a romanised orthography alongside the phonemic forms. - Morphology — affix breadth, inflection classes, and stacking.
- Diachrony —
conlang evolve: ordered sound changes (with environments) derive a daughter language, recorded inlineage. - Syntax — sampled word order and alignment, case marking with subject agreement, the predication tier, clause sequencing, and aspect.
- Translation pipeline —
conlang new/grow/translate/validate-translation/extras, including a grammar-match port from a sibling. - Writing systems —
conlang script: a sampled script (alphabet / syllabary / impure abjad / featural) rendered as deterministic SVG glyphs. - Data packs — optional, pinned PHOIBLE and WALS ground sampling (
conlang data fetch), with a graceful fallback to the built-in presets. - Feature-driven phonology — natural classes and feature-based sound-change rules.
- Place structure — an ordered list of semantic roles per predicate; role-labelled clauses.
- Semantics — negation, quantifiers, coordination, and topic/focus markers.
- Complex clauses — relative, complement, and reported clauses.
- Adverbial clauses — causal (because), temporal (when), and conditional (if) adjuncts, positioned by head direction.
Planned after 1.0: non-finite complements, direct quotation, a numeral system, and formal semantics.
License
MIT (code). Kah dictionary and grammar content remains Kwesho's and is not part of this repository.
Metadata
Release files for conlanggen 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| conlanggen-1.1.0.tar.gz | 215.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| conlanggen-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 302.1 kB
Release files / conlanggen-1.1.0.tar.gz
| Download URL | conlanggen-1.1.0.tar.gz |
|---|---|
| Size | 215.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a7538c8b78ea40923b41bf7cd7e1824ac4bceacc7e0e78416ac44d535716db0a
|
|
BLAKE2b-256 checksum How to use checksums |
3a408f94e522c0258193fe190f3607016276c9bd0dcd30d2e838659f05c16472
|
| 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 Oct 14, 2026.
Transparency logRelease files / conlanggen-1.1.0-py3-none-any.whl
| Download URL | conlanggen-1.1.0-py3-none-any.whl |
|---|---|
| Size | 87.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc8725cf933a3c4f4de2a39d59f78df77d206562f1b64fdc10dd63e94a449d4a
|
|
BLAKE2b-256 checksum How to use checksums |
f23f95ea4f8406b0234bd5b76f08cf7225ef6132cb743ee3bf1f1e226525b9a3
|
| 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 Oct 14, 2026.
Transparency log