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.
- Releasing — the Codeberg CI setup and how to cut a release.
- Cross-pollination — how
conlangand the siblingmunaproject can share (the lexicon, the story, the grammar). - 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–1.7 add tiers):
- 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.
- Numerals — a closed digit class that composes cardinals in base 10 (ordered by word
order) and derives ordinals with an
ORDaffix. - Infinitives & quotation — non-finite complements with subject control (an
infmarker before a bare verb) and aquotparticle for direct, verbatim quotation. - Initial mutation — a
Mutationtable on the model plus triggers, so a language can lenite/eclipse a word's initial segment by grammatical context (Celtic); a## Mutationview and amutation.tablelint rule. - Meaning — a compositional meaning layer: a typed lambda denotation per lexeme
(derived from its place structure) and composed truth conditions (predication, negation,
generalized quantifiers), rendered in a
## Meaningview. - Model & entailment — a spec-declared semantic model (a domain of individuals plus
predicate extensions) that evaluates clauses to truth values and checks entailment
by model-checking the declared model; a
## Modelview. - Lexicon converter —
conlang convert-lexicon: a Muna-style lexicon TSV → a speclexicon(theconlang↔munacross-pollination seam).
Planned after 1.0: validity over all models, and meaning for relatives/complements/tense.
License
MIT (code). Kah dictionary and grammar content remains Kwesho's and is not part of this repository.
Metadata
Release files for conlanggen 1.7.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.7.0.tar.gz | 312.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| conlanggen-1.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 411.0 kB
Release files / conlanggen-1.7.0.tar.gz
| Download URL | conlanggen-1.7.0.tar.gz |
|---|---|
| Size | 312.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
05d4d133e0c968b15340ed4abaf507a32388ff7ba01d1424c148a03adb5bb17d
|
|
BLAKE2b-256 checksum How to use checksums |
a0c250ac62a51f8e4fba8e776f16df2bdd2366bf3320ef7c3b0ec3f5e67a8abc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|
Release files / conlanggen-1.7.0-py3-none-any.whl
| Download URL | conlanggen-1.7.0-py3-none-any.whl |
|---|---|
| Size | 98.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ca2c927e71aaf497a3780169649a3aa1f40ef75c8b0856f09731cb4f8621b153
|
|
BLAKE2b-256 checksum How to use checksums |
b0df418dee560c7440f8acb79c0e868619126584bbb0c31e09842d8ae66fefdf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.15
|