@lingual/i18n-check 0.8.13 → 0.8.15

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.
Files changed (27) hide show
  1. package/dist/{src/bin → bin}/index.js +16 -3
  2. package/dist/{src/utils → utils}/findInvalidTranslations.d.ts +11 -0
  3. package/dist/{src/utils → utils}/findInvalidTranslations.js +56 -9
  4. package/package.json +2 -2
  5. package/dist/vitest.bin.config.d.ts +0 -2
  6. package/dist/vitest.bin.config.js +0 -14
  7. package/dist/vitest.config.d.ts +0 -2
  8. package/dist/vitest.config.js +0 -12
  9. /package/dist/{src/bin → bin}/index.d.ts +0 -0
  10. /package/dist/{src/errorReporters.d.ts → errorReporters.d.ts} +0 -0
  11. /package/dist/{src/errorReporters.js → errorReporters.js} +0 -0
  12. /package/dist/{src/index.d.ts → index.d.ts} +0 -0
  13. /package/dist/{src/index.js → index.js} +0 -0
  14. /package/dist/{src/types.d.ts → types.d.ts} +0 -0
  15. /package/dist/{src/types.js → types.js} +0 -0
  16. /package/dist/{src/utils → utils}/constants.d.ts +0 -0
  17. /package/dist/{src/utils → utils}/constants.js +0 -0
  18. /package/dist/{src/utils → utils}/findInvalidI18NextTranslations.d.ts +0 -0
  19. /package/dist/{src/utils → utils}/findInvalidI18NextTranslations.js +0 -0
  20. /package/dist/{src/utils → utils}/findMissingKeys.d.ts +0 -0
  21. /package/dist/{src/utils → utils}/findMissingKeys.js +0 -0
  22. /package/dist/{src/utils → utils}/flattenTranslations.d.ts +0 -0
  23. /package/dist/{src/utils → utils}/flattenTranslations.js +0 -0
  24. /package/dist/{src/utils → utils}/i18NextParser.d.ts +0 -0
  25. /package/dist/{src/utils → utils}/i18NextParser.js +0 -0
  26. /package/dist/{src/utils → utils}/nextIntlSrcParser.d.ts +0 -0
  27. /package/dist/{src/utils → utils}/nextIntlSrcParser.js +0 -0
@@ -14,6 +14,7 @@ const __1 = require("..");
14
14
  const errorReporters_1 = require("../errorReporters");
15
15
  const flattenTranslations_1 = require("../utils/flattenTranslations");
16
16
  const node_path_1 = __importDefault(require("node:path"));
17
+ const findInvalidTranslations_1 = require("../utils/findInvalidTranslations");
17
18
  const version = require('../../package.json').version;
18
19
  commander_1.program
19
20
  .version(version)
@@ -156,7 +157,7 @@ const main = async () => {
156
157
  options.checks.includes('invalidKeys')) &&
157
158
  targetFiles.length === 0) {
158
159
  // Remove missingKeys and invalidKeys from checks since they require multiple files
159
- options.checks = options.checks.filter(check => check !== 'missingKeys' && check !== 'invalidKeys');
160
+ options.checks = options.checks.filter((check) => check !== 'missingKeys' && check !== 'invalidKeys');
160
161
  console.log(chalk_1.default.yellow('\nOnly one locale file found. Skipping missingKeys and invalidKeys checks.\n'));
161
162
  }
162
163
  try {
@@ -193,10 +194,22 @@ const main = async () => {
193
194
  else {
194
195
  (0, node_process_1.exit)(0);
195
196
  }
196
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
197
197
  }
198
198
  catch (e) {
199
- console.log(chalk_1.default.red("\nError: Can't validate translations. Check if the format is supported or specify the translation format i.e. -f i18next"));
199
+ let errorMessage = "\nError: Can't validate translations. Check if the format is supported or specify the translation format i.e. -f i18next";
200
+ // Use enhanced error message if available
201
+ if (e instanceof findInvalidTranslations_1.CheckError) {
202
+ errorMessage = `\n${e.message}`;
203
+ // Check if the error has location information (from ICU parser)
204
+ if (e.location) {
205
+ errorMessage += `\nLocation: Line ${e.location.start.line}, Column ${e.location.start.column}`;
206
+ }
207
+ // Check if the error has originalMessage (from ICU parser)
208
+ if (e.originalMessage != null) {
209
+ errorMessage += `\nProblematic translation: "${e.originalMessage}"`;
210
+ }
211
+ }
212
+ console.log(chalk_1.default.red(errorMessage));
200
213
  (0, node_process_1.exit)(1);
201
214
  }
202
215
  };
@@ -1,5 +1,16 @@
1
1
  import { MessageFormatElement } from '@formatjs/icu-messageformat-parser';
2
2
  import { InvalidTranslationEntry, InvalidTranslationsResult, Translation } from '../types';
3
+ type Location = {
4
+ start: {
5
+ line: number;
6
+ column: number;
7
+ };
8
+ };
9
+ export declare class CheckError extends Error {
10
+ location?: Location;
11
+ originalMessage?: string;
12
+ }
3
13
  export declare const findInvalidTranslations: (source: Translation, files: Record<string, Translation>) => InvalidTranslationsResult;
4
14
  export declare const compareTranslationFiles: (a: Translation, b: Translation) => InvalidTranslationEntry[];
5
15
  export declare const hasDiff: (a: MessageFormatElement[], b: MessageFormatElement[]) => boolean;
16
+ export {};
@@ -1,16 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasDiff = exports.compareTranslationFiles = exports.findInvalidTranslations = void 0;
3
+ exports.hasDiff = exports.compareTranslationFiles = exports.findInvalidTranslations = exports.CheckError = void 0;
4
4
  const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
5
+ class CheckError extends Error {
6
+ }
7
+ exports.CheckError = CheckError;
8
+ function isLocation(value) {
9
+ return (typeof value === 'object' &&
10
+ value != null &&
11
+ 'start' in value &&
12
+ typeof value.start === 'object' &&
13
+ value.start != null &&
14
+ 'line' in value.start &&
15
+ typeof value.start.line === 'number' &&
16
+ 'column' in value.start &&
17
+ typeof value.start.column === 'number');
18
+ }
5
19
  const findInvalidTranslations = (source, files) => {
6
20
  const differences = {};
7
21
  if (Object.keys(files).length === 0) {
8
22
  return differences;
9
23
  }
10
24
  for (const [lang, file] of Object.entries(files)) {
11
- const result = (0, exports.compareTranslationFiles)(source, file);
12
- if (result.length > 0) {
13
- differences[lang] = result;
25
+ try {
26
+ const result = (0, exports.compareTranslationFiles)(source, file);
27
+ if (result.length > 0) {
28
+ differences[lang] = result;
29
+ }
30
+ }
31
+ catch (error) {
32
+ // Re-throw with file context
33
+ const enhancedError = new CheckError(`Error in translation file "${lang}": ${error instanceof Error ? error.message : String(error)}`);
34
+ if (error instanceof Error) {
35
+ if ('location' in error && isLocation(error.location)) {
36
+ enhancedError.location = error.location;
37
+ }
38
+ if ('originalMessage' in error &&
39
+ typeof error.originalMessage === 'string') {
40
+ enhancedError.originalMessage = error.originalMessage;
41
+ }
42
+ }
43
+ throw enhancedError;
14
44
  }
15
45
  }
16
46
  return differences;
@@ -32,11 +62,28 @@ const compareTranslationFiles = (a, b) => {
32
62
  if (b[key] === undefined) {
33
63
  continue;
34
64
  }
35
- const parsedTranslationA = (0, icu_messageformat_parser_1.parse)(String(a[key]));
36
- const parsedTranslationB = (0, icu_messageformat_parser_1.parse)(String(b[key]));
37
- if ((0, exports.hasDiff)(parsedTranslationA, parsedTranslationB)) {
38
- const msg = getErrorMessage(parsedTranslationA, parsedTranslationB);
39
- diffs.push({ key, msg });
65
+ try {
66
+ const parsedTranslationA = (0, icu_messageformat_parser_1.parse)(String(a[key]));
67
+ const parsedTranslationB = (0, icu_messageformat_parser_1.parse)(String(b[key]));
68
+ if ((0, exports.hasDiff)(parsedTranslationA, parsedTranslationB)) {
69
+ const msg = getErrorMessage(parsedTranslationA, parsedTranslationB);
70
+ diffs.push({ key, msg });
71
+ }
72
+ }
73
+ catch (error) {
74
+ // Re-throw with key context and preserve location/originalMessage
75
+ const errorMessage = error instanceof Error ? error.message : String(error);
76
+ const enhancedError = new CheckError(`Failed to parse translation key "${key}": ${errorMessage === 'INVALID_TAG' ? 'Invalid ICU message format tags found in translation content' : errorMessage}`);
77
+ if (error instanceof Error) {
78
+ if ('location' in error && isLocation(error.location)) {
79
+ enhancedError.location = error.location;
80
+ }
81
+ if ('originalMessage' in error &&
82
+ typeof error.originalMessage === 'string') {
83
+ enhancedError.originalMessage = error.originalMessage;
84
+ }
85
+ }
86
+ throw enhancedError;
40
87
  }
41
88
  }
42
89
  return diffs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingual/i18n-check",
3
- "version": "0.8.13",
3
+ "version": "0.8.15",
4
4
  "description": "i18n translation messages check",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -16,7 +16,7 @@
16
16
  "lint:fix": "eslint src --fix ",
17
17
  "check-format": "prettier --check './{src,translations}/**/*.{js,jsx,ts,tsx,json,html,css}'",
18
18
  "test": "vitest run",
19
- "test:cli": "tsc && vitest --config vitest.bin.config.ts run src/bin/index.test.ts"
19
+ "test:cli": "pnpm build && vitest --config vitest.bin.config.ts run src/bin/index.test.ts"
20
20
  },
21
21
  "files": [
22
22
  "dist/",
@@ -1,2 +0,0 @@
1
- declare const _default: import("vite", { with: { "resolution-mode": "import" } }).UserConfig;
2
- export default _default;
@@ -1,14 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- // vitest.config.ts
7
- const config_1 = require("vitest/config");
8
- const vitest_config_1 = __importDefault(require("./vitest.config"));
9
- exports.default = (0, config_1.defineConfig)({
10
- ...vitest_config_1.default,
11
- test: {
12
- exclude: ['node_modules', 'dist'],
13
- },
14
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("vite", { with: { "resolution-mode": "import" } }).UserConfig;
2
- export default _default;
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- // vitest.config.ts
4
- const config_1 = require("vitest/config");
5
- exports.default = (0, config_1.defineConfig)({
6
- test: {
7
- globals: true, // (optional) use Jest-like globals like `describe`, `test`, etc.
8
- environment: 'node', // 'node' or 'jsdom' depending on your project
9
- // setupFiles: ['./vitest.setup.ts'], // optional setup file
10
- exclude: ['src/bin', 'node_modules', 'dist'], // exclude specific test paths
11
- },
12
- });
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes