Locale-Codes
Language and country locale data for JavaScript and TypeScript, with lookups by name, tag, ISO code, or LCID.
Repository Health
Technical Analysis
locale-codes is a small Node.js and TypeScript library that ships a pre-built table of language and country locale information — English names, native names, geographic locations, BCP-47-style locale tags, Windows LCID numeric identifiers, and ISO 639-1/639-2 codes — assembled by cross-referencing the windows-locale, iso639-codes, and langs packages at require-time.
Rather than parsing locale strings or hitting an external service, consumers get a flat, in-memory array (locale.all) plus a small set of lookup helpers (where, getByTag, getByLCID, getByISO6392, getByISO6391, getByName, getByNameLocal, getByLocation) for finding a single locale record by whichever identifier they already have on hand. It ships full TypeScript typings (ILocale) alongside the CommonJS implementation.
What You Get
- A single
locale.allarray covering hundreds of language/country locale combinations, built at module load time. - Multiple lookup helpers (
getByTag,getByLCID,getByISO6392,getByISO6391,getByName,getByNameLocal,getByLocation) so callers can query by whichever identifier they already have. - Cross-referenced data merging Windows LCID tags/ids (via
windows-locale), ISO 639-1/639-2 codes (viaiso639-codes), and native language names (vialangs) into one normalized record shape. - First-class TypeScript typings (
index.d.ts) exporting theILocaleinterface for every field on a locale record. - Zero runtime network calls or file I/O — the whole table is computed once at require-time and kept in memory.
Common Use Cases
- Language selector dropdowns - a frontend app builds a language picker by mapping over
locale.alland rendering each entry’sname/localfields. - Normalizing user locale input - a backend service receives a tag like
pt-BRfrom a client and callsgetByTagto resolve it to a canonical language/country name for display or logging. - ISO code cross-referencing - a data pipeline maps a two-letter ISO 639-1 code to the corresponding three-letter ISO 639-2 code, via
getByISO6391and reading theiso639-2field off the result. - Windows LCID interoperability - an app integrating with a Windows-originated system (e.g. parsing a document’s locale metadata) uses
getByLCIDto translate a numeric LCID into a human-readable language and location.
Under The Hood
Architecture
The library is a single-file module (index.js, ~78 lines) with no internal layering — at require time it eagerly builds a merged locale table by iterating windows-locale’s keys, cross-referencing against iso639-codes by case-insensitive name match, and further cross-referencing langs’ all() output by ISO 639-2 code to attach a native name; the merged records are pushed into a module-level all array closed over by a small where() generic query function, and every exported getter (getByTag, getByLCID, etc.) is a thin wrapper calling where with a fixed key. There’s no dependency injection and no lazy computation — the entire table is built once as a side effect of require(), so a key/field naming change in any of the three upstream data packages would silently break the string-matching cross-references.
Tech Stack
Plain CommonJS JavaScript (require/module.exports) targeting Node >=14.17.4, with no build step for the runtime code — index.js ships directly per package.json’s files array. Runtime dependencies are exactly three data-only packages: windows-locale (^1.1.0), iso639-codes (^1.0.1), and langs (^2.0.0). Dev tooling is xo (^0.30.0, an opinionated ESLint preset) for linting and tsd (^0.13.1) for validating the hand-written index.d.ts against index.test-d.ts; the test script chains xo && tsd && node test.js. A .travis.yml is the only CI config present, pointing at a now largely inactive Travis CI setup.
Code Quality
Testing is minimal — test.js is a 10-line script with four bare assert.equal calls (row count check, one getByTag roundtrip, one negative-lookup check), run directly via node test.js rather than through a test framework, with no coverage of getByLCID, getByISO6392, getByLocation, or getByNameLocal. Error handling is implicit — where() returns undefined on no match rather than throwing. Type safety comes only from the parallel, hand-maintained index.d.ts, since there’s no source-level TypeScript, so types can drift from runtime behavior (e.g. local is typed optional but the code always sets it to null rather than omitting it). Style is enforced via xo, and naming is consistent, but no active CI gates these checks today.
API Design
The public surface is intentionally tiny — one data array (locale.all) plus one generic query function (where(key, text)) plus seven named convenience wrappers — so a consumer can go from an ISO code or LCID straight to a locale record with a single case-insensitive call and no configuration or async handling required. Rough edges: where’s key parameter is an untyped string in the runtime code (only the .d.ts constrains it), the same generic getter is reused for structurally different lookups distinguished only by a special-cased key === 'lcid' branch, and several fields can be null with no documented fallback beyond checking for it. Documentation is a single README with usage snippets plus a full literal locale table pasted inline, and example.js/example.ts give a minimal but sufficient quick-start.