{"_id":"@emirotin/i18next-light","_rev":"3-fd98cb21ae3f857c2e27e3ced59a4a45","name":"@emirotin/i18next-light","dist-tags":{"latest":"1.0.1-2"},"versions":{"1.0.1-0":{"name":"@emirotin/i18next-light","version":"1.0.1-0","description":"i18next lightweight client-side companion","main":"index.js","module":"./src/index.js","types":"./index.d.ts","keywords":["i18next","internationalization","i18n","translation","localization","l10n","globalization","gettext"],"homepage":"https://github.com/emirotin/i18next-light","bugs":{"url":"https://github.com/emirotin/i18next-light/issues"},"repository":{"type":"git","url":"git+https://github.com/emirotin/i18next-light.git"},"dependencies":{"@babel/runtime":"^7.9.6"},"devDependencies":{"@babel/core":"^7.9.6","@babel/plugin-proposal-async-generator-functions":"^7.8.3","@babel/plugin-proposal-object-rest-spread":"^7.9.6","@babel/plugin-transform-modules-commonjs":"^7.9.6","@babel/plugin-transform-runtime":"^7.9.6","@babel/polyfill":"^7.8.7","@babel/preset-env":"^7.9.6","@babel/register":"^7.9.0","@typescript-eslint/eslint-plugin":"^2.30.0","@typescript-eslint/parser":"^2.30.0","babel-eslint":"^10.1.0","chai":"^4.2.0","cpy-cli":"^2.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.11.0","eslint-plugin-prettier":"^3.1.3","husky":"^4.2.5","karma":"^5.0.0","karma-chai":"^0.1.0","karma-chrome-launcher":"^3.1.0","karma-mocha":"^2.0.1","karma-spec-reporter":"^0.0.32","lint-staged":"^10.2.2","markdown-toc":"^1.2.0","mocha":"^3.2.0","npm-run-all":"^4.1.5","prettier":"^2.0.5","rimraf":"^2.5.4","rollup":"^1.1.2","rollup-plugin-babel":"^4.4.0","rollup-plugin-commonjs":"^9.2.0","rollup-plugin-node-resolve":"^4.0.0","rollup-plugin-terser":"^4.0.4","typescript":"^3.8.3"},"scripts":{"lint":"eslint \"src/*.js\"","pretest":"run-s prettify lint test:typescript test:typescript:noninterop","test:node":"mocha --require test/node-support.js \"test/**/*.spec.js\"","test:browser":"karma start karma.conf.js","test":"run-s test:node test:browser","test:typescript":"eslint -c .eslintrc.ts.js \"./**/*.ts\"","test:typescript:noninterop":"eslint -c .eslintrc.ts.nonEsModuleInterop.js \"./**/*.ts\"","tdd":"karma start karma.conf.js","build":"rimraf dist && rollup -c && cpy \"./dist/umd/*.js\" ./","preversion":"run-s test build && git commit -am 'preversion build' --allow-empty && git push","postversion":"git push && git push --tags","prettify":"prettier --write \"{,**/}*.{ts,tsx,js,json,md}\""},"author":{"name":"Eugene Mirotin","email":"emirotin@gmail.com"},"license":"MIT","husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"*.{ts,tsx}":["yarn prettify","yarn eslint -c .eslintrc.ts.js"],"*.js":["yarn prettify","yarn lint"],"*.{json,md}":["yarn prettify"],"README.md":["markdown-toc -i"]},"browserslist":["defaults","> 2%","not dead"],"contributors":[{"name":"Eugene Mirotin","email":"emirotin@gmail.com"},{"name":"Jan Mühlemann","email":"jan.muehlemann@gmail.com","url":"https://github.com/jamuhl"}],"gitHead":"646a519ee1df2b8037f907084d1b2fd0c4888683","_id":"@emirotin/i18next-light@1.0.1-0","_nodeVersion":"12.16.3","_npmVersion":"6.14.4","dist":{"integrity":"sha512-+uTJ8FRKwrWefBSBk8qpXDOR+Jvb3cw/efCQKTt0oRSI4mdmCMuqjTsVzD/lHbz8FRlVlP7dPjjwCDnO3U3Byw==","shasum":"5501477a4fb341bc062e1d3bc5944592932779d9","tarball":"https://registry.npmjs.org/@emirotin/i18next-light/-/i18next-light-1.0.1-0.tgz","fileCount":24,"unpackedSize":483850,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeupfvCRA9TVsSAnZWagAAEGsP/1CLSlt2th/CquVd2naF\nJHkey2MjcAYthOR79MZ5grU6+fC0cvClJbaECtwlkEaYn4kjvPtuLMce5FWM\nkUKTj1HTeX8elsUJAyfmV1/p7RSRVrKQN4QQuofDo2V4XSKdlJAnqBD7mT52\nm2r7WLI+SCe1iexdh51oP8mf+/CdchYcLTfBg77cUMrhNlSmw4zukcdP+H1i\n2eMUEqdWuRKurr3VOfj9pwu66FPUd9gb/t80h4BLuDUsZD1wj6DCYv2zQoyJ\nsofL8czJEXRJoI5sEs5L3yZZvX3yWpZCH/inFLQwfA4H2zcU+0gXA820FqdZ\nM7DZZS0n8hsF+ybJoj1ldT+6cOXKO4RhZpWREhIXWwQwiOfCPhpDzzLN/4ct\nnp9FNOrQlOr26u9dgaamwPx1tXemV1MsD1IjbeiRZP2te8jSuMRL33Uz8bBM\nEzZySZ7y/XOcdYv4AgPYH0n6e1s1Few6zOh+IQnutNuMgq0M5AHrIawoyxk9\nOG3YUYNfkMEdoyu8VAgpiNdNGTizAfzS3IuiVVPaG3Vh+UP5mn5fR3V4BrED\nK1gmYYXdR63kK+aFw4YcV1xfgMSdi1lBy3AluIW0Gir+BiCVfM6F3tF8d+/0\n7F9AFb9Q0tMYV4lJ/J5SRUH1B20ZZMnWx0mO/wTjc62/3jd+H7546wGGurYC\noe4M\r\n=fhjo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC3xb+k2hiAkeJLKTwWCwVBLmd07coyZ5els4RqhVRf1AiEA6UdcPcp03Qd/wM0glOvxJsGuJxQH7j88O0Uqyr4lPSs="}]},"maintainers":[{"name":"emirotin","email":"emirotin@gmail.com"}],"_npmUser":{"name":"emirotin","email":"emirotin@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/i18next-light_1.0.1-0_1589286894688_0.27304636819164907"},"_hasShrinkwrap":false},"1.0.1-1":{"name":"@emirotin/i18next-light","version":"1.0.1-1","description":"i18next lightweight client-side companion","main":"index.js","module":"./src/index.js","types":"./index.d.ts","keywords":["i18next","internationalization","i18n","translation","localization","l10n","globalization","gettext"],"homepage":"https://github.com/emirotin/i18next-light","bugs":{"url":"https://github.com/emirotin/i18next-light/issues"},"repository":{"type":"git","url":"git+https://github.com/emirotin/i18next-light.git"},"dependencies":{"@babel/runtime":"^7.9.6"},"devDependencies":{"@babel/core":"^7.9.6","@babel/plugin-proposal-async-generator-functions":"^7.8.3","@babel/plugin-proposal-object-rest-spread":"^7.9.6","@babel/plugin-transform-modules-commonjs":"^7.9.6","@babel/plugin-transform-runtime":"^7.9.6","@babel/polyfill":"^7.8.7","@babel/preset-env":"^7.9.6","@babel/register":"^7.9.0","@typescript-eslint/eslint-plugin":"^2.30.0","@typescript-eslint/parser":"^2.30.0","babel-eslint":"^10.1.0","chai":"^4.2.0","cpy-cli":"^2.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.11.0","eslint-plugin-prettier":"^3.1.3","husky":"^4.2.5","karma":"^5.0.0","karma-chai":"^0.1.0","karma-chrome-launcher":"^3.1.0","karma-mocha":"^2.0.1","karma-spec-reporter":"^0.0.32","lint-staged":"^10.2.2","markdown-toc":"^1.2.0","mocha":"^3.2.0","npm-run-all":"^4.1.5","prettier":"^2.0.5","rimraf":"^2.5.4","rollup":"^1.1.2","rollup-plugin-babel":"^4.4.0","rollup-plugin-commonjs":"^9.2.0","rollup-plugin-node-resolve":"^4.0.0","rollup-plugin-terser":"^4.0.4","typescript":"^3.8.3"},"scripts":{"lint":"eslint \"src/*.js\"","pretest":"run-s prettify lint test:typescript test:typescript:noninterop","test:node":"mocha --require test/node-support.js \"test/**/*.spec.js\"","test:browser":"karma start karma.conf.js","test":"run-s test:node test:browser","test:typescript":"eslint -c .eslintrc.ts.js \"./**/*.ts\"","test:typescript:noninterop":"eslint -c .eslintrc.ts.nonEsModuleInterop.js \"./**/*.ts\"","tdd":"karma start karma.conf.js","build":"rimraf dist && rollup -c && cpy \"./dist/umd/*.js\" ./","preversion":"run-s test build && git commit -am 'preversion build' --allow-empty && git push","postversion":"git push && git push --tags","prettify":"prettier --write \"{,**/}*.{ts,tsx,js,json,md}\""},"author":{"name":"Eugene Mirotin","email":"emirotin@gmail.com"},"license":"MIT","husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"*.{ts,tsx}":["yarn prettify","yarn eslint -c .eslintrc.ts.js"],"*.js":["yarn prettify","yarn lint"],"*.{json,md}":["yarn prettify"],"README.md":["markdown-toc -i"]},"browserslist":["defaults","> 2%","not dead"],"contributors":[{"name":"Eugene Mirotin","email":"emirotin@gmail.com"},{"name":"Jan Mühlemann","email":"jan.muehlemann@gmail.com","url":"https://github.com/jamuhl"}],"gitHead":"ad4153d4b72cc8a1184ff8026b4e363046c9ff14","_id":"@emirotin/i18next-light@1.0.1-1","_nodeVersion":"12.16.3","_npmVersion":"6.14.4","dist":{"integrity":"sha512-3/4UjTMcDlKPMXMke4/f+1Pa7xMYbdohU8/71xQTk20pm1c69JEwBlen5dcnGoZJSsrLLRQ4Zrsms3fYFOzp+A==","shasum":"c04c3401aa6a57be404fda9061314e0f66fb47c9","tarball":"https://registry.npmjs.org/@emirotin/i18next-light/-/i18next-light-1.0.1-1.tgz","fileCount":24,"unpackedSize":483509,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeuphKCRA9TVsSAnZWagAAFeQQAJ0fIqruOw/f2AiRNpVq\nDMVupPjCE/rhunK2a7TId0/pPnGnr3eOxza7FEUpwIICvBOaUhGNb+gqlmC+\nYRA/AXLZNiSmX1BASy4E9ChrRLruYyzyVpM/GCuhznykQ3XI5VnwQyQTfgEJ\n4LPwO0dYlwet2mexbq+o2ctqmVJut+kmd46vVZ0WBhkiKE07bd1Dr6OL/kuY\n5jUKaIQ2xVvpPFvEoISBhegph3tXYlOCc8LLPfa80fkXh1RQx3EXKJEsCF0u\nPcGUoRrHhduWTfnawk1yOQckM9LlYtfPCsANaf/BezHD3KcRgvZkhofV7pDN\np6fvpisqYINNPtvKJQlGDlOh/YU3As8H4EVU7H442V1BWWLRdsEhHPChpK7i\nc9EQU8012tYFXs+jlH6JiNK/0AZu3nHuM5OGW4cqo84HouoBPdKo6p6NM2z9\nPASvbMVQeS2hw6XcE3L30iR51CUdh869UvCczumQqtuv25mC5VYkkigmyCzT\nufTwT4OPrpMxYxfAcJyB1HFuEtpJEV5WdAYgos8ZOXepPvprpXxbKiWwHvPF\nhakqZ0BItpoOw/aCWzvAn/DttbZ2z87SJJsTyRVsIeawDBoePQ5EG1YITn3x\nU8HxmtW/nwZjZrfeslD8CB1QaMukq/fkD2AVTK88XUhvbG3fk0C1FYjBQ3oF\nRV6A\r\n=Llca\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHn5AhCpnEt27pnJT05fsqiDUYN5mhSzRFj+TdJTNXYbAiEA64h1sqNZ2kNsPsl+RDMT+eOWMtj9YIfZp57IW+2xuvM="}]},"maintainers":[{"name":"emirotin","email":"emirotin@gmail.com"}],"_npmUser":{"name":"emirotin","email":"emirotin@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/i18next-light_1.0.1-1_1589286985575_0.2600879724091063"},"_hasShrinkwrap":false},"1.0.1-2":{"name":"@emirotin/i18next-light","version":"1.0.1-2","description":"i18next lightweight client-side companion","main":"index.js","module":"./src/index.js","types":"./index.d.ts","keywords":["i18next","internationalization","i18n","translation","localization","l10n","globalization","gettext"],"homepage":"https://github.com/emirotin/i18next-light","bugs":{"url":"https://github.com/emirotin/i18next-light/issues"},"repository":{"type":"git","url":"git+https://github.com/emirotin/i18next-light.git"},"dependencies":{"@babel/runtime":"^7.9.6"},"devDependencies":{"@babel/core":"^7.9.6","@babel/plugin-proposal-async-generator-functions":"^7.8.3","@babel/plugin-proposal-object-rest-spread":"^7.9.6","@babel/plugin-transform-modules-commonjs":"^7.9.6","@babel/plugin-transform-runtime":"^7.9.6","@babel/polyfill":"^7.8.7","@babel/preset-env":"^7.9.6","@babel/register":"^7.9.0","@typescript-eslint/eslint-plugin":"^2.30.0","@typescript-eslint/parser":"^2.30.0","babel-eslint":"^10.1.0","chai":"^4.2.0","cpy-cli":"^2.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.11.0","eslint-plugin-prettier":"^3.1.3","husky":"^4.2.5","karma":"^5.0.0","karma-chai":"^0.1.0","karma-chrome-launcher":"^3.1.0","karma-mocha":"^2.0.1","karma-spec-reporter":"^0.0.32","lint-staged":"^10.2.2","markdown-toc":"^1.2.0","mocha":"^3.2.0","npm-run-all":"^4.1.5","prettier":"^2.0.5","rimraf":"^2.5.4","rollup":"^1.1.2","rollup-plugin-babel":"^4.4.0","rollup-plugin-commonjs":"^9.2.0","rollup-plugin-node-resolve":"^4.0.0","rollup-plugin-terser":"^4.0.4","typescript":"^3.8.3"},"scripts":{"lint":"eslint \"src/*.js\"","pretest":"run-s prettify lint test:typescript test:typescript:noninterop","test:node":"mocha --require test/node-support.js \"test/**/*.spec.js\"","test:browser":"karma start karma.conf.js","test":"run-s test:node test:browser","test:typescript":"eslint -c .eslintrc.ts.js \"./**/*.ts\"","test:typescript:noninterop":"eslint -c .eslintrc.ts.nonEsModuleInterop.js \"./**/*.ts\"","tdd":"karma start karma.conf.js","build":"rimraf dist && rollup -c && cpy \"./dist/umd/*.js\" ./","preversion":"run-s test build && git commit -am 'preversion build' --allow-empty && git push","postversion":"git push && git push --tags","prettify":"prettier --write \"{,**/}*.{ts,tsx,js,json,md}\""},"author":{"name":"Eugene Mirotin","email":"emirotin@gmail.com"},"license":"MIT","husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"*.{ts,tsx}":["yarn prettify","yarn eslint -c .eslintrc.ts.js"],"*.js":["yarn prettify","yarn lint"],"*.{json,md}":["yarn prettify"],"README.md":["markdown-toc -i"]},"browserslist":["defaults","> 2%","not dead"],"contributors":[{"name":"Eugene Mirotin","email":"emirotin@gmail.com"},{"name":"Jan Mühlemann","email":"jan.muehlemann@gmail.com","url":"https://github.com/jamuhl"}],"gitHead":"9ceae9e185c8135504bd21b0699f48e38669d931","_id":"@emirotin/i18next-light@1.0.1-2","_nodeVersion":"12.16.3","_npmVersion":"6.14.4","dist":{"integrity":"sha512-NvLqYM1vfd0ns6td9qKhAozDm2vkQy4pNQR3E8/mYYnroET34WQnvePTT3spSq1s3jbCN+FDlCsrooE6e1Hwrg==","shasum":"f614b1f2b42c496f2a893bd96c032da29f0d24eb","tarball":"https://registry.npmjs.org/@emirotin/i18next-light/-/i18next-light-1.0.1-2.tgz","fileCount":21,"unpackedSize":125372,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeupsUCRA9TVsSAnZWagAAkVMQAI+8RwLBBxNBBQNIqqkp\nfYcj1L7QUZ+2KQ6m9JbEUrIpLk8qahgUcoHaPDr5ujeiG95bOn4+zf1BL2oW\nrpv3h8A2QgqXRbk9Li9Njpqvqf1CZvsmnc/+YLyN0RAJV4AhfzXNJKCQrPLS\nBTGx5Wq7DLrVEPhnT18/VmNpeMcGd5QOpETmxZTGGTgcLDN7Y4kz+cKQm+pD\nF47UWTkA+meo9nCx3w3seQGUiRKQJBBv4RXbzqyWE5H3cdgH+9WB1X60gfUK\nE5HS817PZX5eFzAciz98XR0kHOjEvM9zHFDtThyQNfN9RvixAO/eKM0lF0/e\nR/3KWX1G0TBffr3raOLHlKaq1h60sGCEkVnzAOLGkIhLbnyoLUNyma2dGmKK\nG6uazPrMZINNkEXsHOzUrzwzcxkAutpC39+LfuJaLvDbHOFvXb/ZAMFfuxFH\nEeroBSd0tbokg/O9hjuc9qKTOX4Rm5CzTUvtUuP52pbm9iVtl0tCpWNcaQiV\n9ooKze0jwdlwCuDCjVo4ZCUfrsWhUh8uh/0cV9xgk0yhzdnCi2a0G+wW7xxX\nJa8utFHcEvApUFGNX4z48bTzU+lsIwnHEpJpmaqj/mh4yj8x1roySOKQ6+TR\nZvUR9wWLzr2sDhVwG9bmWZIKWcSDSbBIZInVqqmRX+21GKZvhMPx5RsdRA4K\ngqh5\r\n=XHOx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDUoDDhq51ClKN6Z1Y7FxD2/NNFihSwHj/Y3aIaClDQOAIgT7SZxI2/IzElPacSWDtvKiwfUwugKYxaCB5ULBGJOMk="}]},"maintainers":[{"name":"emirotin","email":"emirotin@gmail.com"}],"_npmUser":{"name":"emirotin","email":"emirotin@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/i18next-light_1.0.1-2_1589287700503_0.08316231339661218"},"_hasShrinkwrap":false}},"time":{"created":"2020-05-12T12:34:54.652Z","1.0.1-0":"2020-05-12T12:34:54.854Z","modified":"2022-04-05T07:33:41.684Z","1.0.1-1":"2020-05-12T12:36:25.711Z","1.0.1-2":"2020-05-12T12:48:20.635Z"},"maintainers":[{"name":"emirotin","email":"emirotin@gmail.com"}],"description":"i18next lightweight client-side companion","homepage":"https://github.com/emirotin/i18next-light","keywords":["i18next","internationalization","i18n","translation","localization","l10n","globalization","gettext"],"repository":{"type":"git","url":"git+https://github.com/emirotin/i18next-light.git"},"contributors":[{"name":"Eugene Mirotin","email":"emirotin@gmail.com"},{"name":"Jan Mühlemann","email":"jan.muehlemann@gmail.com","url":"https://github.com/jamuhl"}],"author":{"name":"Eugene Mirotin","email":"emirotin@gmail.com"},"bugs":{"url":"https://github.com/emirotin/i18next-light/issues"},"license":"MIT","readme":"# `i18next-light`: a lightweight companion for `i18next`\n\n[![CircleCI](https://circleci.com/gh/emirotin/i18next-light.svg?style=svg)](https://circleci.com/gh/emirotin/i18next-light)\n\n> `i18next-light` is a simplified and _much smaller_ version of `i18next` intended for the client-usage when you already have the prepackaged i18n strings.\n\n```bash\nnpm install --save i18next-light\n```\n\nor\n\n```bash\nyarn add i18next-light\n```\n\n---\n\n**Table of Contents:**\n\n<!-- toc -->\n\n- [Motivation](#motivation)\n- [What can `i18next-light` do](#what-can-i18next-light-do)\n  - [What's the use of i18n with a single language?](#whats-the-use-of-i18n-with-a-single-language)\n  - [Will multi-language be implemented in the future?](#will-multi-language-be-implemented-in-the-future)\n  - [Will there be namespaces implementation in the future?](#will-there-be-namespaces-implementation-in-the-future)\n  - [Will there be more features added/returned?](#will-there-be-more-features-addedreturned)\n- [How was this implemented](#how-was-this-implemented)\n  - [And what's the difference in size?](#and-whats-the-difference-in-size)\n- [API](#api)\n  - [Initialize the instance](#initialize-the-instance)\n    - [Load the library](#load-the-library)\n    - [Create the instance](#create-the-instance)\n    - [Options](#options)\n  - [Instance properties and methods](#instance-properties-and-methods)\n  - [Translation function (`i18n.t`)](#translation-function-i18nt)\n  - [Key existence function (`i18n.exists`)](#key-existence-function-i18nexists)\n  - [Custom formatting function](#custom-formatting-function)\n  - [Custom logger contract](#custom-logger-contract)\n- [Browsers support](#browsers-support)\n- [Differences from the original `i18next`](#differences-from-the-original-i18next)\n\n<!-- tocstop -->\n\n---\n\n## Motivation\n\n[`i18next`](https://github.com/i18next/i18next) is a powerful tool that nicely handles many aspects of i18n: it handles namepsaces, multiple languages with fallbacks, interpolation, pluralization, nested translations, missing tanslations handling, etc.\n\nUnfortunately, it's not modular (as of the moment of `i18next-light` inception) and the bundled project has the significant size (~44KiB minified but not gzipped).\n\nI had a use-case where my website is mostly static and needs i18n support (build-time) while also having some dynamic parts that also need access to the translated strings with interpolation.\n\nSo I was happy to use `i18next` at build time but wasn't happy carying it over to the JS bundle let alone bundling all the i18n strings JSON where a single page may need 5 % or at most 10 % of them.\n\nSo this project was created — a much simpler and lighter (~8 KiB minified but not gzipped) library responsible for the following tasks only:\n\n- find the strings (\"resources\") in the provided hash (_single language only_),\n- handle intrerpolation with formatting,\n- handle pluralization and context,\n- handle nested translations.\n\n## What can `i18next-light` do\n\nIt can:\n\n- find the strings (\"resources\") by key in the provided hash (_single language only_),\n- handle [intrerpolation](https://www.i18next.com/translation-function/interpolation) with [formatting](https://www.i18next.com/translation-function/formatting),\n- handle [pluralization](https://www.i18next.com/translation-function/plurals) and [context](https://www.i18next.com/translation-function/context)-specific translations,\n- handle [nested translations](https://www.i18next.com/translation-function/nesting).\n\n### What's the use of i18n with a single language?\n\nThis is one scenario, for example.\n\nI have a mostly static website built using the static site generator. At build time using the same templates I procude language-specific pages using the full `i18next` library power.\n\nI also need _some_ i18n strings available client-side, really few compared to the total number of resources (like 2-5 per page while we have a total of hundreds of resources).\n\nI determine all such strings at build time and put them into a global object injected into my page before any other JS:\n\n```html\n<script>\n  window.__I18N__ = {\n    \"apples-guilty\": \"I've eaten 1 apple out of {{total}}\",\n    \"apples-guilty_plural\": \"I've eaten {{count}} apples out of {{total}}\",\n  };\n</script>\n<script src=\"/main.js\"></script>\n<script src=\"/my-page.js\"></script>\n```\n\nThen in my scripts I can initialize the `i18n` object and use it:\n\n```javascript\nconst i18n = i18next({ lng: \"en\", resources: window.__I18N__ });\nconsole.log(\n  i18n.t(\"apples-guilty\", {\n    count: 7,\n    total: 7,\n  })\n);\n```\n\nThis way my JS is universal and language-agnostic, and only my HTML pages are different per language.\n\nThis works great with reactive soultions as well as you can directly use `t` in your render code or provide it as a filter. For example, you can have proper pluralization with React by keeping the `count` in the component's state and using `t` in the render method. Or use svelte's `$` blocks to make the computed string based on the `count` variable.\n\n### Will multi-language be implemented in the future?\n\nIt may happen because I can imagine how this library can be useful in multi-language client-side scenario. At the same time there's no guarantees as I don't need this right now and I want to keep the size minimal possible. If you have a good use-case please open an issue for discussion.\n\n### Will there be namespaces implementation in the future?\n\nI don't think so. So far I see how namespaces work good when the same resources are shared across multiple projects (I have such a use-case) but merging the namespaces is trivial (using `reduce`, for example) and can be handled in the userland.\n\n### Will there be more features added/returned?\n\nVery unlikely. The sole purpose of this project is to nicely handle interpolation and pluralization on the provided set of resources. But if you have a really good use-case for another feature please open an issue for discussion.\n\n## How was this implemented\n\nI've first stripped all the functionality that I decided to drop (backend support, custom configuration options, namespaces, multilanguage, etc.) and simplified the code by dropping the ever-false conditions.\n\nI have then rewritten the rest from classes to singleton objects (where no config nor state were left) and object factories.\n\nThen, I've improved the Babel transpilation by providing the `browserslist` config to avoid transpiling things that are natively supported by the modern browsers.\n\nI've removed the tests specific to the removed functionality and kept _all the rest_. The majority of them were left without changes, those where the functionality was changed — adapted and updated. At the time of creation there are _207 test-cases_ in this project.\n\nI've also added Node.js testing in addition to the browser testing used in the original project (with Chrome/karma).\n\nI've also removed the ES module transpilation, the original source code is the ES entry point and can be used by the bundlers that support the `module` declaration in `package.json`. The transpiled CommonJS version is still available form the `dist` folder and is `require`d by the runtimes (like Node.js) that use the `main` field. The UMD version is also available as `i18next-light.js` and `i18next-light.min.js` files in the root folder of the project.\n\n### And what's the difference in size?\n\nThe `.min.js` file in the original project is `44KiB`, the similar file in this project is around `8KiB`.\n\nIt may not be a huge difference if your bundle is already over 1MiB (which may be something to worry about in the first place) but for me it resulted in 2x bundle reduction for some pages, for example.\n\n## API\n\nThe API is similar to the original project but simpler because of the reduced scope. Please remember this **is not a drop-in replacement** for the original library but it's deliberately similar to it.\n\n### Initialize the instance\n\n#### Load the library\n\nUsing ES6 import:\n\n```javascript\nimport i18next from \"i18next-light\";\n```\n\nUsing CommonJS:\n\n```javascript\nconst i18next = require(\"i18next-light\");\n```\n\nOr loading the UMD build in your browser:\n\n```html\n<script src=\"/vendor/i18next-light.min.js\"></script>\n<script>\n  const i18next = window[\"i18next-light\"];\n</script>\n```\n\n#### Create the instance\n\n```javascript\nconst i18n = i18next({\n  lng: \"en\",\n  resources: {\n    key: \"string\",\n    // ...\n  },\n  // ...\n});\n```\n\n#### Options\n\nThe factory method `i18next` accepts a single configuration parameter that can have the following options:\n\n| Option                | Required | Type       | Default                | Description                                                                                                                                  |\n| --------------------- | -------- | ---------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |\n| `lng`                 | Y        | `string`   | `undefined`            | The language of the resources, used to properly determine plural forms if they're used, also passed to the formatting function if it's used. |\n| `resources`           | Y        | `object`   | `{}`                   | The plain object (string key to string value mapping) defining the keys correspondance to the resources (translation strings).               |\n| `debug`               | N        | `boolean`  | `false`                | When `true` causes the additional warnings printed to the console.                                                                           |\n| `maxReplaces`         | N        | `number`   | `1000`                 | The max number of nested translation replaces, needed to prevent the potential infinite loops. Most likely you don't need to change it.      |\n| `interpolationFormat` | N        | `function` | `value => value`       | The custom formatting function. See below for the contract description.                                                                      |\n| `logger`              | N        | `object`   | `console`-based logger | A custom logger can be provided for handling the debug warnings. See below for the contract description.                                     |\n| `logPrefix`           | N        | `string`   | `\"i18next-light:\"`     | The string that is prepended to the first log argument (if it's also a string).                                                              |\n\n### Instance properties and methods\n\nThe instance returned from the `i18next` factory has the following properties and methods:\n\n| Property       | Type       | Description                                                                                                                                                                                          |\n| -------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `t`            | `function` | The main method, the translation function, see below.                                                                                                                                                |\n| `exists`       | `function` | The method that checks if there's a translation for the given key or a specific variant of it (taking into account pluralization/context). The arguments are similar to the `t` function, see below. |\n| `dir`          | `function` | given the key code (like `\"en\"` or `\"ru-RU\"`) returns `\"rtl\"` or `\"ltr\"` depending on the language read direction.                                                                                   |\n| `options`      | `object`   | The options object merged from the defaults and the initialization options.                                                                                                                          |\n| `interpolator` | `object`   | The internal interpolator instance, see the [source code](https://github.com/emirotin/i18next-light/blob/master/src/Interpolator.js) if you need to use it directly.                                 |\n| `translator`   | `object`   | The internal translator instance, see the [source code](https://github.com/emirotin/i18next-light/blob/master/src/Translator.js) if you need to use it directly.                                     |\n\n### Translation function (`i18n.t`)\n\nThe core functionality of this library is the translation functon.\n\nIt has several call options:\n\n```javascript\ni18n.exists('key')\ni18n.exists(['key1', 'key2', ...])\ni18n.exists(['key1', 'key2', ...], { x: 1, y: 2 })\ni18n.exists(['key1', 'key2', ...], { count: 1, context: 'boy' })\ni18n.exists(['key1', 'key2', ...], 'default value')\ni18n.exists(['key1', 'key2', ...], { x: 1, y: 2, count: 1, context: 'boy',defaultValue: 'default value' })\n```\n\nThe first argument is a string (a key) or an array of strings (multiple keys, checked in order against the resources map until a match is found).\n\nThe second argument can be a string which would be used if no match is found.\n\nOr the second argument can be an _options object_. The _options object_ can contain any values for [interpolation](https://www.i18next.com/translation-function/interpolation) as well as two special values: `count` is used to determine the specific [pluralized](https://www.i18next.com/translation-function/plurals) key (if it exists), and `context` is used to pick the [context-specific](https://www.i18next.com/translation-function/context) key (if it exists).\n\nFor each key the following forms are checked in order:\n\n- with _context_ and with _plural_ (if `context` is provided and `count` are provided and the value of `count` requires the pluralized form for the provided `lng`),\n- with _context_ only (if `context` is provided),\n- with _plural_ only (if `count` is provided and the value of `count` requires the pluralized form for the provided `lng`),\n- the key itself.\n\nIf no matching key is found and the default value is provided (as the 2nd string argument or as a `defaultValue` option) it will be returned, otherwise the last key is returned as the translation (and a warning is printed).\n\nSee the [original documentation](https://www.i18next.com/translation-function/essentials) for more details, it applies except for the following topics:\n\n- this library does not allow special handling for arrays and objects as translation results,\n- deep resources object and the dot-separated deep keys are not handled, each key is a string and the resource at that key must be a string.\n\n### Key existence function (`i18n.exists`)\n\nThe function is similar to the `t` function and can be called like this:\n\n```javascript\ni18n.exists('key')\ni18n.exists(['key1', 'key2', ...])\ni18n.exists(['key1', 'key2', ...], { count: 1, context: 'boy' })\n```\n\nOptions other thn `count` and `context` have no effect.\n\n### Custom formatting function\n\nJust like the original project this library supports [formatting](https://www.i18next.com/translation-function/formatting) for the interpolated arguments.\n\nThe signature of this function is `(value: any, format: string, lng: string) => string`.\n\nGiven the example\n\n```javascript\nconst i18n = i18next({\n  lng: \"en\",\n  resources: {\n    key1: \"The current date is {{date, MM/DD/YYYY}}\",\n    key2: \"{{text, uppercase}} just uppercased\",\n  },\n  interpolationFormat: myFormatFunction,\n});\n\ni18n.t(\"key1\", { date: new Date() });\ni18n.t(\"key2\", { text: \"hello\" });\n```\n\nThe `myFormatFunction` will be called:\n\n- for `key1` with the arguments `(new Date(), 'MM/DD/YYYY', 'en')`,\n- for `key2` with the arguments `('hello', 'uppercase', 'en')`,\n\nAn example implementation of the formatting function could be:\n\n```javascript\nconst myFormatFunction = (value, format, lng) => {\n  if (format === \"uppercase\") {\n    return value.toUpperCase();\n  }\n  if (value instanceof Date) {\n    return moment(value).format(format);\n  }\n  if (typeof value === \"number\" && lng === \"ru\") {\n    return russianNumberFormatting(value);\n  }\n  return \"\" + value;\n};\n```\n\n### Custom logger contract\n\nThe custom logger is a simple object that must implement the 3 methods: `log`, `warn`, `error`. Each method should handle variable number of arguments.\n\nExample `console`-based logger implementation:\n\n```javascript\nconst consoleLogger = {\n  name: \"consoleLogger\",\n  log: (...args) => {\n    typeof console !== \"undefined\" && console.log(...args);\n  },\n\n  warn: (...args) => {\n    typeof console !== \"undefined\" && console.warn(...args);\n  },\n\n  error: (...args) => {\n    typeof console !== \"undefined\" && console.error(...args);\n  },\n};\n```\n\n## Browsers support\n\nThis project is built with the following `browserslist` configuration:\n\n```\n\"defaults\",\n\"> 2%\",\n\"not dead\"\n```\n\nThis allows for many ES6 features to be used natiely, like arrow functions, splats, etc.\n\nIf you have any specific use-case of a non-dead browser not handling this library properly please raise an issue.\n\n## Differences from the original `i18next`\n\nThis library has the following differences compared to the original `i18next` project:\n\n- the initialization API is different, you pass the options to the factory method rather than using the `.init` call: `const i18n = i18next({ ... })`,\n- there's no support for various backend implementations, you pass the `resources` as a plain object directly to the factory function,\n- it does not support multiple languages, you determine the language-specific resources to be passed to it in your code (see the use-case above), as a result it also has no support for fallback language, languages array, `changeLanguage` methods, whitelists, etc.,\n- it does not support namespaces, you need to merge your resources yourself before providing them,\n- it does not support saving the missing keys (because it has no backend), it will just report them in the `debug` mode,\n- it also does not have the special handling for the CI case, just provide an empty `resources` object there and you will get the keys as translations,\n- it always does plural suffix simplification — when like in English there are only two forms the keys checked are `key_plural` and `key` (otherwise the numeric suffixes are used, see [the original docs](https://www.i18next.com/translation-function/plurals#languages-with-multiple-plurals)),\n- it has no special handling for arrays and ojects as translation results,\n- it allows resources to be empty strings or `null`, which is also treated as an empty string,\n- it has no support for the legacy formats (for interpolation and the like),\n- it doesn't support `defaultVariables`, if you need them merge your `t` options in your code,\n- nested keys (`key1.key2` as in `{ resources: { key1: { key2: 'translation here; } } }`) are not supported, flatten your resources before passing to the library,\n- `t` option `replace` is not used, pass the interpolation data directly in the `options` object as the 2nd arguement of `t`: `t('key', { count: 1, total: 7 })`,\n- `t` options do not override anything passed when initialing the `i18n` object, like formatting function,\n- `options.interpolation.maxReplaces => options.maxReplaces`,\n- `options.interpolation.format => options.interpolationFormat`,\n- only the default syntax is supported: interpolation is `{{var}}`, formatting is always `{{var, format}}`, nesting is always `$t()`, plural and context separator — always `_`,\n- reduced the browsers support to `> 2 %, not dead`.\n\n---\n\nAuthor: Eugene Mirotin <emirotin@gmail.com>\n","readmeFilename":"README.md"}