Node.js Gettext Localization Library
node-gettext is a comprehensive JavaScript implementation of a significant subset of the GNU gettext localization framework, designed for both server-side Node.js and client-side browser environments, making it an isomorphic solution. Currently at version 3.0.1, the library focuses exclusively on string and phrase translation, omitting categories like LC_NUMERIC or LC_MONETARY found in the full GNU gettext specification, as it assumes the LC_MESSAGES category at all times. It supports core gettext features such as domains, contexts, and plural forms, and ships with pluralization rules for 136 languages. A key differentiator is that developers are responsible for loading translation files (e.g., .mo, .po, .json via gettext-parser) and providing them to the instance, rather than the library automatically reading from the file system. The library provides useful error messages when debug is enabled and emits events for internal issues, such as missing translations.
Common errors
-
TypeError: (0 , node_gettext__WEBPACK_IMPORTED_MODULE_0__.default) is not a constructor
cause Attempting to use `import { Gettext } from 'node-gettext'` when `Gettext` is the default export, especially common in bundled ESM projects.fixChange the import statement to `import Gettext from 'node-gettext'`. -
SyntaxError: Cannot use import statement outside a module
cause Using ES Module `import` syntax (`import Gettext from 'node-gettext'`) in a CommonJS (`.js`) file without the project being configured for ESM (e.g., missing `"type": "module"` in `package.json`).fixEither configure your project for ES Modules by adding `"type": "module"` to your `package.json`, or use the CommonJS `require` syntax: `const Gettext = require('node-gettext')`. -
Translation for 'Your message here' not found (often manifests as the original msgid being returned)
cause The requested translation key does not exist in the loaded translations for the current locale/domain, or the translations were not loaded correctly, or the locale/domain was not set.fixVerify that `gt.addTranslations(locale, domain, translations)` has been called with the correct `locale` and `domain`, that `gt.setLocale(locale)` is correctly set, and that the translation key exactly matches a `msgid` entry in your loaded translation data. Also, ensure you handle 'error' events for debugging.
Warnings
- breaking Version 2.x of node-gettext introduced significant breaking changes from 1.x, requiring API adjustments for users migrating. This includes changes to constructor arguments and method signatures.
- gotcha Unlike the full GNU gettext, `node-gettext` is exclusively designed for string message translation (equivalent to the `LC_MESSAGES` category). It does not provide functionality for internationalizing numbers, currencies, or dates.
- gotcha Developers must manually load translation files (e.g., .mo, .po, .json) from the file system or other sources and provide them as JavaScript objects to the `Gettext` instance via `addTranslations()`. The library does not automatically read files based on locale paths like GNU gettext.
- gotcha Missing translations or other internal issues are emitted as 'error' events rather than being thrown as exceptions. If these events are not explicitly handled, they might be silently ignored, leading to untranslated strings in production without clear warnings.
Install
-
npm install node-gettext -
yarn add node-gettext -
pnpm add node-gettext
Imports
- Gettext
import { Gettext } from 'node-gettext'import Gettext from 'node-gettext'
- Gettext (CJS)
const { Gettext } = require('node-gettext')const Gettext = require('node-gettext') - gettext-parser (PO parser)
import gettextParser from 'gettext-parser'
import { po } from 'gettext-parser'
Quickstart
import Gettext from 'node-gettext';
// Example Swedish translation data in the format expected by node-gettext.
// This would typically be loaded from a .json, .mo, or .po file processed by gettext-parser.
const swedishTranslations = {
charset: 'UTF-8',
headers: {
'plural-forms': 'nplurals=2; plural=(n != 1);',
'content-type': 'text/plain; charset=UTF-8'
},
translations: {
messages: {
'The world is a funny place': {
msgid: 'The world is a funny place',
msgstr: ['Världen är en underlig plats']
},
'Hello, %s!': {
msgid: 'Hello, %s!',
msgstr: ['Hallå, %s!']
},
'One apple': {
msgid: 'One apple',
msgid_plural: '%d apples',
msgstr: ['Ett äpple', '%d äpplen']
}
}
}
};
const gt = new Gettext();
// Add the loaded translations for the 'messages' domain and 'sv-SE' locale.
gt.addTranslations('sv-SE', 'messages', swedishTranslations);
// Set the current locale for the Gettext instance.
gt.setLocale('sv-SE');
console.log('--- Simple Translation ---');
console.log(gt.gettext('The world is a funny place'));
// Expected output: "Världen är en underlig plats"
console.log('\n--- Translation with Interpolation ---');
console.log(gt.gettext('Hello, %s!', 'Alex'));
// Expected output: "Hallå, Alex!"
console.log('\n--- Plural Form Translation (Singular) ---');
console.log(gt.ngettext('One apple', '%d apples', 1));
// Expected output: "Ett äpple"
console.log('\n--- Plural Form Translation (Plural) ---');
console.log(gt.ngettext('One apple', '%d apples', 5));
// Expected output: "5 äpplen"
// Example of error event handling for missing translations
gt.on('error', (error) => {
console.error('\nGettext Error Event:', error);
});
console.log('\n--- Triggering an Error Event (missing translation) ---');
gt.gettext('This message does not exist');
// Expected output: "Gettext Error Event: This message does not exist"