{"id":13526920,"url":"https://github.com/oliviertassinari/i18n-extract","last_synced_at":"2025-10-05T04:19:25.965Z","repository":{"id":35025158,"uuid":"39132194","full_name":"oliviertassinari/i18n-extract","owner":"oliviertassinari","description":"Manage localization with static analysis. :mag:","archived":false,"fork":false,"pushed_at":"2022-01-23T02:25:59.000Z","size":323,"stargazers_count":174,"open_issues_count":12,"forks_count":28,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-12T23:13:42.753Z","etag":null,"topics":["es6","i18n","localization","static-analysis","translation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"davidjbradshaw/iframe-resizer","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oliviertassinari.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-15T11:03:02.000Z","updated_at":"2024-07-12T15:45:38.000Z","dependencies_parsed_at":"2022-09-15T23:40:21.135Z","dependency_job_id":null,"html_url":"https://github.com/oliviertassinari/i18n-extract","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oliviertassinari%2Fi18n-extract","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oliviertassinari%2Fi18n-extract/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oliviertassinari%2Fi18n-extract/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oliviertassinari%2Fi18n-extract/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oliviertassinari","download_url":"https://codeload.github.com/oliviertassinari/i18n-extract/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247261603,"owners_count":20910108,"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":["es6","i18n","localization","static-analysis","translation"],"created_at":"2024-08-01T06:01:37.475Z","updated_at":"2025-10-05T04:19:20.922Z","avatar_url":"https://github.com/oliviertassinari.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# i18n-extract\n\n\u003e Manage localization with static analysis.\n\n[![npm version](https://img.shields.io/npm/v/i18n-extract.svg?style=flat-square)](https://www.npmjs.com/package/i18n-extract)\n[![npm downloads](https://img.shields.io/npm/dm/i18n-extract.svg?style=flat-square)](https://www.npmjs.com/package/i18n-extract)\n[![Build Status](https://travis-ci.org/oliviertassinari/i18n-extract.svg?branch=master)](https://travis-ci.org/oliviertassinari/i18n-extract)\n\n[![Dependencies](https://img.shields.io/david/oliviertassinari/i18n-extract.svg?style=flat-square)](https://david-dm.org/oliviertassinari/i18n-extract)\n[![DevDependencies](https://img.shields.io/david/dev/oliviertassinari/i18n-extract.svg?style=flat-square)](https://david-dm.org/oliviertassinari/i18n-extract#info=devDependencies\u0026view=list)\n\n## Installation\n\n```sh\nnpm install --save-dev i18n-extract\n```\n\n## The problem solved\n\nThis module analyses code statically for key usages, such as `i18n.t('some.key')`, in order to:\n\n- Report keys that are missing\n- Report keys that are unused.\n- Report keys that are highly duplicated.\n\nE.g. This module works well in conjunction with:\n- [polyglot.js](https://github.com/airbnb/polyglot.js) (`marker: 'polyglot.t',`)\n- webpack and his localisation plugin: [i18n-webpack-plugin](https://github.com/webpack/i18n-webpack-plugin) (`marker: 'i18n',`)\n\n\n## Supported keys\n\n- static:\n```js\ni18n('key.static')\n```\n- string concatenation:\n```js\ni18n('key.' + 'concat')\n```\n- template string:\n```js\ni18n(`key.template`)\n```\n- dynamic:\n```js\ni18n(`key.${dynamic}`)\n```\n- comment:\n```js\n/* i18n-extract key.comment */\n```\n\n## API\n\n### extractFromCode(code, [options])\n\nParse the `code` to extract the argument of calls of i18n(`key`).\n\n- `code` should be a string.\n- Return an array containing keys used.\n\n##### Example\n\n```js\nimport {extractFromCode} from 'i18n-extract';\nconst keys = extractFromCode(\"const followMe = i18n('b2b.follow');\", {\n  marker: 'i18n',\n});\n// keys = ['b2b.follow']\n```\n\n### extractFromFiles(files, [options])\n\nParse the `files` to extract the argument of calls of i18n(`key`).\n\n- `files` can be either an array of strings or a string. You can also use a glob.\n- Return an array containing keys used in the source code.\n\n##### Example\n\n```js\nimport {extractFromFiles} from 'i18n-extract';\nconst keys = extractFromFiles([\n  '*.jsx',\n  '*.js',\n], {\n  marker: 'i18n',\n});\n```\n\n### Options\n\n- `marker`: The name of the internationalized string marker function. Defaults to `i18n`.\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.\n- `parser`: Enum indicate the parser to use, can be `typescript` or `flow`. Defaults to `flow`.\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.\n\n### findMissing(locale, keysUsed)\n\nReport the missing keys. Those keys should probably be translated.\n\n- `locale` should be a object containing the translations.\n- `keysUsed` should be an array. Containes the keys used in the source code.\nIt can be retrieve with `extractFromFiles` our `extractFromCode`.\n- Return a report.\n\n##### Example\n\n```js\nimport {findMissing} from 'i18n-extract';\nconst missing = findMissing({\n  key1: 'key 1',\n}, ['key1', 'key2']);\n\n/**\n * missing = [{\n *   type: 'MISSING',\n *   key: 'key2',\n * }];\n */\n```\n\n## Plugins\n\n### findUnused(locale, keysUsed)\n\nReport the unused key. Those keys should probably be removed.\n\n- `locale` should be a object containing the translations.\n- `keysUsed` should be an array. Containes the keys used in the source code.\nIt can be retrieve with `extractFromFiles` our `extractFromCode`.\n- Return a report.\n\n##### Example\n\n```js\nimport {findUnused} from 'i18n-extract';\nconst unused = findUnused({\n  key1: 'key 1',\n  key2: 'key 2',\n}, ['key1']);\n\n/**\n * unused = [{\n *   type: 'UNUSED',\n *   key: 'key2',\n * }];\n */\n```\n\n### findDuplicated(locale, keysUsed, options)\n\nReport the duplicated key. Those keys should probably be mutualized.\nThe default `threshold` is 1, it will report any duplicated translations.\n\n- `locale` should be a object containing the translations.\n- `keysUsed` should be an array. Containes the keys used in the source code.\nIt can be retrieve with `extractFromFiles` our `extractFromCode`.\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.\n- Return a report.\n\n##### Example\n\n```js\nimport {findDuplicated} from 'i18n-extract';\nconst duplicated = findDuplicated({\n  key1: 'Key 1',\n  key2: 'Key 2',\n  key3: 'Key 2',\n});\n\n/**\n * unused = [{\n *   type: 'DUPLICATED',\n *   keys: [\n *     'key2',\n *     'key3',\n *   ],\n *   value: 'Key 2',\n * }];\n */\n```\n\n### forbidDynamic(locale, keysUsed)\n\nReport any dynamic key. It's arguably more dangerous to use dynamic key. They may break.\n\n- `locale` should be a object containing the translations.\n- `keysUsed` should be an array. Containes the keys used in the source code.\nIt can be retrieve with `extractFromFiles` our `extractFromCode`.\n- Return a report.\n\n##### Example\n\n```js\nimport {forbidDynamic} from 'i18n-extract';\nconst forbidDynamic = forbidDynamic({}, ['key.*']);\n\n/**\n * forbidDynamic = [{\n *   type: 'FORBID_DYNAMIC',\n *   key: 'key.*',\n * }];\n */\n```\n\n### flatten(object)\n\nFlatten the object.\n\n- `object` should be a object.\n\n##### Example\n\n```js\nimport {flatten} from 'i18n-extract';\nconst flattened = flatten({\n  key2: 'Key 2',\n  key4: {\n    key41: 'Key 4.1',\n    key42: {\n      key421: 'Key 4.2.1',\n    },\n  },\n});\n\n/**\n * flattened = {\n *   key2: 'Key 2',\n *   'key4.key41': 'Key 4.1',\n *   'key4.key42.key421': 'Key 4.2.1',\n * };\n */\n```\n\n### mergeMessagesWithPO(messages, poInput, poOutput)\n\nOutput a new po file with only the messages present in `messages`.\nIf a message is already present in the `poInput`, we keep the translation.\nIf a message is not present, we add a new empty translation.\n\n- `messages` should be an array.\n- `poInput` should be a string.\n- `poOutput` should be a string.\n\n##### Example\n\n```js\nimport {mergeMessagesWithPO} from 'i18n-extract';\n\nconst messages = ['Message 1', 'Message 2'];\nmergeMessagesWithPO(messages, 'messages.po', 'messages.output.po');\n\n/**\n * Will output :\n * \u003e messages.output.po has 812 messages.\n * \u003e We have added 7 messages.\n * \u003e We have removed 3 messages.\n */\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foliviertassinari%2Fi18n-extract","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foliviertassinari%2Fi18n-extract","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foliviertassinari%2Fi18n-extract/lists"}