@lingual/i18n-check 0.8.4 → 0.8.5

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/README.md CHANGED
@@ -4,9 +4,9 @@
4
4
  It compares the defined source language with all target translation files and finds inconsistencies between source and target files.
5
5
  You can run these checks as a pre-commit hook or on the CI depending on your use-case and setup.
6
6
 
7
- ![example 1](./assets/i18n-check-screenshot-full.png)
7
+ ![example 1](./assets/i18n_check_multipleFilesFolderExample_basic_v2.png)
8
8
 
9
- ![example 2](./assets/i18n-check-screenshot-summary.png)
9
+ ![example 2](./assets/i18n_check_multipleFilesFolderExample_react_intl_unused_v2.png)
10
10
 
11
11
  ## Table of Contents
12
12
 
@@ -106,7 +106,7 @@ Additionally the `i18next` format is supported and can be set via the `-f` or `-
106
106
 
107
107
  There are i18n libraries that have their own specific format, which might not be based on ICU and therefore can not be validated against currently. On a side-note: there might be future support for more specific formats.
108
108
 
109
- Hint: If you want to use the `--unused` flag, you should provide `react-intl` or `i18-next` as the format. Also see the [`unused` section](#--unused) for more details.
109
+ Hint: If you want to use the `--unused` flag, you should provide `react-intl` or `i18-next` as the format. Also see the [`unused` section](#--unused--u) for more details.
110
110
 
111
111
  ```bash
112
112
  yarn i18n:check --locales translations/i18NextMessageExamples -s en-US -f i18next
@@ -165,7 +165,7 @@ This feature is currently only supported for `react-intl` and `i18next` as well
165
165
 
166
166
  Via the `-u` or `--unused` option you provide a source path to the code, which will be parsed to find all unused as well as undefined keys in the primary target language.
167
167
 
168
- It is important to note that you must also provide the `-f` or `--format` option with `react-intl`, `i18next` or `next-intl` as value. See the [`format` section](#--format) for more information.
168
+ It is important to note that you must also provide the `-f` or `--format` option with `react-intl`, `i18next` or `next-intl` as value. See the [`format` section](#--format--f) for more information.
169
169
 
170
170
  ```bash
171
171
  yarn i18n:check --locales translations/messageExamples -s en-US -u client/ -f react-intl
package/dist/bin/index.js CHANGED
@@ -160,6 +160,7 @@ const main = async () => {
160
160
  }
161
161
  try {
162
162
  const result = (0, __1.checkTranslations)(srcFiles, targetFiles, options);
163
+ let undefinedKeyResult = undefined;
163
164
  printTranslationResult(result);
164
165
  if (unusedSrcPath) {
165
166
  const isMultiUnusedFolders = unusedSrcPath.length > 1;
@@ -176,11 +177,13 @@ const main = async () => {
176
177
  printUndefinedKeysResult({
177
178
  undefinedKeys,
178
179
  });
180
+ undefinedKeyResult = undefinedKeys;
179
181
  }
180
182
  const end = performance.now();
181
183
  console.log(chalk_1.default.green(`\nDone in ${Math.round(((end - start) * 100) / 1000) / 100}s.`));
182
184
  if ((result.missingKeys && Object.keys(result.missingKeys).length > 0) ||
183
- (result.invalidKeys && Object.keys(result.invalidKeys).length > 0)) {
185
+ (result.invalidKeys && Object.keys(result.invalidKeys).length > 0) ||
186
+ (undefinedKeyResult && Object.keys(undefinedKeyResult).length > 0)) {
184
187
  (0, node_process_1.exit)(1);
185
188
  }
186
189
  else {
@@ -140,6 +140,49 @@ const getKeys = (path) => {
140
140
  }
141
141
  }
142
142
  }
143
+ // Check if getTranslations is called inside a promise.all
144
+ // Example:
145
+ // const [data, t] = await Promise.all([
146
+ // loadData(id),
147
+ // getTranslations('asyncPromiseAll'),
148
+ // ]);
149
+ if (ts.isCallExpression(node.initializer.expression) &&
150
+ node.initializer.expression.arguments.length > 0 &&
151
+ ts.isArrayLiteralExpression(node.initializer.expression.arguments[0])) {
152
+ const functionNameIndex = node.initializer.expression.arguments[0].elements.findIndex((argument) => {
153
+ return (ts.isCallExpression(argument) &&
154
+ ts.isIdentifier(argument.expression) &&
155
+ argument.expression.text === GET_TRANSLATIONS);
156
+ });
157
+ // Try to find the correct function name via the position in the variable declaration
158
+ if (functionNameIndex !== -1 &&
159
+ ts.isArrayBindingPattern(node.name) &&
160
+ ts.isBindingElement(node.name.elements[functionNameIndex]) &&
161
+ ts.isIdentifier(node.name.elements[functionNameIndex].name)) {
162
+ const variable = node.name.elements[functionNameIndex].name.text;
163
+ const [argument] = ts.isCallExpression(node.initializer.expression.arguments[0].elements[functionNameIndex])
164
+ ? node.initializer.expression.arguments[0].elements[functionNameIndex].arguments
165
+ : [];
166
+ if (argument && ts.isObjectLiteralExpression(argument)) {
167
+ argument.properties.forEach((property) => {
168
+ if (property &&
169
+ ts.isPropertyAssignment(property) &&
170
+ property.name &&
171
+ ts.isIdentifier(property.name) &&
172
+ property.name.text === 'namespace' &&
173
+ ts.isStringLiteral(property.initializer)) {
174
+ pushNamespace({ name: property.initializer.text, variable });
175
+ }
176
+ });
177
+ }
178
+ else if (argument && ts.isStringLiteral(argument)) {
179
+ pushNamespace({ name: argument.text, variable });
180
+ }
181
+ else if (argument === undefined) {
182
+ pushNamespace({ name: '', variable });
183
+ }
184
+ }
185
+ }
143
186
  }
144
187
  }
145
188
  // Search for direct inline calls and extract namespace and key
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingual/i18n-check",
3
- "version": "0.8.4",
3
+ "version": "0.8.5",
4
4
  "description": "i18n translation messages check",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "types": "dist/index.d.ts",
12
12
  "scripts": {
13
- "build": "tsc",
13
+ "build": "tsc -p tsconfig.production.json",
14
14
  "format": "prettier --write .",
15
15
  "lint": "eslint src",
16
16
  "lint:fix": "eslint src --fix ",
@@ -19,31 +19,32 @@
19
19
  "test:cli": "tsc && jest src/bin/index.test.ts"
20
20
  },
21
21
  "files": [
22
- "dist/"
22
+ "dist/",
23
+ "!dist/**/*.test.*"
23
24
  ],
24
25
  "dependencies": {
25
26
  "@formatjs/cli-lib": "^6.6.6",
26
27
  "@formatjs/icu-messageformat-parser": "^2.11.2",
27
28
  "chalk": "^4.1.2",
28
29
  "commander": "^12.1.0",
29
- "glob": "^11.0.2",
30
+ "glob": "11.0.2",
30
31
  "i18next-parser": "^9.3.0",
31
32
  "js-yaml": "^4.1.0",
32
33
  "typescript": "^5.8.3"
33
34
  },
34
35
  "devDependencies": {
35
- "@eslint/js": "^9.26.0",
36
+ "@eslint/js": "^9.30.1",
36
37
  "@types/jest": "^29.5.14",
37
38
  "@types/js-yaml": "^4.0.9",
38
- "@types/node": "^22.14.1",
39
+ "@types/node": "^22.16.0",
39
40
  "@types/vinyl": "^2.0.12",
40
41
  "braces": "^3.0.3",
41
- "eslint": "^9.26.0",
42
- "globals": "^16.0.0",
42
+ "eslint": "^9.30.1",
43
+ "globals": "^16.3.0",
43
44
  "jest": "^29.7.0",
44
- "prettier": "^3.5.3",
45
- "ts-jest": "^29.3.2",
46
- "typescript-eslint": "^8.31.1"
45
+ "prettier": "^3.6.2",
46
+ "ts-jest": "^29.4.0",
47
+ "typescript-eslint": "^8.35.1"
47
48
  },
48
49
  "repository": {
49
50
  "type": "git",
@@ -1 +0,0 @@
1
- export {};