Language pack registry for African programming tools · Apache 2.0 · Kolanut Technologies Ltd
Not a standalone programming language (unlike Nuru, Yorlang, or similar runtimes). This repo ships keyword maps and IDE gloss data for editors, transpilers, and learning tools.
Building with these packs? Star the repo on GitHub to follow releases and support African-language programming.
Language packs for African-language programming: a consistent set of logical programming concepts, mapped to native-language phrases, with enough structure for tools to transpile to JavaScript, Python, TypeScript, Go, Rust, Java, C, C++, C#, Kotlin, Swift, Dart, Ruby, PHP, and R.
If you’re building an editor, a transpiler, a linter, or a learning tool, this repo is the shared “source of truth”.
Africa-first:
The pain: learning and writing code in a second language costs attention. Part of your mind is translating words (if, className, error text) instead of solving the problem. Put the surface language in the language people already think in, and more of that attention goes to the programming.
The job of this registry: shared, versioned maps so editors, transpilers, and learning tools can help people learn and write code in languages they actually think in.
Most tools that try “programming in African languages” also hit a packaging wall:
- There’s no single public, spec-backed registry that says “these are the official reserved words for each target language” and “these are the logical concepts they map to”.
- Even when translation resources exist, they’re often not packaged, not versioned, and not reusable across tools.
This project is our attempt to fix that properly:
- A canonical logical token registry (the concepts)
- A canonical official keyword list per programming target (the specs)
- A growing set of African language packs (the human-language layer)
- Validation so everyone can build on top of the same foundation with confidence
See packs/ROADMAP.md for scope layers (keywords, IDE gloss, UI/Design, builtins, Phase F).
Pack metadata follows international conventions so tools worldwide can consume our data:
| Standard | Field | Example |
|---|---|---|
| ISO 639 | languageCode |
sw (Swahili), wo (Wolof), zu (isiZulu) |
| ISO 3166-1 | countries |
KE, SN, ZA, EG |
| BCP-47 | locale |
sw-KE, wo-SN, ar-EG |
We use the same code systems as major platforms and localization projects — standards-aligned, not a custom Kolanut-only format. Plain English: packs/GLOSSARY.md.
- 29 shipped African language packs (and a roadmap for more)
- 370 logical tokens that every pack maps (shared across all programming targets)
- Schemas + validation to keep packs consistent
- Coverage checks against official keyword lists for each target language
The data lives under packs/. The package published to npm is @kolanut/language-packs.
In short:
- Logical token registry: a shared list of concepts (the “meaning layer”)
- Official keyword lists: spec-backed reserved words for each target language
- African language packs: native-language phrases mapped to those concepts
- Validation: ensures packs are complete and spec coverage stays at 0 gaps
| What we cover | Shipped | Planned | Source of truth |
|---|---|---|---|
| African language packs | 29 | +39 | packs/coverage-summary.json · packs/languages-roadmap.json |
| Programming targets | 15 | +5 | packs/coverage-summary.json · packs/languages-roadmap.json |
| Logical tokens | 370 | — | packs/logical-tokens.json |
| Keyword coverage gaps | 0 | — | packs/coverage-summary.json |
We track coverage against official reserved keywords for each transpile target. Some concepts are “structural” (they don’t have a 1:1 keyword in a given language, but still need a consistent logical token).
Source of truth: packs/coverage-summary.json
| Target | Spec keywords | Mapped | Gaps | Score |
|---|---|---|---|---|
| JavaScript | 38 | 38 | 0 | 100% |
| Python | 40 | 40 | 0 | 100% |
| TypeScript | 79 tracked† | 79 | 0 | 100% |
| Go | 25 | 25 | 0 | 100% |
| Rust | 40 | 40 | 0 | 100% |
| Java | 51 | 51 | 0 | 100% |
| C | 44 | 44 | 0 | 100% |
| C++ | 92 | 92 | 0 | 100% |
| C# | 104 | 104 | 0 | 100% |
| Kotlin | 80 | 80 | 0 | 100% |
| Swift | 90 | 90 | 0 | 100% |
| Dart | 68 | 68 | 0 | 100% |
| Ruby | 41 | 41 | 0 | 100% |
| PHP | 81 | 81 | 0 | 100% |
| R | 29 | 29 | 0 | 100% |
†TypeScript has no single official keyword count in the Handbook; the tracked count is our reserved/modifier + type-keyword set for coverage (see notes in official-target-keywords.json).
How much of each pack is translated (vs English stubs). Core = the concepts every tool needs first. Translated means a native phrase exists. English-only slots count as untranslated. Help close the gap: suggest a translation.
Source of truth: packs/coverage-summary.json
| Pack | Core | Full | Translated | Shared forms |
|---|---|---|---|---|
Ẹdo (edo) |
88.5% | 14.5% | 54/370 | 0 |
Hausa (hausa) |
85.7% | 9.4% | 35/370 | 0 |
Igbo (igbo) |
85.7% | 9.4% | 35/370 | 0 |
Arabic (arabic) |
85.7% | 9.1% | 34/370 | 0 |
Yorùbá (yoruba) |
82.8% | 8.6% | 32/370 | 0 |
Swahili (swahili) |
85.7% | 8.3% | 31/370 | 0 |
isiZulu (zulu) |
85.7% | 8.3% | 31/370 | 0 |
Amharic (amharic) |
85.7% | 8.1% | 30/370 | 0 |
French (french) |
85.7% | 8.1% | 30/370 | 0 |
Luganda (luganda) |
82.8% | 8.1% | 30/370 | 0 |
Nigerian Pidgin (nigerian-pidgin) |
85.7% | 8.1% | 30/370 | 0 |
isiXhosa (xhosa) |
85.7% | 8.1% | 30/370 | 0 |
Afrikaans (afrikaans) |
82.8% | 7.8% | 29/370 | 0 |
Efik (efik) |
82.8% | 7.8% | 29/370 | 0 |
Kinyarwanda (kinyarwanda) |
82.8% | 7.8% | 29/370 | 0 |
Lingala (lingala) |
82.8% | 7.8% | 29/370 | 0 |
Oromo (oromo) |
82.8% | 7.8% | 29/370 | 0 |
Somali (somali) |
82.8% | 7.8% | 29/370 | 0 |
Tigrinya (tigrinya) |
82.8% | 7.8% | 29/370 | 0 |
Shona (shona) |
80% | 7.5% | 28/370 | 0 |
Akan (akan) |
77.1% | 7.2% | 27/370 | 0 |
Twi (twi) |
77.1% | 7.2% | 27/370 | 0 |
Wolof (wolof) |
74.2% | 7% | 26/370 | 0 |
Cameroon Pidgin (cameroon-pidgin) |
71.4% | 6.7% | 25/370 | 0 |
Bambara (bambara) |
0% | 0% | 0/370 | 0 |
Fulfulde (fulfulde) |
0% | 0% | 0/370 | 0 |
Portuguese (Africa) (portuguese-africa) |
0% | 0% | 0/370 | 0 |
Sesotho (sesotho) |
0% | 0% | 0/370 | 0 |
Setswana (setswana) |
0% | 0% | 0/370 | 0 |
Shared forms: a non-primary phrase that also appears on another logical token in the same pack. Allowed when primaries stay unique. Full policy: packs/KEYWORD_ALIASES.md. Machine export: coverage-summary.json → packCoverage.<name>.ambiguousForms.
Currently: 0 shared secondary-alias forms (each pack keeps unique primaries; homographs live in the allowlist until native review adds shared secondaries).
Source of truth: packs/official-target-keywords.json
| Target | Spec keywords | Spec source |
|---|---|---|
| JavaScript | 38 | ECMA-262 Edition 15 |
| Python | 40 | Python 3.12+ Language Reference (hard + soft; lazy via PEP 810) |
| TypeScript | 79 tracked† | TypeScript — tracked reserved tokens (practical set) |
| Go | 25 | The Go Programming Language Specification |
| Rust | 40 | The Rust Reference — Keywords |
| Java | 51 | Java Language Specification (Java SE 21) |
| C | 44 | ISO/IEC 9899:2011 (C11) - Keywords |
| C++ | 92 | ISO C++20 — Keywords (cppreference) |
| C# | 104 | C# 12 — Keywords (Microsoft Learn) |
| Kotlin | 80 | Kotlin — Keywords and operators |
| Swift | 90 | The Swift Programming Language — Lexical Structure |
| Dart | 68 | Dart 3.12.2 - Language keywords (dart.dev table) |
| Ruby | 41 | Ruby 3.2 — Keywords |
| PHP | 81 | PHP 8.3 — Reserved keywords |
| R | 29 | R Language Definition — Reserved words |
npm install @kolanut/language-packsimport { listPackNames, loadPack, loadPublishedKeywords } from '@kolanut/language-packs';
const packs = await listPackNames(); // e.g. 29 packs
const yoruba = await loadPack('yoruba'); // metadata + source keywords
const keywords = await loadPublishedKeywords('yoruba'); // runtime map
// keywords.IF → ['ṣé', 'ti', 'if'] (370 logical tokens)Most tools use this package as a mapping layer: the official keyword stays the same, but the UI (or source language) can present a localized phrase as an alias.
Example (Nigerian Pidgin, illustrative — exact phrases live in the pack):
IF → "if case say"
PRINT → "show for screen"
If you prefer to consume JSON directly (Rust/Go/Python/CLI tools), start here:
packs/index.json: pack manifest (locale, region, countries, status)packs/language-registry.json: taken and plannedname/locale/languageCode(check before adding a pack)packs/NAMING_GUIDE.md: how to name packs and write localespacks/logical-tokens.json: the 370-token registry (the thing packs must fully map)packs/by-country.json:NG→["yoruba", "igbo", ...]packs/by-region.json: region → pack namespacks/coverage-summary.json: auto-generated coverage reportpacks/ROADMAP.md: version plan (0.12 → 1.0 → 2.0)packs/TIERS.md: pack layers and scope ceilingspacks/languages-roadmap.json: shipped vs planned packs (machine-readable)
These are the 29 packs currently shipped.
- Flags are shown for the primary locale (quick scanning). Many packs apply to multiple countries—see
packs/index.jsonfor the full list. - We use Twemoji flag images (not emoji characters) so the flags render reliably on both GitHub and npm.
West Africa
Akan (
ak-GH)Bambara (
bm-ML)Ẹdo (
bin-NG)Efik (
efi-NG)French (
fr-SN)Fulfulde (
ff-NG)Hausa (
ha-NG)Igbo (
ig-NG)Nigerian Pidgin (
pcm-NG)Twi (
tw-GH)Wolof (
wo-SN)Yorùbá (
yo-NG)
East Africa
Central Africa
Horn of Africa
North / East Africa
Southern Africa
Afrikaans (
af-ZA)isiXhosa (
xh-ZA)isiZulu (
zu-ZA)Portuguese (Africa) (
pt-AO)Sesotho (
st-LS)Setswana (
tn-BW)Shona (
sn-ZW)
Full metadata (including all countries per pack): packs/index.json.
Most packs start at reviewStatus: "starter". That’s intentional: we’d rather ship useful starter packs quickly, then improve them through native-speaker review.
If you care about linguistic accuracy or preferred terminology for a specific community, open a PR — see CONTRIBUTING.md.
We track roadmaps in packs/ROADMAP.md (version plan: patch / minor / major) and packs/languages-roadmap.json (machine-readable). Layer ceilings: packs/TIERS.md.
- Planned African languages (by region + priority) — 39 more packs on the list
- Planned programming targets — Clojure, Lua, SQL, Scala, Elixir (see
packs/ROADMAP.md) - Logical tokens — 370 shipped; UI/Design Design-tab layer → 0.37.0; stdlib / builtins → 2.0.0 (neither is keyword coverage)
- Programming targets — 15 shipped with 0 keyword coverage gaps (see table above)
Regional focus (how we’re sequencing the work):
- Phase 1 — West Africa + Central Africa: highest immediate demand and strong community contributor base
- Phase 2 — East Africa + Horn of Africa: expand coverage where multilingual education is already strong
- Phase 3 — North Africa + Southern Africa + Indian Ocean: fill remaining gaps and add country-specific variants where needed
High-priority upcoming packs currently include:
See packs/languages-roadmap.json for the full planned list.
Contributions are welcome—especially from native speakers and educators.
Start here if you do not use git or JSON: CONTRIBUTING-SIMPLE.md
- Suggest a translation (add or improve a word)
- Report unnatural phrasing
Maintainers apply your suggestion and credit you in the pack.
Start here: CONTRIBUTING.md — step-by-step guide (what to edit, what not to touch, checklist before you open a PR).
New language? packs/NAMING_GUIDE.md · packs/language-registry.json · packs/DIALECTS.md (dialects)
Also read: packs/PACK_SCOPE.md · packs/GLOSSARY.md (what ISO / BCP-47 mean)
| File | Your role |
|---|---|
packs/<language>/pack.json |
Edit — metadata + native keyword phrases (source) |
packs/<language>/keywords.json |
Generated — run npm run generate after editing pack.json; do not hand-edit |
packs/logical-tokens.json |
Read only — checklist of all 370 concepts; do not edit for translations |
packs/index.json |
Edit only when adding a new pack |
packs/language-registry.json |
Check before naming — shipped + planned identifiers |
packs/NAMING_GUIDE.md |
Read for new packs — full field list, locale format, template |
A valid contribution is a complete pack (correct scope metadata + all 370 tokens translated), not a few word changes in isolation.
- Improve an existing pack — e.g.
packs/zulu/— fix phrasing, add dialect aliases, clarifyscopeNote - Add a new pack — copy an existing pack, set all metadata, translate all 370 tokens, add to
packs/index.json, runnpm run registry
One language pack per PR. Run npm test from the repo root before opening the PR.
Windows (PowerShell):
git clone https://github.com/KolanutTechnologies/kola-language-packs.git
cd kola-language-packs
npm install
npm testMac / Linux:
git clone https://github.com/KolanutTechnologies/kola-language-packs.git
cd kola-language-packs
npm install
npm testEdit pack.json keywords only. Run npm run generate (or npm test) to refresh keywords.json. Do not run bulk regenerate scripts unless you are a maintainer (scripts/README.md).
Docs: CONTRIBUTING-SIMPLE.md (no coding) · CONTRIBUTING.md · packs/REPO_MAP.md (what each file does) · VERSIONING.md · CHANGELOG.md
- Pick the right pack (or create a new variant) — see
packs/index.jsonandPACK_SCOPE.md - Edit
pack.jsonmetadata and translations; keepkeywords.jsonin sync - Map every token listed in
packs/logical-tokens.json(370 total) - Run
npm test - Open a PR for native-speaker review
This project only works if real people show up with real language knowledge. Thank you to everyone who’s contributed time, expertise, and care.
Answers to recurring questions. This section lives in README.md only — it is not a folder or auto-generated file.
Who adds FAQ entries? Maintainers, when the same question appears in GitHub issues, PRs, or discussions. Suggest one: open an issue with tag question.
Where do answers come from? Project scope decisions already documented in packs/ (logical tokens, pack schema, validation rules) — summarized here in plain language.
It's exhaustive for this project's current scope: a shared registry of logical concepts needed to map official reserved keywords across 15 programming targets (plus a small set of "structural" concepts).
It is not a full programming-language grammar. It intentionally does not try to model:
- punctuation (
;,{},()) - operators (
+,==,??,:=) - comment syntax (
//,#,/* */) - every syntax feature that isn’t keyword-driven
If we expand into full syntax coverage later, that would likely be a separate registry rather than inflating “logical tokens” beyond readability.
Usually edit the existing pack and add aliases — not a new folder.
Example (Swahili, East Africa): "IF": ["kama", "ikiwa", "if"] in packs/swahili/.
Full decision tree: packs/DIALECTS.md.
International standards for language codes, country codes, and locale tags. We follow them so npm, editors, and locale APIs understand our packs — same codes used across the African language ecosystem and global tech.
Plain English: packs/GLOSSARY.md. There is no formal certification body for language packs; we are standards-aligned.
From the repo root only:
npm test— every PR (checks your files; does not delete anything)npm run registry— only when adding a new packnpm run generateonly after you edit your pack's source (pack.json). It syncs derived files from source; it is not the old bootstrap footgun (that script was deleted in 0.18.0)
Details: CONTRIBUTING.md · scripts/README.md
Not today — all packs share the npm package version on each release. See VERSIONING.md.
packs/REPO_MAP.md — plain map of every folder and file.
This section is only relevant if you’re maintaining the package or editing generated pack data.
Maintainer notes (publishing + regeneration)
- Publishing: push to
mainruns.github/workflows/release.yml(tag + GitHub Release + npm via Trusted Publisher OIDC). Configure on npm:KolanutTechnologies/kola-language-packs/release.yml. Local fallback:npm loginthennpm publish --access public. - README metrics: counts, coverage tables, spec-source tables, and the regional pack list are generated — do not hand-edit inside
<!-- …:start -->/<!-- …:end -->markers. Runnpm run readme:sync(ornpm test) and commitREADME.md. CI fails if README is stale after test. - Sync pack versions after a manual version bump:
npm run sync-versions - Regenerate derived pack files after changing the source definitions:
npm run generateApache 2.0 — see LICENSE.
Some imported terminology may carry additional license terms (e.g. Mafoko/NOODL). Check source licenses before bulk import and cite them in your PR.