@lingual/i18n-check 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/index.js CHANGED
@@ -214,7 +214,7 @@ const printTranslationResult = ({ missingKeys, invalidKeys, }) => {
214
214
  const printUnusedKeysResult = ({ unusedKeys, }) => {
215
215
  const reporter = commander_1.program.getOptionValue("reporter");
216
216
  const isSummary = reporter === "summary";
217
- if (unusedKeys && Object.keys(unusedKeys).length > 0) {
217
+ if (unusedKeys && hasUnusedKeys(unusedKeys)) {
218
218
  console.log(chalk_1.default.red("\nFound unused keys!"));
219
219
  if (isSummary) {
220
220
  console.log(chalk_1.default.red((0, errorReporters_1.summaryReporter)(getSummaryRows(unusedKeys))));
@@ -224,7 +224,7 @@ const printUnusedKeysResult = ({ unusedKeys, }) => {
224
224
  }
225
225
  }
226
226
  else if (unusedKeys) {
227
- console.log(chalk_1.default.green("\nNo unused found!"));
227
+ console.log(chalk_1.default.green("\nNo unused keys found!"));
228
228
  }
229
229
  };
230
230
  const truncate = (chars) => chars.length > 80 ? `${chars.substring(0, 80)}...` : chars;
@@ -250,4 +250,12 @@ const getStandardRows = (checkResult) => {
250
250
  }
251
251
  return formattedRows;
252
252
  };
253
+ const hasUnusedKeys = (checkResult) => {
254
+ for (const [_, keys] of Object.entries(checkResult)) {
255
+ if (keys.length > 0) {
256
+ return true;
257
+ }
258
+ }
259
+ return false;
260
+ };
253
261
  main();
package/dist/index.js CHANGED
@@ -19,7 +19,6 @@ const findInvalidi18nTranslations_1 = require("./utils/findInvalidi18nTranslatio
19
19
  const glob_1 = require("glob");
20
20
  const cli_lib_1 = require("@formatjs/cli-lib");
21
21
  const fs_1 = __importDefault(require("fs"));
22
- const vinyl_1 = __importDefault(require("vinyl"));
23
22
  const checkInvalidTranslations = (source, targets, options = { format: "icu" }) => {
24
23
  return options.format === "i18next"
25
24
  ? (0, findInvalidi18nTranslations_1.findInvalid18nTranslations)(source, targets)
@@ -95,37 +94,53 @@ const findUnusedI18NextTranslations = (source_1, codebaseSrc_1, ...args_1) => __
95
94
  let extractedResult = [];
96
95
  // @ts-ignore
97
96
  const { transform } = yield import("i18next-parser");
97
+ const i18nextParser = new transform({
98
+ lexers: {
99
+ jsx: [
100
+ {
101
+ lexer: "JsxLexer",
102
+ componentFunctions: componentFunctions.concat(["Trans"]),
103
+ },
104
+ ],
105
+ tsx: [
106
+ {
107
+ lexer: "JsxLexer",
108
+ componentFunctions: componentFunctions.concat(["Trans"]),
109
+ },
110
+ ],
111
+ },
112
+ });
113
+ // Skip any parsed keys that have the `returnObjects` property set to true
114
+ // As these are used dynamically, they will be skipped to prevent
115
+ // these keys from being marked as unused.
116
+ const skippableKeys = [];
98
117
  unusedKeysFiles.forEach((file) => {
99
- const rawContent = fs_1.default.readFileSync(file);
100
- const i18nextParser = new transform({
101
- lexers: {
102
- jsx: [
103
- {
104
- lexer: "JsxLexer",
105
- componentFunctions: componentFunctions.concat(["Trans"]),
106
- },
107
- ],
108
- tsx: [
109
- {
110
- lexer: "JsxLexer",
111
- componentFunctions: componentFunctions.concat(["Trans"]),
112
- },
113
- ],
114
- },
115
- });
116
- i18nextParser.once("data", (file) => {
117
- extractedResult = extractedResult.concat(Object.keys(flatten(JSON.parse(file.contents))));
118
- });
119
- i18nextParser.end(new vinyl_1.default({
120
- contents: rawContent,
121
- path: file,
122
- }));
118
+ const rawContent = fs_1.default.readFileSync(file, "utf-8");
119
+ const entries = i18nextParser.parser.parse(rawContent, file);
120
+ // Intermediate solution to retrieve all keys from the parser.
121
+ // This will be built out to also include the namespace and check
122
+ // the key against the namespace corresponding file.
123
+ // The current implementation considers the key as used no matter the namespace.
124
+ for (const entry of entries) {
125
+ if (entry.returnObjects) {
126
+ skippableKeys.push(entry.key);
127
+ }
128
+ else {
129
+ extractedResult.push(entry.key);
130
+ }
131
+ }
123
132
  });
124
133
  const extractedResultSet = new Set(extractedResult);
125
134
  source.forEach(({ name, content }) => {
126
135
  const keysInSource = Object.keys(content);
127
136
  const found = [];
128
137
  for (const keyInSource of keysInSource) {
138
+ const isSkippable = skippableKeys.find((skippableKey) => {
139
+ return keyInSource.includes(skippableKey);
140
+ });
141
+ if (isSkippable !== undefined) {
142
+ continue;
143
+ }
129
144
  if (!extractedResultSet.has(keyInSource)) {
130
145
  found.push(keyInSource);
131
146
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingual/i18n-check",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "i18n translation messages check",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -18,19 +18,18 @@
18
18
  "dist/"
19
19
  ],
20
20
  "dependencies": {
21
- "@formatjs/cli-lib": "^6.4.2",
22
- "@formatjs/icu-messageformat-parser": "^2.9.7",
21
+ "@formatjs/cli-lib": "^6.6.6",
22
+ "@formatjs/icu-messageformat-parser": "^2.11.0",
23
23
  "chalk": "^4.1.2",
24
24
  "commander": "^12.1.0",
25
- "glob": "^11.0.0",
26
- "i18next-parser": "^9.0.2",
27
- "js-yaml": "^4.1.0",
28
- "vinyl": "^3.0.0"
25
+ "glob": "^11.0.1",
26
+ "i18next-parser": "^9.1.0",
27
+ "js-yaml": "^4.1.0"
29
28
  },
30
29
  "devDependencies": {
31
30
  "@types/jest": "^29.5.14",
32
31
  "@types/js-yaml": "^4.0.9",
33
- "@types/node": "^22.10.1",
32
+ "@types/node": "^22.10.10",
34
33
  "@types/vinyl": "^2.0.12",
35
34
  "braces": "^3.0.3",
36
35
  "jest": "^29.7.0",