{"id":19531482,"url":"https://github.com/alexanderwallin/lioness","last_synced_at":"2025-10-11T03:47:21.976Z","repository":{"id":42362863,"uuid":"58827986","full_name":"alexanderwallin/lioness","owner":"alexanderwallin","description":"🐯 A React library for efficiently implementing Gettext localization","archived":false,"fork":false,"pushed_at":"2023-03-01T10:11:54.000Z","size":1900,"stargazers_count":29,"open_issues_count":17,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-15T14:44:24.417Z","etag":null,"topics":["gettext","i18n","l10n","localization","react","translation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"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":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-14T20:08:36.000Z","updated_at":"2023-01-26T15:53:10.000Z","dependencies_parsed_at":"2024-06-18T22:47:59.409Z","dependency_job_id":"324d3e0c-3056-4bde-9495-ca7d65df11ed","html_url":"https://github.com/alexanderwallin/lioness","commit_stats":null,"previous_names":["alexanderwallin/lioness-react"],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexanderwallin%2Flioness","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexanderwallin%2Flioness/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexanderwallin%2Flioness/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexanderwallin%2Flioness/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexanderwallin","download_url":"https://codeload.github.com/alexanderwallin/lioness/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250983868,"owners_count":21518024,"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","i18n","l10n","localization","react","translation"],"created_at":"2024-11-11T01:43:07.370Z","updated_at":"2025-10-11T03:47:16.939Z","avatar_url":"https://github.com/alexanderwallin.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/alexanderwallin/lioness/blob/master/docs/lioness-logo-2.png?raw=true\" /\u003e\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n  Lioness\n  \u003cbr /\u003e\n  \u003cimg src=\"https://badge.fury.io/js/lioness.svg\" alt=\"npm version\" class=\"badge\"\u003e \u003cimg src=\"https://travis-ci.org/alexanderwallin/lioness.svg?branch=master\" /\u003e\n\u003c/h1\u003e\n\n**Lioness** is a React library for efficiently implementing Gettext localization in your app with little effort.\n\nIt utilises [`node-gettext`](https://github.com/alexanderwallin/node-gettext) as translations tool, but this ought to be modularized in the future.\n\n```js\n\u003cT\n  message=\"You have one thingy, {{ itemLink:check it out }}\"\n  messagePlural=\"You have {{ count }} thingies, {{ listLink:check them out }}\"\n  count={items.length}\n  itemLink={\u003ca href={`/thingies/${items[0].id}`} /\u003e}\n  listLink={\u003ca href=\"/thingies\" /\u003e}\n/\u003e\n// items.length === 1 =\u003e Du har en grej, \u003ca href=\"/thingies/281\"\u003ekolla in den här\u003ca/\u003e.\n// items.length === 7 =\u003e Du har 7 grejer, \u003ca href=\"/thingies\"\u003ekolla in dem här\u003ca/\u003e.\n```\n\n## Table of contents\n\n* [Features](#features)\n* [Installation](#installation)\n* [Usage](#usage)\n  * [Using `\u003cT /\u003e`](#using-t-)\n  * [Using `withTranslators(Component)`](#using-withtranslatorscomponent)\n  * [Locale switching](#locale-switching)\n* [API](#api)\n* [Contributing](#contributing)\n* [See also](#see-also)\n\n## Features\n\n* Context and plural\n* String interpolation using a `{{ variable }}` style syntax\n* **Component interpolation** with translatable child content using a `{{ link:Link text here }}` style syntax\n* [Locale switching](#locale-switching) on the fly\n\n## Installation\n\n```sh\nnpm install --save lioness\n\n# ...or the shorter...\nnpm i -S lioness\n```\n\n## Usage\n\nThis is an example app showing how to translate some text:\n\n```js\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport { LionessProvider, T } from 'lioness'\n\n// messages.json is a JSON file with all translations concatenated into one.\n// The format must conform to what node-gettext expects.\n//\n// See https://github.com/alexanderwallin/node-gettext#Gettext+addTranslations\nimport messages from './translations/messages.json'\n\nfunction App({ name, numPotatoes }) {\n  return (\n    \u003cLionessProvider\n      messages={messages}\n      locale=\"sv-SE\"\n      debug={/* true | false | null */}\n    \u003e\n      \u003cdiv className=\"App\"\u003e\n        \u003ch1\u003e\u003cT\u003ePotato inventory\u003c/T\u003e\u003c/h1\u003e\n        {/* =\u003e \u003ch1\u003e\u003cspan\u003ePotatisinventarie\u003c/span\u003e\u003c/h1\u003e */}\n\n        \u003cT\n          message=\"Dear {{ name }}, there is one potato left\"\n          messagePlural=\"Dear {{ name }}, there are {{ count }} potatoes left\"\n          count={numPotatoes}\n          name={name}\n        /\u003e\n        {/* =\u003e \u003cspan\u003eKära Ragnhild, det finns 2 potatisar kvar\u003c/span\u003e */}\n\n        \u003cT\n          message=\"By more potatoes {{ link:here }}!\"\n          link={\u003ca href=\"http://potatoes.com/buy\" /\u003e}\n        /\u003e\n        {/* =\u003e \u003cspan\u003eKöp mer potatis \u003ca href=\"http://potatoes.com/buy\"\u003ehär\u003c/a\u003e!\u003c/span\u003e */}\n      \u003c/div\u003e\n    \u003c/LionessProvider\u003e\n  )\n}\n\nReactDOM.render(\n  \u003cApp name=\"Ragnhild\" numPotatoes={Math.round(Math.random() * 3))} /\u003e,\n  document.querySelector('.app-root')\n)\n```\n\n### Using `\u003cT /\u003e`\n\n`\u003cT /\u003e` exposes a set of props that make it easy to translate and interpolate your content. Being a React component, it works perfect for when you are composing your UI, like with the example above.\n\n### Using `withTranslators(Component)`\n\nSometimes, you will need to just translate and interpolate pure strings, without rendering components. To do this you can hook up your components with translator functions using the `withTranslators(Component)` composer function.\n\n`withTranslators(Component)` will provide any component you feed it with a set of translator functions as props. Those props are: `t`, `tn`, `tp`, `tnp`, `tc`, `tcn`, `tcp` and `tcnp`.\n\n```js\nimport { withTranslators } from 'lioness'\n\nfunction PotatoNotification({ notificationCode, t }) {\n  let message = ''\n\n  if (notificationCode === 'POTATOES_RECEIVED') {\n    message = t(`You have received potatoes`)\n  } else if (notificationCode === 'POTATOES_STOLEN') {\n    message = t(`Someone stole all your potatoes :(`)\n  }\n\n  return \u003cspan\u003e{message}\u003c/span\u003e\n}\n\nexport default withTranslators(PotatoNotification)\n```\n\n### Via [`babel-plugin-react-gettext-parser`](http://github.com/alexanderwallin/babel-plugin-react-gettext-parser)\n\n```js\n// .babelrc\n{\n  ...\n  \"plugins\": [\n    [\"react-gettext-parser\", {\n      \"output\": \"gettext.pot\",\n      \"funcArgumentsMap\": {\n        \"tc\": [\"msgid\", null],\n        \"tcn\": [\"msgid\", \"msgid_plural\", null, null],\n        \"tcp\": [\"msgctxt\", \"msgid\", null],\n        \"tcnp\": [\"msgctxt\", \"msgid\", \"msgid_plural\", null, null],\n\n        \"t\": [\"msgid\"],\n        \"tn\": [\"msgid\", \"msgid_plural\", null],\n        \"tp\": [\"msgctxt\", \"msgid\"],\n        \"tnp\": [\"msgctxt\", \"msgid\", \"msgid_plural\", null]\n      },\n      \"componentPropsMap\": {\n        \"T\": {\n          \"message\": \"msgid\",\n          \"messagePlural\": \"msgid_plural\",\n          \"context\": \"msgctxt\",\n          \"comment\": \"comment\"\n        }\n      }\n    }]\n  ]\n  ...\n}\n```\n\n### Locale switching\n\nLioness makes it possible to change locale and have all the application's translations instantly update to those of the new locale. `\u003cLionessProvider\u003e` will trigger a re-render of all `\u003cT\u003e` components and components wrapped in `withTranslators()` whenever its `locale` or `messages` props change.\n\n**Note:** For performance reasons, and in favour of immutability, this check is done using shallow equality, which means you need to pass an entirely new object reference as `messages` for it to trigger the re-render. If this is an issue for you, simply make sure you create a new object when you get new messages, for instace by using something like `messages = Object.assign({}, messages)`.\n\n## API\n\nThe following table indicates how gettext strings map to parameters in `withTranslations` and props for `\u003cT /\u003e`\n\n| Gettext      | `withTranslations` | `\u003cT /\u003e`       |\n| ------------ | ------------------ | ------------- |\n| msgctxt      | context            | context       |\n| msgid        | message \\| one     | message       |\n| msgid_plural | other              | messagePlural |\n\n### `withTranslations(Component)`\n\nProvides `Component` with the `lioness` context variables as props. These are `locale`, `t`, `tn`, `tp`, `tnp`, `tc`, `tcn`, `tcp` and `tcnp`.\n\nAs a little helper, here's what the letters stand for:\n\n| Letter | Meaning                           | Parameters              |\n| ------ | --------------------------------- | ----------------------- |\n| t      | translate a message               | `message`               |\n| c      | ...with injected React components | -                       |\n| n      | ...with pluralisation             | `one`, `other`, `count` |\n| p      | ...in a certain gettext context   | `context`               |\n\n* #### `locale`\n\n  The currently set locale passed to `\u003cLionessProvider /\u003e`.\n\n* #### `t(message, scope = {})`\n\n  Translates and interpolates message.\n\n* #### `tn(one, other, count, scope = {})`\n\n  Translates and interpolates a pluralised message.\n\n* #### `tp(context, message, scope = {})`\n\n  Translates and interpolates a message in a given context.\n\n* #### `tnp(context, one, other, count, scope = {})`\n\n  Translates and interpolates a pluralised message in a given context.\n\n* #### `tc(message, scope = {})`\n\n  Translates and interpolates a message.\n\n* #### `tcn(one, other, count, scope = {})`\n\n  Translates and interpolates a pluralised message.\n\n* #### `tcp(context, message, scope = {})`\n\n  Translates and interpolates a message in a given context.\n\n* #### `tcnp(context, one, other, count, scope = {})`\n\n  Translates and interpolates a plural message in a given context.\n\n### `\u003cLionessProvider /\u003e`\n\nA higher-order component that provides the translation functions and state to `\u003cT /\u003e` through context.\n\n**Props:**\n\n* `messages` – An object containing translations for all languages. It should have the format created by [gettext-parser](https://github.com/smhg/gettext-parser)\n* `locale` – The currently selected locale (which should correspond to a key in `messages`)\n* `gettextInstance` - A custom [node-gettext](https://github.com/alexanderwallin/node-gettext) instance. If you provide the `messages` and/or `local` props they will be passed on to this instance.\n* `transformInput` – A function `(input: String) =\u003e String` that you can use to transform a string before `\u003cT /\u003e` sends it to the translation function. One use case is normalising strings when something like [`prettier`](https://github.com/prettier/prettier) puts child content in `\u003cT /\u003e` on new lines, with lots of indentation. The default is a function that simply returns the input as is.\n\n## Contributing\n\nAll PRs that passes the tests are very much appreciated! 🎂\n\n## See also\n\n* [node-gettext](https://github.com/alexanderwallin/node-gettext) - A JavaScript implementation of Gettext.\n* [gettext-parser](https://github.com/smhg/gettext-parser) – A parser between JSON and .po/.mo files. The JSON has the format required by this library.\n* [react-gettext-parser](https://github.com/laget-se/react-gettext-parser) – A utility that extracts translatable content from JavaScript code.\n* [narp](https://github.com/laget-se/narp) – A workflow utility for extracting, uploading, downloading and integrating translations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexanderwallin%2Flioness","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexanderwallin%2Flioness","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexanderwallin%2Flioness/lists"}