{"id":19531487,"url":"https://github.com/alexanderwallin/node-gettext","last_synced_at":"2025-05-15T20:02:34.663Z","repository":{"id":37883649,"uuid":"1995620","full_name":"alexanderwallin/node-gettext","owner":"alexanderwallin","description":"A JavaScript implementation of gettext, a localization framework.","archived":false,"fork":false,"pushed_at":"2022-12-30T19:59:49.000Z","size":1020,"stargazers_count":188,"open_issues_count":10,"forks_count":39,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-15T08:25:26.435Z","etag":null,"topics":["gettext","gettext-library","i18n","internationalization","l10n","language","localization","translation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexanderwallin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-07-04T13:50:21.000Z","updated_at":"2024-01-04T16:54:27.000Z","dependencies_parsed_at":"2023-01-31T15:15:20.653Z","dependency_job_id":null,"html_url":"https://github.com/alexanderwallin/node-gettext","commit_stats":null,"previous_names":["andris9/node-gettext"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexanderwallin%2Fnode-gettext","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexanderwallin%2Fnode-gettext/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexanderwallin%2Fnode-gettext/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexanderwallin%2Fnode-gettext/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexanderwallin","download_url":"https://codeload.github.com/alexanderwallin/node-gettext/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254303449,"owners_count":22048203,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gettext","gettext-library","i18n","internationalization","l10n","language","localization","translation"],"created_at":"2024-11-11T01:43:07.697Z","updated_at":"2025-05-15T20:02:33.328Z","avatar_url":"https://github.com/alexanderwallin.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003cp align=\"center\"\u003e\n \u003cimg src=\"https://raw.githubusercontent.com/alexanderwallin/node-gettext/master/docs/node-gettext-logo.png\" width=\"160\" height=\"160\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\n node-gettext\n\u003c/h1\u003e\n\n[![Build Status](https://travis-ci.org/alexanderwallin/node-gettext.svg?branch=master)](http://travis-ci.org/alexanderwallin/node-gettext)\n[![npm version](https://badge.fury.io/js/node-gettext.svg)](https://badge.fury.io/js/node-gettext)\n\n**`node-gettext`** is a JavaScript implementation of (a large subset of) [gettext](https://www.gnu.org/software/gettext/gettext.html), a localization framework originally written in C.\n\nIf you just want to parse or compile mo/po files, for use with this library or elsewhere, check out [gettext-parser](https://github.com/smhg/gettext-parser).\n\n**NOTE:** This is the README for v2 of node-gettext, which introduces several braking changes. You can find the [README for v1 here](https://github.com/alexanderwallin/node-gettext/blob/master/docs/v1/README.md).\n\n* [Features](#features)\n  * [Differences from GNU gettext](#differences-from-gnu-gettext)\n* [Installation](#installation)\n* [Usage](#usage)\n  * [Error events](#error-events)\n  * [Recipes](#recipes)\n* [API](#api)\n* [Migrating from v1 to v2](#migrating-from-v1-to-v2)\n* [License](#license)\n* [See also](#see-also)\n\n\n## Features\n\n* Supports domains, contexts and plurals\n* Supports .json, .mo and .po files with the help of [gettext-parser](https://github.com/smhg/gettext-parser)\n* Ships with plural forms for 136 languages\n* Change locale or domain on the fly\n* Useful error messages enabled by a `debug` option\n* Emits events for internal errors, such as missing translations\n\n\n### Differences from GNU gettext\n\nThere are two main differences between `node-gettext` and GNU's gettext:\n\n1. **There are no categories.** GNU gettext features [categories such as `LC_MESSAGES`, `LC_NUMERIC` and `LC_MONETARY`](https://www.gnu.org/software/gettext/manual/gettext.html#Locale-Environment-Variables), but since there already is a plethora of great JavaScript libraries to deal with numbers, currencies, dates etc, `node-gettext` is simply targeted towards strings/phrases. You could say it just assumes the `LC_MESSAGES` category at all times.\n2. **You have to read translation files from the file system yourself.** GNU gettext is a C library that reads files from the file system. This is done using `bindtextdomain(domain, localesDirPath)` and `setlocale(category, locale)`, where these four parameters combined are used to read the appropriate translations file.\n\n  However, since `node-gettext` needs to work both on the server in web browsers (which usually is referred to as it being *universal* or *isomorphic* JavaScript), it is up to the developer to read translation files from disk or somehow provide it with translations as pure JavaScript objects using [`addTranslations(locale, domain, translations)`](#gettextsetlocalelocale).\n\n  `bindtextdomain` will be provided as an optional feature in a future release.\n\n\n## Installation\n\n```sh\nnpm install --save node-gettext\n```\n\n\n## Usage\n\n```js\nimport Gettext from 'node-gettext'\nimport swedishTranslations from './translations/sv-SE.json'\n\nconst gt = new Gettext()\ngt.addTranslations('sv-SE', 'messages', swedishTranslations)\ngt.setLocale('sv-SE')\n\ngt.gettext('The world is a funny place')\n// -\u003e \"Världen är en underlig plats\"\n```\n\n### Error events\n\n```js\n// Add translations etc...\n\ngt.on('error', error =\u003e console.log('oh nose', error))\ngt.gettext('An unrecognized message')\n// -\u003e 'oh nose', 'An unrecognized message'\n```\n\n### Recipes\n\n#### Load and add translations from .mo or .po files\n\n`node-gettext` expects all translations to be in the format specified by [`gettext-parser`](https://github.com/smhg/gettext-parser). Therefor, you should use that to parse .mo or .po files.\n\nHere is an example where we read a bunch of translation files from disk and add them to our `Gettext` instance:\n\n```js\nimport fs from 'fs'\nimport path from 'path'\nimport Gettext from 'node-gettext'\nimport { po } from 'gettext-parser'\n\n// In this example, our translations are found at\n// path/to/locales/LOCALE/DOMAIN.po\nconst translationsDir = 'path/to/locales'\nconst locales = ['en', 'fi-FI', 'sv-SE']\nconst domain = 'messages'\n\nconst gt = new Gettext()\n\nlocales.forEach((locale) =\u003e {\n    const fileName = `${domain}.po`\n    const translationsFilePath = path.join(translationsDir, locale, fileName)\n    const translationsContent = fs.readFileSync(translationsFilePath)\n\n    const parsedTranslations = po.parse(translationsContent)\n    gt.addTranslations(locale, domain, parsedTranslations)\n})\n```\n\n\n## API\n\n\u003ca name=\"Gettext\"\u003e\u003c/a\u003e\n\n## Gettext\n\n* [Gettext](#Gettext)\n    * [new Gettext([options])](#new_Gettext_new)\n    * [.on(eventName, callback)](#Gettext+on)\n    * [.off(eventName, callback)](#Gettext+off)\n    * [.addTranslations(locale, domain, translations)](#Gettext+addTranslations)\n    * [.setLocale(locale)](#Gettext+setLocale)\n    * [.setTextDomain(domain)](#Gettext+setTextDomain)\n    * [.gettext(msgid)](#Gettext+gettext) ⇒ \u003ccode\u003eString\u003c/code\u003e\n    * [.dgettext(domain, msgid)](#Gettext+dgettext) ⇒ \u003ccode\u003eString\u003c/code\u003e\n    * [.ngettext(msgid, msgidPlural, count)](#Gettext+ngettext) ⇒ \u003ccode\u003eString\u003c/code\u003e\n    * [.dngettext(domain, msgid, msgidPlural, count)](#Gettext+dngettext) ⇒ \u003ccode\u003eString\u003c/code\u003e\n    * [.pgettext(msgctxt, msgid)](#Gettext+pgettext) ⇒ \u003ccode\u003eString\u003c/code\u003e\n    * [.dpgettext(domain, msgctxt, msgid)](#Gettext+dpgettext) ⇒ \u003ccode\u003eString\u003c/code\u003e\n    * [.npgettext(msgctxt, msgid, msgidPlural, count)](#Gettext+npgettext) ⇒ \u003ccode\u003eString\u003c/code\u003e\n    * [.dnpgettext(domain, msgctxt, msgid, msgidPlural, count)](#Gettext+dnpgettext) ⇒ \u003ccode\u003eString\u003c/code\u003e\n    * [.textdomain()](#Gettext+textdomain)\n    * [.setlocale()](#Gettext+setlocale)\n    * ~~[.addTextdomain()](#Gettext+addTextdomain)~~\n\n\u003ca name=\"new_Gettext_new\"\u003e\u003c/a\u003e\n\n### new Gettext([options])\nCreates and returns a new Gettext instance.\n\n**Returns**: \u003ccode\u003eObject\u003c/code\u003e - A Gettext instance\n**Params**\n\n- `[options]`: \u003ccode\u003eObject\u003c/code\u003e - A set of options\n    - `.sourceLocale`: \u003ccode\u003eString\u003c/code\u003e - The locale that the source code and its texts are written in. Translations for this locale is not necessary.\n    - `.debug`: \u003ccode\u003eBoolean\u003c/code\u003e - Whether to output debug info into the\n                                 console.\n\n\u003ca name=\"Gettext+on\"\u003e\u003c/a\u003e\n\n### gettext.on(eventName, callback)\nAdds an event listener.\n\n**Params**\n\n- `eventName`: \u003ccode\u003eString\u003c/code\u003e - An event name\n- `callback`: \u003ccode\u003efunction\u003c/code\u003e - An event handler function\n\n\u003ca name=\"Gettext+off\"\u003e\u003c/a\u003e\n\n### gettext.off(eventName, callback)\nRemoves an event listener.\n\n**Params**\n\n- `eventName`: \u003ccode\u003eString\u003c/code\u003e - An event name\n- `callback`: \u003ccode\u003efunction\u003c/code\u003e - A previously registered event handler function\n\n\u003ca name=\"Gettext+addTranslations\"\u003e\u003c/a\u003e\n\n### gettext.addTranslations(locale, domain, translations)\nStores a set of translations in the set of gettext\ncatalogs.\n\n**Params**\n\n- `locale`: \u003ccode\u003eString\u003c/code\u003e - A locale string\n- `domain`: \u003ccode\u003eString\u003c/code\u003e - A domain name\n- `translations`: \u003ccode\u003eObject\u003c/code\u003e - An object of gettext-parser JSON shape\n\n**Example**  \n```js\ngt.addTranslations('sv-SE', 'messages', translationsObject)\n```\n\u003ca name=\"Gettext+setLocale\"\u003e\u003c/a\u003e\n\n### gettext.setLocale(locale)\nSets the locale to get translated messages for.\n\n**Params**\n\n- `locale`: \u003ccode\u003eString\u003c/code\u003e - A locale\n\n**Example**  \n```js\ngt.setLocale('sv-SE')\n```\n\u003ca name=\"Gettext+setTextDomain\"\u003e\u003c/a\u003e\n\n### gettext.setTextDomain(domain)\nSets the default gettext domain.\n\n**Params**\n\n- `domain`: \u003ccode\u003eString\u003c/code\u003e - A gettext domain name\n\n**Example**  \n```js\ngt.setTextDomain('domainname')\n```\n\u003ca name=\"Gettext+gettext\"\u003e\u003c/a\u003e\n\n### gettext.gettext(msgid) ⇒ \u003ccode\u003eString\u003c/code\u003e\nTranslates a string using the default textdomain\n\n**Returns**: \u003ccode\u003eString\u003c/code\u003e - Translation or the original string if no translation was found  \n**Params**\n\n- `msgid`: \u003ccode\u003eString\u003c/code\u003e - String to be translated\n\n**Example**  \n```js\ngt.gettext('Some text')\n```\n\u003ca name=\"Gettext+dgettext\"\u003e\u003c/a\u003e\n\n### gettext.dgettext(domain, msgid) ⇒ \u003ccode\u003eString\u003c/code\u003e\nTranslates a string using a specific domain\n\n**Returns**: \u003ccode\u003eString\u003c/code\u003e - Translation or the original string if no translation was found  \n**Params**\n\n- `domain`: \u003ccode\u003eString\u003c/code\u003e - A gettext domain name\n- `msgid`: \u003ccode\u003eString\u003c/code\u003e - String to be translated\n\n**Example**  \n```js\ngt.dgettext('domainname', 'Some text')\n```\n\u003ca name=\"Gettext+ngettext\"\u003e\u003c/a\u003e\n\n### gettext.ngettext(msgid, msgidPlural, count) ⇒ \u003ccode\u003eString\u003c/code\u003e\nTranslates a plural string using the default textdomain\n\n**Returns**: \u003ccode\u003eString\u003c/code\u003e - Translation or the original string if no translation was found  \n**Params**\n\n- `msgid`: \u003ccode\u003eString\u003c/code\u003e - String to be translated when count is not plural\n- `msgidPlural`: \u003ccode\u003eString\u003c/code\u003e - String to be translated when count is plural\n- `count`: \u003ccode\u003eNumber\u003c/code\u003e - Number count for the plural\n\n**Example**  \n```js\ngt.ngettext('One thing', 'Many things', numberOfThings)\n```\n\u003ca name=\"Gettext+dngettext\"\u003e\u003c/a\u003e\n\n### gettext.dngettext(domain, msgid, msgidPlural, count) ⇒ \u003ccode\u003eString\u003c/code\u003e\nTranslates a plural string using a specific textdomain\n\n**Returns**: \u003ccode\u003eString\u003c/code\u003e - Translation or the original string if no translation was found  \n**Params**\n\n- `domain`: \u003ccode\u003eString\u003c/code\u003e - A gettext domain name\n- `msgid`: \u003ccode\u003eString\u003c/code\u003e - String to be translated when count is not plural\n- `msgidPlural`: \u003ccode\u003eString\u003c/code\u003e - String to be translated when count is plural\n- `count`: \u003ccode\u003eNumber\u003c/code\u003e - Number count for the plural\n\n**Example**  \n```js\ngt.dngettext('domainname', 'One thing', 'Many things', numberOfThings)\n```\n\u003ca name=\"Gettext+pgettext\"\u003e\u003c/a\u003e\n\n### gettext.pgettext(msgctxt, msgid) ⇒ \u003ccode\u003eString\u003c/code\u003e\nTranslates a string from a specific context using the default textdomain\n\n**Returns**: \u003ccode\u003eString\u003c/code\u003e - Translation or the original string if no translation was found  \n**Params**\n\n- `msgctxt`: \u003ccode\u003eString\u003c/code\u003e - Translation context\n- `msgid`: \u003ccode\u003eString\u003c/code\u003e - String to be translated\n\n**Example**  \n```js\ngt.pgettext('sports', 'Back')\n```\n\u003ca name=\"Gettext+dpgettext\"\u003e\u003c/a\u003e\n\n### gettext.dpgettext(domain, msgctxt, msgid) ⇒ \u003ccode\u003eString\u003c/code\u003e\nTranslates a string from a specific context using s specific textdomain\n\n**Returns**: \u003ccode\u003eString\u003c/code\u003e - Translation or the original string if no translation was found  \n**Params**\n\n- `domain`: \u003ccode\u003eString\u003c/code\u003e - A gettext domain name\n- `msgctxt`: \u003ccode\u003eString\u003c/code\u003e - Translation context\n- `msgid`: \u003ccode\u003eString\u003c/code\u003e - String to be translated\n\n**Example**  \n```js\ngt.dpgettext('domainname', 'sports', 'Back')\n```\n\u003ca name=\"Gettext+npgettext\"\u003e\u003c/a\u003e\n\n### gettext.npgettext(msgctxt, msgid, msgidPlural, count) ⇒ \u003ccode\u003eString\u003c/code\u003e\nTranslates a plural string from a specific context using the default textdomain\n\n**Returns**: \u003ccode\u003eString\u003c/code\u003e - Translation or the original string if no translation was found  \n**Params**\n\n- `msgctxt`: \u003ccode\u003eString\u003c/code\u003e - Translation context\n- `msgid`: \u003ccode\u003eString\u003c/code\u003e - String to be translated when count is not plural\n- `msgidPlural`: \u003ccode\u003eString\u003c/code\u003e - String to be translated when count is plural\n- `count`: \u003ccode\u003eNumber\u003c/code\u003e - Number count for the plural\n\n**Example**  \n```js\ngt.npgettext('sports', 'Back', '%d backs', numberOfBacks)\n```\n\u003ca name=\"Gettext+dnpgettext\"\u003e\u003c/a\u003e\n\n### gettext.dnpgettext(domain, msgctxt, msgid, msgidPlural, count) ⇒ \u003ccode\u003eString\u003c/code\u003e\nTranslates a plural string from a specifi context using a specific textdomain\n\n**Returns**: \u003ccode\u003eString\u003c/code\u003e - Translation or the original string if no translation was found  \n**Params**\n\n- `domain`: \u003ccode\u003eString\u003c/code\u003e - A gettext domain name\n- `msgctxt`: \u003ccode\u003eString\u003c/code\u003e - Translation context\n- `msgid`: \u003ccode\u003eString\u003c/code\u003e - String to be translated\n- `msgidPlural`: \u003ccode\u003eString\u003c/code\u003e - If no translation was found, return this on count!=1\n- `count`: \u003ccode\u003eNumber\u003c/code\u003e - Number count for the plural\n\n**Example**  \n```js\ngt.dnpgettext('domainname', 'sports', 'Back', '%d backs', numberOfBacks)\n```\n\u003ca name=\"Gettext+textdomain\"\u003e\u003c/a\u003e\n\n### gettext.textdomain()\nC-style alias for [setTextDomain](#gettextsettextdomaindomain)\n\n**See**: Gettext#setTextDomain  \n\u003ca name=\"Gettext+setlocale\"\u003e\u003c/a\u003e\n\n### gettext.setlocale()\nC-style alias for [setLocale](#gettextsetlocalelocale)\n\n**See**: Gettext#setLocale  \n\u003ca name=\"Gettext+addTextdomain\"\u003e\u003c/a\u003e\n\n### ~~gettext.addTextdomain()~~\n***Deprecated***\n\nThis function will be removed in the final 2.0.0 release.\n\n\n\n## Migrating from v1 to v2\n\nVersion 1 of `node-gettext` confused domains with locales, which version 2 has corrected. `node-gettext` also no longer parses files or file paths for you, but accepts only ready-parsed JSON translation objects.\n\nHere is a full list of all breaking changes:\n\n* `textdomain(domain)` is now `setLocale(locale)`\n* `dgettext`, `dngettext`, `dpgettext` and `dnpgettext` does not treat the leading `domain` argument as a locale, but as a domain. To get a translation from a certain locale you need to call `setLocale(locale)` beforehand.\n* A new `setTextDomain(domain)` has been introduced\n* `addTextdomain(domain, file)` is now `addTranslations(locale, domain, translations)`\n* `addTranslations(locale, domain, translations)` **only accepts a JSON object with the [shape described in the `gettext-parser` README](https://github.com/smhg/gettext-parser#data-structure-of-parsed-mopo-files)**. To load translations from .mo or .po files, use [gettext-parser](https://github.com/smhg/gettext-parser), and it will provide you with valid JSON objects.\n* `_currentDomain` is now `domain`\n* `domains` is now `catalogs`\n* The instance method `__normalizeDomain(domain)` has been replaced by a static method `Gettext.getLanguageCode(locale)`\n\n\n## License\n\nMIT\n\n\n## See also\n\n* [gettext-parser](https://github.com/smhg/gettext-parser) - Parsing and compiling gettext translations between .po/.mo files and JSON\n* [lioness](https://github.com/alexanderwallin/lioness) – Gettext library for React\n* [react-gettext-parser](https://github.com/laget-se/react-gettext-parser) - Extracting gettext translatable strings from JS(X) code\n* [narp](https://github.com/laget-se/narp) - Workflow CLI tool that syncs translations between your app and Transifex\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexanderwallin%2Fnode-gettext","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexanderwallin%2Fnode-gettext","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexanderwallin%2Fnode-gettext/lists"}