Structured metadata for programming languages, packaged as a typed, tree-shakeable TypeScript library.
code-languages is useful when you need a small source of truth for language names, slugs, file extensions, release metadata, websites, paradigms, logos, and reference colors in developer tools, docs sites, learning platforms, or editor-like interfaces.
- TypeScript-first data model
- Zero runtime dependencies
- ESM and CommonJS builds
- Subpath imports for per-language usage
- Tree-shakeable exports
- Lazy-loading API that imports only the languages you use
- Localized content in English, Spanish, Italian, French, German, and Portuguese
- Works in Node.js and modern bundlers
npm install code-languagesImport only the language metadata you need:
import { typescript } from "code-languages/typescript";
import { localizeLanguage } from "code-languages/i18n";
const localized = localizeLanguage(typescript, "en");
console.log(localized.name);
console.log(localized.description);
console.log(typescript.extensions);
console.log(typescript.paradigms);Import multiple languages:
import { abap } from "code-languages/abap";
import { actionscript } from "code-languages/actionscript";
console.log(abap.version);
console.log(actionscript.extensions);Import from the package root when bundle size is not a concern:
import {
abap,
actionscript,
localizeLanguage,
} from "code-languages";
console.log(localizeLanguage(abap).description);
console.log(localizeLanguage(actionscript, "es").description);Every language object satisfies the Language interface:
export type BaseLocale = "en" | "es" | "it" | "fr" | "de" | "pt";
export type Locale = BaseLocale | `${BaseLocale}-${string}` | string;
export interface LanguageContent {
name: string;
description: string;
longDescription: string;
}
export type LanguageStatus = "active" | "experimental" | "legacy" | "historical";
export interface Language {
slug: string;
aliases?: string[]; // lookup aliases, e.g. ["golang"] for go
status?: LanguageStatus; // absent means "active"
relations?: {
supersetOf?: string[]; // e.g. TypeScript → ["javascript"]
dialectOf?: string[]; // e.g. T-SQL → ["sql"]
compilesTo?: string[]; // e.g. Elm → ["javascript"]
};
publishedDate: string;
extensions: string[];
author: string;
website: string;
paradigms: string[];
tooling?: {
runtimes?: string[];
packageManagers?: string[];
ecosystems?: string[];
};
version: string;
logo: string;
color: `#${string}`;
i18n: {
en: LanguageContent;
es?: LanguageContent;
it?: LanguageContent;
fr?: LanguageContent;
de?: LanguageContent;
pt?: LanguageContent;
};
}Use the fluent API when you want one entry point for localization, async loading, and filename detection:
import { api } from "code-languages/api";
const astro = api.language("astro").locale("es-PE").get();
const vue = await api.language("vue").locale("en-US").load();
const detected = api.detect("src/App.vue").locale("es").get();
const ambiguous = await api.detectAll("include/config.h").locale("en").load();
console.log(astro?.resolvedLocale); // "es"
console.log(vue?.slug); // "vue"
console.log(detected?.name); // "Vue"
console.log(ambiguous.map((language) => language.slug)); // ["c", "cpp"]api.language(...) normalizes lookup values to the package slug format, so inputs
such as "Visual Basic" and "Jupyter Notebook!" resolve to visual-basic and
jupyter-notebook. Language aliases are resolved before normalization, so "golang",
"C#", "F#", "C++", "wasm", or "elisp" find go, csharp, fsharp, cpp,
webassembly, and emacs-lisp. When the slug is a known literal, get() and load()
are typed as always returning a language — no undefined check needed.
get() and load() both read from the in-memory catalog bundled with the api
entry point; load() returns the same data behind a promise. When bundle size
matters, use code-languages/api/lazy or import individual languages from
code-languages/<slug> instead.
Use api.runtime(value) to query languages that run on a specific platform or runtime environment:
import { api } from "code-languages/api";
// Get runtime metadata
const info = api.runtime('node').info();
// {
// slug: 'node',
// name: 'Node.js',
// color: '#339933',
// logo: 'https://cdn.simpleicons.org/nodedotjs',
// website: 'https://nodejs.org',
// aliases: ['node', 'nodejs', 'node.js'],
// packageManagers: ['npm', 'pnpm', 'Yarn', 'Bun'],
// }
// Get languages that target this runtime
const langs = api.runtime('node').langs().get();
const langsEs = api.runtime('.net').langs().locale('es').get();
await api.runtime('jvm').langs().load();
// Returns undefined / [] for unknown values
api.runtime('unknown-xyz').info(); // undefined
api.runtime('unknown-xyz').langs().get(); // []Supported runtime aliases include: node / nodejs / node.js, bun, deno, browser,
.net / dotnet, jvm / java, android, ios, python, ruby, rust, go / golang,
wasm, sql, and many more. Searches tooling.runtimes and tooling.ecosystems on each language.
Use api.packageManager(value) to query languages that use a specific package manager:
import { api } from "code-languages/api";
// Get package manager metadata
const info = api.packageManager('npm').info();
// {
// slug: 'npm',
// name: 'npm',
// color: '#CB3837',
// logo: 'https://cdn.simpleicons.org/npm',
// website: 'https://npmjs.com',
// aliases: ['npm'],
// }
// Get languages that use this package manager
const langs = api.packageManager('cargo').langs().get();
const langsEs = api.packageManager('pip').langs().locale('es').get();
// Get runtime platforms that include this package manager
const runtimes = api.packageManager('npm').runtimes();
// [{ name: 'Node.js', ... }, { name: 'Bun', ... }, { name: 'Deno', ... }]
// Returns undefined / [] for unknown values
api.packageManager('unknown-xyz').info(); // undefined
api.packageManager('unknown-xyz').langs().get(); // []
api.packageManager('unknown-xyz').runtimes(); // []Supported package manager aliases include: npm, pnpm, yarn, pip, poetry, uv,
cargo, maven, gradle, nuget, composer, hex, spm, rubygems, go-mod,
luarocks, opam, cpan, and more. Searches tooling.packageManagers on each language.
Use api.category(value) to filter languages by their domain of use:
import { api, getCategories } from "code-languages";
// frontend — targets the browser only (CSS, HTML, WGSL…)
api.category('frontend').langs().get();
// backend — runs on a server runtime (Python, Go, Ruby, PHP, Java, C#…)
api.category('backend').langs().locale('es').get();
// fullstack — targets both browser and server (JavaScript, TypeScript…)
api.category('fullstack').langs().get();
// systems — low-level / native / embedded (C, C++, Rust, Zig…)
api.category('systems').langs().get();
// data-science — data, ML, scientific computing (R, Julia, Python…)
api.category('data-science').langs().locale('pt').get();
// scripting — shell and scripting languages (Bash, Zsh, PowerShell…)
api.category('scripting').langs().get();
// other — everything that does not match any of the above
api.category('other').langs().get();
// async load and locale chaining work the same as other collection methods
await api.category('backend').langs().locale('pt').load();
// list all available categories
getCategories();
// → ['frontend', 'backend', 'fullstack', 'systems', 'data-science', 'scripting', 'other']Categories are inferred from each language's tooling.runtimes and tooling.ecosystems —
no extra data is needed in individual language files.
frontend, backend, and fullstack are mutually exclusive; the remaining categories
can overlap (Python appears in both backend and data-science).
Use api.paradigm(value) to filter languages by programming paradigm:
import { api, getParadigms } from "code-languages";
// Get paradigm metadata
const info = api.paradigm('functional').info();
// {
// slug: 'functional',
// name: 'Functional',
// description: 'Computation through function evaluation, immutability, and avoiding side effects.',
// aliases: ['functional', 'fp', 'pure-functional'],
// }
// Get languages that belong to this paradigm
const langs = api.paradigm('functional').langs().get();
const langsEs = api.paradigm('oop').langs().locale('es').get();
await api.paradigm('object-oriented').langs().load();
// Returns undefined / [] for unknown values
api.paradigm('unknown-xyz').info(); // undefined
api.paradigm('unknown-xyz').langs().get(); // []
// List all available paradigms
getParadigms();Supported paradigm aliases include: functional / fp, object-oriented / oop,
imperative / procedural, declarative, logic, concurrent, reactive, scripting / shell,
query, markup, templating, array, systems / low-level, stack-based / concatenative,
shader / gpu, and more. Searches paradigms on each language.
Use api.ecosystem(value) to filter languages by technology ecosystem:
import { api, getEcosystems } from "code-languages";
// Get ecosystem metadata
const info = api.ecosystem('jvm').info();
// {
// slug: 'jvm',
// name: 'JVM',
// description: 'Languages that run on the Java Virtual Machine.',
// aliases: ['jvm', 'java'],
// }
// Get languages that belong to this ecosystem
const langs = api.ecosystem('jvm').langs().get();
const langsEs = api.ecosystem('data-science').langs().locale('es').get();
await api.ecosystem('web').langs().load();
// Returns undefined / [] for unknown values
api.ecosystem('unknown-xyz').info(); // undefined
api.ecosystem('unknown-xyz').langs().get(); // []
// List all available ecosystems
getEcosystems();Supported ecosystem aliases include: web / frontend, node / nodejs, jvm / java,
dotnet / .net, data-science / ml, embedded / iot, game-dev / games,
blockchain / web3, mobile, wasm, cloud, kubernetes / k8s, systems,
formal-methods / verification, gpu / graphics, and more. Searches tooling.ecosystems on each language.
Use localizeLanguage to read localized display content with English fallback:
import { json } from "code-languages/json";
import { localizeLanguage } from "code-languages/i18n";
const language = localizeLanguage(json, "es-PE");
console.log(language.name);
console.log(language.longDescription);
console.log(language.resolvedLocale); // "es"localizeLanguage resolves locales in this order:
- Exact locale, for example
es. - Base language from a regional locale, for example
es-PE->es. - English fallback, for example
ja-JP->en.
English, Spanish, Italian, French, German, and Portuguese are supported base locales.
The current Italian, French, German, and Portuguese translations were initially
generated with translategemma:4b; translation reviews and corrections are welcome.
Use detectLanguage or detectLanguages to infer languages from filenames:
import { detectLanguage, detectLanguages } from "code-languages/detect";
console.log(detectLanguage("src/index.ts")?.slug); // "typescript"
console.log(detectLanguage("Dockerfile")?.slug); // "dockerfile"
console.log(detectLanguages("include/config.h").map((language) => language.slug)); // ["c", "cpp"]Use detectLanguageSlug or detectLanguageSlugs when you only need the slug
and want to avoid importing the full language catalog:
import { detectLanguageSlug, detectLanguageSlugs } from "code-languages/detect-slugs";
console.log(detectLanguageSlug("src/index.ts")); // "typescript"
console.log(detectLanguageSlugs("include/config.h")); // ["c", "cpp"]Use detectProjectLanguages to summarize a project file list by detected language:
import { detectProjectLanguages } from "code-languages/detect-slugs";
const files = ["src/index.ts", "src/app.ts", "README.md", "styles/main.css", "LICENSE"];
console.log(detectProjectLanguages(files));
// [
// { slug: "typescript", files: 2 },
// { slug: "css", files: 1 },
// { slug: "markdown", files: 1 }
// ]Use api.extension(value) to list every language that registers an extension or exact filename:
import { api } from "code-languages/api";
api.extension(".h").langs().get().map((language) => language.slug); // ["c", "cpp"]
api.extension("ts").langs().locale("es").get(); // leading dot optional
api.extension("Dockerfile").langs().get(); // exact filename entries work too
await api.extension(".vue").langs().load();Use detectLanguageByShebang or detectLanguageSlugByShebang to detect extensionless
scripts from their first line:
import { detectLanguageByShebang } from "code-languages/detect";
import { detectLanguageSlugByShebang } from "code-languages/detect-slugs";
detectLanguageSlugByShebang("#!/bin/bash\necho hi"); // "bash"
detectLanguageSlugByShebang("#!/usr/bin/env python3\nprint(1)"); // "python"
detectLanguageSlugByShebang("#!/usr/bin/env -S deno run --allow-net"); // "typescript"
detectLanguageByShebang("#!/usr/bin/env node\nconsole.log(1)")?.slug; // "javascript"Shebang detection handles direct interpreter paths, env indirection with flags, and
versioned interpreters such as python3.12 or perl5.36.
Use api.search(query) for ranked lookup across names, slugs, and aliases:
import { api } from "code-languages/api";
api.search("type").get().map((language) => language.slug); // ["typescript", ...]
api.search("golang").get().at(0)?.slug; // "go" — exact alias match ranks first
api.search("script").locale("es").get(); // ranked + localizedUse api.status(value) to filter by lifecycle status (active, experimental,
legacy, historical; languages without a status count as active):
import { api, getStatuses } from "code-languages";
api.status("legacy").langs().get(); // VBScript, ActionScript, ...
api.status("experimental").langs().locale("es").get();
getStatuses(); // ["active", "experimental", "legacy", "historical"]Use api.related(slug) to walk the relations graph in both directions:
import { api } from "code-languages/api";
api.related("javascript").langs().get(); // TypeScript, CoffeeScript, Elm, ...
api.related("typescript").langs().get(); // JavaScript
api.related("sql").langs().get(); // T-SQL, PL/SQL, PL/pgSQL, PRQLFilters compose. Every language collection is chainable: call .category(), .paradigm(), .runtime(),
.packageManager(), .ecosystem(), .extension(), .status(), or .related() on any
langs(), languages(), search(), or detectAll() result to intersect filters.
Order does not matter, and .locale() can be set at any point in the chain:
import { api } from "code-languages/api";
// Backend languages that are also functional
api.category("backend").langs().paradigm("functional").get(); // Elixir, Erlang, ...
// Active languages that run on Node.js, localized
api.languages().runtime("node").status("active").locale("es").get();
// Systems languages registering the .h extension
api.category("systems").langs().extension(".h").get(); // C, C++
// Ranked search narrowed by lifecycle status
api.search("script").status("active").get();Collections also offer cheap helpers that skip localization: .slugs() returns the
matching catalog slugs, .count() the number of matches, and .first() the first
match localized (or undefined when the collection is empty):
api.category("backend").langs().paradigm("functional").slugs(); // ["clojure", "elixir", ...]
api.runtime("node").langs().count(); // number of matching languages
api.search("golang").first()?.slug; // "go"code-languages/api/lazy exports lazyApi, which never bundles the catalog. Lookups
and detection run against a lightweight slug and extension index (~37 kB minified), and
each .load() dynamically imports only the language modules it returns, so bundlers
split every language into its own chunk:
import { lazyApi } from "code-languages/api/lazy";
const go = await lazyApi.language("golang").locale("es").load(); // loads only Go
const detected = await lazyApi.detect("src/main.rs").load(); // loads only Rust
const candidates = lazyApi.detectAll("include/config.h").slugs(); // ["c", "cpp"], nothing loaded
const headers = await lazyApi.extension(".h").langs().locale("de").load();
console.log(go?.name); // "Go"
console.log(detected?.slug); // "rust"lazyApi supports language(), languages(), detect(), detectAll(), and
extension().langs() with the same lookup, alias, and ranking rules as api. Everything
is async (.load() only); collections also offer slugs() and count() without loading
anything. Search and category, paradigm, runtime, package manager, ecosystem, status, and
related filters need every language in memory, so they are only available on api.
It loads languages on demand in both ESM and CommonJS.
The catalog currently includes 317 language entries. Each row can be imported directly from its package subpath.
npm ci
npm run check
npm run buildCommon scripts:
| Script | Purpose |
|---|---|
npm run format |
Format and auto-fix with Biome |
npm run format:check |
Check formatting with Biome (read-only) |
npm run lint |
Run ESLint |
npm run lint:fix |
Run ESLint with auto-fix |
npm run typecheck |
Run TypeScript without emitting files |
npm test |
Run Vitest |
npm run bench |
Run manual performance benchmarks |
npm run build |
Build ESM, CommonJS, and declaration files |
npm run check |
Run format:check, lint, typecheck, and tests |
npm run check:language-versions -- --language typescript |
Check release metadata for one language |
npm run website:prepare |
Build the static website data, unit test summary, and benchmark summary |
npm run website:serve |
Preview the static website locally |
The static website lives in docs and is generated from the package build.
It includes a live filename detector, localized language lookup, the full language
catalog, unit test summary, and benchmark summary.
npm run website:prepare
npm run website:serveSee CONTRIBUTING.md for setup instructions, field rules, and the process for adding a new language.
MIT