Modern TypeScript rewrite of messageformat/Jed. ESM-only, zero dependencies, drop-in API compatible.
Jed hasn't been touched since 2016. Jeb takes the same gettext API and locale data format and reimplements it in modern TypeScript — no Jison, no AMD/UMD module dance, no eval or new Function.
Credit where it's due: the public API, chain API, locale data format, and overall design are all from Alex Sexton's original Jed. This is a rewrite, not a fork — none of Jed's source is carried over — but it stands entirely on Jed's shoulders.
- TypeScript source with full type exports
- ESM only (
"type": "module") - Hand-written recursive descent plural-forms parser (no Jison dependency)
- Strict mode: no
eval, nonew Function, expressions length-capped - Cached compiled plural functions and sprintf templates
- Hardened count handling: NaN, Infinity, and negative counts are clamped instead of producing garbage plural indices
textdomain(domain)throws on unknown domains instead of silently switching- Compiled output targets ES2022, Node ≥ 20
- Same constructor options:
{ locale_data, domain, debug, missing_key_callback } - Same locale data JSON format (compatible with po2json output)
- Same gettext API:
gettext,ngettext,pgettext,dgettext,dngettext,dpgettext,npgettext,dnpgettext,dcnpgettext, etc. - Same chain API:
translate(key).withContext().ifPlural().onDomain().fetch() - Same
sprintf(static and instance) - Same
context_delimiter(�) - Same fallback behaviour (missing key returns the key itself)
This package is published to GitHub Packages under the @surgeventures scope.
# .npmrc
@surgeventures:registry=https://npm.pkg.github.com/npm install @surgeventures/jebReplace your import:
- import Jed from 'jed';
+ import Jeb from '@surgeventures/jeb';Everything else stays the same. The constructor, methods, locale data format, and chain API are all compatible.
If you have custom type declarations for Jed (e.g. a jed.d.ts module augmentation), you can delete them — jeb ships its own types.
import Jeb from '@surgeventures/jeb';
const i18n = new Jeb({
domain: 'messages',
locale_data: {
messages: {
'': {
domain: 'messages',
lang: 'fr',
plural_forms: 'nplurals=2; plural=(n > 1);',
},
Hello: ['Bonjour'],
'%d item': ['%d article', '%d articles'],
},
},
});
i18n.gettext('Hello'); // 'Bonjour'
i18n.ngettext('%d item', '%d items', 5); // '%d articles'import Jeb, { sprintf, compilePluralForms, extractNPlurals } from '@surgeventures/jeb';
import type { JebOptions, LocaleData, TranslationDomain, DomainMetadata } from '@surgeventures/jeb';MIT. See LICENSE.
The original Jed is © Alex Sexton and contributors, also under MIT. Jeb is an independent reimplementation; no Jed source is included.