{"_id":"@agencyanalytics/i18n-extract","_rev":"2-be3d61cd2feb81c3495772dcf41d1076","name":"@agencyanalytics/i18n-extract","dist-tags":{"latest":"0.6.7"},"versions":{"0.6.7":{"name":"@agencyanalytics/i18n-extract","private":false,"version":"0.6.7","description":"Manage localization of ES6 code with static analysis","main":"lib/index.js","scripts":{"lint":"eslint . && echo \"eslint: no lint errors\"","test":"npm run lint && npm run test:unit","test:unit":"mocha src/{,**/}*.spec.js","test:watch":"yarn test:unit -- -w","build":"rm -rf lib && mkdir lib && babel src --out-dir lib","prettier":"find . -name \"*.js\" | grep -v -f .eslintignore | xargs prettier --write","version":"npm run build && pkgfiles"},"repository":{"type":"git","url":"git+https://github.com/oliviertassinari/i18n-extract.git"},"keywords":["i18n","localization","translation","ES6","static analysis"],"homepage":"https://github.com/oliviertassinari/i18n-extract","author":{"name":"Olivier Tassinari","email":"olivier.tassinari@gmail.com","url":"https://github.com/oliviertassinari"},"license":"MIT","dependencies":{"@babel/core":"^7.4.0","@babel/plugin-proposal-class-properties":"^7.4.0","@babel/plugin-proposal-decorators":"^7.4.0","@babel/plugin-syntax-dynamic-import":"^7.2.0","@babel/register":"^7.4.0","@babel/traverse":"^7.4.0","gettext-parser":"^3.1.1","glob":"^7.1.3"},"devDependencies":{"@babel/cli":"^7.2.3","@babel/preset-env":"^7.4.2","@babel/preset-react":"^7.0.0","@babel/preset-stage-1":"^7.0.0","babel-eslint":"^10.0.1","chai":"^4.2.0","eslint":"^5.15.3","eslint-config-airbnb":"^17.1.0","eslint-plugin-babel":"^5.3.0","eslint-plugin-import":"^2.16.0","eslint-plugin-jsx-a11y":"^6.2.1","eslint-plugin-mocha":"^5.3.0","eslint-plugin-prettier":"^3.0.1","eslint-plugin-react":"^7.12.4","mocha":"^6.0.2","pkgfiles":"^2.3.2","prettier":"^1.16.4"},"bugs":{"url":"https://github.com/oliviertassinari/i18n-extract/issues"},"gitHead":"91fe51d2b63b456a770753b0b6e92f6cb56b9107","_id":"@agencyanalytics/i18n-extract@0.6.7","_nodeVersion":"12.18.2","_npmVersion":"6.14.5","dist":{"integrity":"sha512-zateUU6rkheW+hJvmqSWFpq958FFCjS/CaMbV46ek5YVZUZUcZd4/xpx9bmvSkJlD6cwvoKF3QFMaDjBAL3DxA==","shasum":"a935589b569673ceabbb88ae534998e3ce993e37","tarball":"https://registry.npmjs.org/@agencyanalytics/i18n-extract/-/i18n-extract-0.6.7.tgz","fileCount":69,"unpackedSize":80702,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhwuv1CRA9TVsSAnZWagAA/JgP/itJ068eA3l+wBOdQ8fS\nr2a9Pfzg6uU0HB4PSHCswT7Lu4Usind+SgoYfiCOugn6EN9wNqObSDfMrOol\noJ0r8JGv5ju6IkSi7X/W4PSURDbbhIvihkdUmssTGeTRAXAIoUsztW9fNCRK\nKVPehmky7zCExh00VfpAlQF4lT+wjEFQeZZSnnCgS1TjV60Yfh1zbmQSj5Uf\nIK8ImIEJ1jifXjBdPqUeKKDyyKFgDoGtX1B7kAleKTLjgHWOqLHT88AHk7BA\nAW75lC5DC2pZyzhcclVcu7ZZjeOcKnebmcALGb9fOjgqVW4owR1KIKEcne9N\n5ogbhgY2ylnO2eXEbuqrHFzykhhFBDmrCLm9adAsDOHn4KmZa38xtZTPX+zp\nkyp34SbX2DLMDMU4Mrbi/joQhg9KXxL1L1RtPs8mKzMobFzkKsguXOUPy0YI\nLN2DuRUcxXddLcPcbEuxgSOrP0Bz/WlqP3phTu3ELb1IKUhQK4DW7zJb+/7/\n/6feMpbO32il7lk/T/ZYjuyaktfdP0uGhZWkB6zXFzNEtjDUVJ6xmT4Q1xCy\nHzG4BtqS7xDVk3PAhiG+Z2f3oOvzMMRu4InnggGAhBW9bLiQKpvstrFNyS6j\nEX7PAKh3PUwkGnxyxWzAIDzy0TIKC1NTz4QYoButS/HWdBmMYdXHtbCJ+Hsi\nAB9l\r\n=iTfv\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID9mZSRuAPqjwhgZKRhgx6lCuqO0+EbXyGZQ1qvT39vgAiEAo3eIJV/PUudvVW4ueW1bH77EAcRRZMcJou0PEahA5Xk="}]},"_npmUser":{"name":"xuzrus","email":"jeremy.fmcc@gmail.com"},"directories":{},"maintainers":[{"name":"jm-agencyanalytics","email":"jeremy.mcconnell@agencyanalytics.com"},{"name":"xuzrus","email":"jeremy.fmcc@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/i18n-extract_0.6.7_1632245418631_0.5704393390596987"},"_hasShrinkwrap":false}},"time":{"created":"2021-09-21T17:30:18.553Z","0.6.7":"2021-09-21T17:30:18.772Z","modified":"2022-04-04T11:55:23.863Z"},"maintainers":[{"name":"jm-agencyanalytics","email":"jeremy.mcconnell@agencyanalytics.com"},{"name":"xuzrus","email":"jeremy.fmcc@gmail.com"}],"description":"Manage localization of ES6 code with static analysis","homepage":"https://github.com/oliviertassinari/i18n-extract","keywords":["i18n","localization","translation","ES6","static analysis"],"repository":{"type":"git","url":"git+https://github.com/oliviertassinari/i18n-extract.git"},"author":{"name":"Olivier Tassinari","email":"olivier.tassinari@gmail.com","url":"https://github.com/oliviertassinari"},"bugs":{"url":"https://github.com/oliviertassinari/i18n-extract/issues"},"license":"MIT","readme":"# i18n-extract\r\n\r\n> Manage localization with static analysis.\r\n\r\n[![npm version](https://img.shields.io/npm/v/i18n-extract.svg?style=flat-square)](https://www.npmjs.com/package/i18n-extract)\r\n[![npm downloads](https://img.shields.io/npm/dm/i18n-extract.svg?style=flat-square)](https://www.npmjs.com/package/i18n-extract)\r\n[![Build Status](https://travis-ci.org/oliviertassinari/i18n-extract.svg?branch=master)](https://travis-ci.org/oliviertassinari/i18n-extract)\r\n\r\n[![Dependencies](https://img.shields.io/david/oliviertassinari/i18n-extract.svg?style=flat-square)](https://david-dm.org/oliviertassinari/i18n-extract)\r\n[![DevDependencies](https://img.shields.io/david/dev/oliviertassinari/i18n-extract.svg?style=flat-square)](https://david-dm.org/oliviertassinari/i18n-extract#info=devDependencies&view=list)\r\n\r\n## Installation\r\n\r\n```sh\r\nnpm install --save-dev i18n-extract\r\n```\r\n\r\n## The problem solved\r\n\r\nThis module analyses code statically for key usages, such as `i18n.t('some.key')`, in order to:\r\n\r\n- Report keys that are missing\r\n- Report keys that are unused.\r\n- Report keys that are highly duplicated.\r\n\r\nE.g. This module works well in conjunction with:\r\n- [polyglot.js](https://github.com/airbnb/polyglot.js) (`marker: 'polyglot.t',`)\r\n- webpack and his localisation plugin: [i18n-webpack-plugin](https://github.com/webpack/i18n-webpack-plugin) (`marker: 'i18n',`)\r\n\r\n\r\n## Supported keys\r\n\r\n- static:\r\n```js\r\ni18n('key.static')\r\n```\r\n- string concatenation:\r\n```js\r\ni18n('key.' + 'concat')\r\n```\r\n- template string:\r\n```js\r\ni18n(`key.template`)\r\n```\r\n- dynamic:\r\n```js\r\ni18n(`key.${dynamic}`)\r\n```\r\n- comment:\r\n```js\r\n/* i18n-extract key.comment */\r\n```\r\n\r\n## API\r\n\r\n### extractFromCode(code, [options])\r\n\r\nParse the `code` to extract the argument of calls of i18n(`key`).\r\n\r\n- `code` should be a string.\r\n- Return an array containing keys used.\r\n\r\n##### Example\r\n\r\n```js\r\nimport {extractFromCode} from 'i18n-extract';\r\nconst keys = extractFromCode(\"const followMe = i18n('b2b.follow');\", {\r\n  marker: 'i18n',\r\n});\r\n// keys = ['b2b.follow']\r\n```\r\n\r\n### extractFromFiles(files, [options])\r\n\r\nParse the `files` to extract the argument of calls of i18n(`key`).\r\n\r\n- `files` can be either an array of strings or a string. You can also use a glob.\r\n- Return an array containing keys used in the source code.\r\n\r\n##### Example\r\n\r\n```js\r\nimport {extractFromFiles} from 'i18n-extract';\r\nconst keys = extractFromFiles([\r\n  '*.jsx',\r\n  '*.js',\r\n], {\r\n  marker: 'i18n',\r\n});\r\n```\r\n\r\n### Options\r\n\r\n- `marker`: The name of the internationalized string marker function. Defaults to `i18n`.\r\n- `keyLoc`: An integer indicating the position of the key in the arguments. Defaults to `0`. Negative numbers, e.g., `-1`, indicate a position relative to the end of the argument list.\r\n- `parser`: Enum indicate the parser to use, can be `typescript` or `flow`. Defaults to `flow`.\r\n- `babelOptions`: A Babel [configuration object](https://babeljs.io/docs/en/options) to allow applying custom transformations or plugins before scanning for i18n keys. Defaults to a config with all babylon plugins enabled.\r\n\r\n### findMissing(locale, keysUsed)\r\n\r\nReport the missing keys. Those keys should probably be translated.\r\n\r\n- `locale` should be a object containing the translations.\r\n- `keysUsed` should be an array. Containes the keys used in the source code.\r\nIt can be retrieve with `extractFromFiles` our `extractFromCode`.\r\n- Return a report.\r\n\r\n##### Example\r\n\r\n```js\r\nimport {findMissing} from 'i18n-extract';\r\nconst missing = findMissing({\r\n  key1: 'key 1',\r\n}, ['key1', 'key2']);\r\n\r\n/**\r\n * missing = [{\r\n *   type: 'MISSING',\r\n *   key: 'key2',\r\n * }];\r\n */\r\n```\r\n\r\n## Plugins\r\n\r\n### findUnused(locale, keysUsed)\r\n\r\nReport the unused key. Those keys should probably be removed.\r\n\r\n- `locale` should be a object containing the translations.\r\n- `keysUsed` should be an array. Containes the keys used in the source code.\r\nIt can be retrieve with `extractFromFiles` our `extractFromCode`.\r\n- Return a report.\r\n\r\n##### Example\r\n\r\n```js\r\nimport {findUnused} from 'i18n-extract';\r\nconst unused = findUnused({\r\n  key1: 'key 1',\r\n  key2: 'key 2',\r\n}, ['key1']);\r\n\r\n/**\r\n * unused = [{\r\n *   type: 'UNUSED',\r\n *   key: 'key2',\r\n * }];\r\n */\r\n```\r\n\r\n### findDuplicated(locale, keysUsed, options)\r\n\r\nReport the duplicated key. Those keys should probably be mutualized.\r\nThe default `threshold` is 1, it will report any duplicated translations.\r\n\r\n- `locale` should be a object containing the translations.\r\n- `keysUsed` should be an array. Containes the keys used in the source code.\r\nIt can be retrieve with `extractFromFiles` our `extractFromCode`.\r\n- `options` should be an object. You can provide a `threshold` property to change the number of duplicated value before it's added to the report.\r\n- Return a report.\r\n\r\n##### Example\r\n\r\n```js\r\nimport {findDuplicated} from 'i18n-extract';\r\nconst duplicated = findDuplicated({\r\n  key1: 'Key 1',\r\n  key2: 'Key 2',\r\n  key3: 'Key 2',\r\n});\r\n\r\n/**\r\n * unused = [{\r\n *   type: 'DUPLICATED',\r\n *   keys: [\r\n *     'key2',\r\n *     'key3',\r\n *   ],\r\n *   value: 'Key 2',\r\n * }];\r\n */\r\n```\r\n\r\n### forbidDynamic(locale, keysUsed)\r\n\r\nReport any dynamic key. It's arguably more dangerous to use dynamic key. They may break.\r\n\r\n- `locale` should be a object containing the translations.\r\n- `keysUsed` should be an array. Containes the keys used in the source code.\r\nIt can be retrieve with `extractFromFiles` our `extractFromCode`.\r\n- Return a report.\r\n\r\n##### Example\r\n\r\n```js\r\nimport {forbidDynamic} from 'i18n-extract';\r\nconst forbidDynamic = forbidDynamic({}, ['key.*']);\r\n\r\n/**\r\n * forbidDynamic = [{\r\n *   type: 'FORBID_DYNAMIC',\r\n *   key: 'key.*',\r\n * }];\r\n */\r\n```\r\n\r\n### flatten(object)\r\n\r\nFlatten the object.\r\n\r\n- `object` should be a object.\r\n\r\n##### Example\r\n\r\n```js\r\nimport {flatten} from 'i18n-extract';\r\nconst flattened = flatten({\r\n  key2: 'Key 2',\r\n  key4: {\r\n    key41: 'Key 4.1',\r\n    key42: {\r\n      key421: 'Key 4.2.1',\r\n    },\r\n  },\r\n});\r\n\r\n/**\r\n * flattened = {\r\n *   key2: 'Key 2',\r\n *   'key4.key41': 'Key 4.1',\r\n *   'key4.key42.key421': 'Key 4.2.1',\r\n * };\r\n */\r\n```\r\n\r\n### mergeMessagesWithPO(messages, poInput, poOutput)\r\n\r\nOutput a new po file with only the messages present in `messages`.\r\nIf a message is already present in the `poInput`, we keep the translation.\r\nIf a message is not present, we add a new empty translation.\r\n\r\n- `messages` should be an array.\r\n- `poInput` should be a string.\r\n- `poOutput` should be a string.\r\n\r\n##### Example\r\n\r\n```js\r\nimport {mergeMessagesWithPO} from 'i18n-extract';\r\n\r\nconst messages = ['Message 1', 'Message 2'];\r\nmergeMessagesWithPO(messages, 'messages.po', 'messages.output.po');\r\n\r\n/**\r\n * Will output :\r\n * > messages.output.po has 812 messages.\r\n * > We have added 7 messages.\r\n * > We have removed 3 messages.\r\n */\r\n```\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}