@lingual/i18n-check 0.9.2 → 0.9.4
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 +28 -0
- package/dist/bin/index.js +5 -2
- package/dist/index.js +48 -40
- package/dist/types.d.ts +1 -0
- package/dist/utils/i18NextParser.js +1 -3
- package/dist/utils/i18NextSrcParser.js +43 -0
- package/dist/utils/nextIntlSrcParser.d.ts +2 -1
- package/dist/utils/nextIntlSrcParser.js +82 -3
- package/package.json +13 -14
package/README.md
CHANGED
|
@@ -259,6 +259,34 @@ yarn i18n:check --locales translations/i18NextMessageExamples -s en-US -f i18nex
|
|
|
259
259
|
-u src --parser-component-functions WrappedTransComponent AnotherWrappedTransComponent
|
|
260
260
|
```
|
|
261
261
|
|
|
262
|
+
### --next-intl-translation-fn-type-alias
|
|
263
|
+
|
|
264
|
+
To find any indirect function calls inside a `next-intl` codebase, the parser will try to find the type `ReturnType<typeof useTranslations>` in the function call arguments.
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
const indirectFnCall = (
|
|
268
|
+
t: ReturnType<typeof useTranslations<'SomeNameSpace'>>
|
|
269
|
+
) => {
|
|
270
|
+
const indirectTranslation = t('someKey');
|
|
271
|
+
// Do something with the indirectTranslation
|
|
272
|
+
};
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
When a type alias is used instead of `ReturnType<typeof useTranslations>`, the `--next-intl-translation-fn-type-alias` option can be used to tell the parser the name of the type or types.
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
import { NextIntlTranslateFnAlias } from './types';
|
|
279
|
+
|
|
280
|
+
const indirectFnCall = (t: NextIntlTranslateFnAlias<'SomeNameSpace'>) => {
|
|
281
|
+
const indirectTranslation = t('someKey');
|
|
282
|
+
// Do something with the indirectTranslation
|
|
283
|
+
};
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
yarn i18n:check --source en --locales translations/codeExamples/next-intl/locales/ -f next-intl -u translations/codeExamples/next-intl/src --next-intl-translation-fn-type-alias NextIntlTranslateFnAlias
|
|
288
|
+
```
|
|
289
|
+
|
|
262
290
|
## Examples
|
|
263
291
|
|
|
264
292
|
i18n-check is able to load and validate against different locale folder structures. Depending on how the locale files are organized, there are different configuration options.
|
package/dist/bin/index.js
CHANGED
|
@@ -9,7 +9,7 @@ const node_process_1 = require("node:process");
|
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
10
|
const commander_1 = require("commander");
|
|
11
11
|
const glob_1 = require("glob");
|
|
12
|
-
const
|
|
12
|
+
const yaml_1 = require("yaml");
|
|
13
13
|
const __1 = require("..");
|
|
14
14
|
const errorReporters_1 = require("../errorReporters");
|
|
15
15
|
const flattenTranslations_1 = require("../utils/flattenTranslations");
|
|
@@ -28,6 +28,7 @@ commander_1.program
|
|
|
28
28
|
.option('-i, --ignore <ignore...>', 'define the key(s) or group of keys (i.e. `some.namespace.*`) that should be excluded from the check')
|
|
29
29
|
.option('-u, --unused <paths...>', 'define the source path(s) to find all unused and undefined keys')
|
|
30
30
|
.option('--parser-component-functions <components...>', 'a list of component names to parse when using the --unused option')
|
|
31
|
+
.option('--next-intl-translation-fn-type-alias <nextIntlTranslationFnTypeAliases...>', 'next-intl translation function type aliases')
|
|
31
32
|
.parse();
|
|
32
33
|
const getCheckOptions = () => {
|
|
33
34
|
const checkOption = commander_1.program.getOptionValue('only') || commander_1.program.getOptionValue('check');
|
|
@@ -52,6 +53,7 @@ const main = async () => {
|
|
|
52
53
|
const ignore = commander_1.program.getOptionValue('ignore');
|
|
53
54
|
const unusedSrcPath = commander_1.program.getOptionValue('unused');
|
|
54
55
|
const componentFunctions = commander_1.program.getOptionValue('parserComponentFunctions');
|
|
56
|
+
const nextIntlTranslationFnTypeAlias = commander_1.program.getOptionValue('nextIntlTranslationFnTypeAlias');
|
|
55
57
|
if (!srcPath) {
|
|
56
58
|
console.log(chalk_1.default.red('Source not found. Please provide a valid source locale, i.e. -s en-US'));
|
|
57
59
|
(0, node_process_1.exit)(1);
|
|
@@ -81,6 +83,7 @@ const main = async () => {
|
|
|
81
83
|
checks: getCheckOptions(),
|
|
82
84
|
format: format ?? undefined,
|
|
83
85
|
ignore,
|
|
86
|
+
nextIntlTranslationFnTypeAlias,
|
|
84
87
|
};
|
|
85
88
|
const fileInfos = [];
|
|
86
89
|
files.sort().forEach((file) => {
|
|
@@ -97,7 +100,7 @@ const main = async () => {
|
|
|
97
100
|
fileInfos.forEach(({ extension, file, name, path }) => {
|
|
98
101
|
let rawContent;
|
|
99
102
|
if (extension === 'yaml') {
|
|
100
|
-
rawContent =
|
|
103
|
+
rawContent = (0, yaml_1.parse)(node_fs_1.default.readFileSync(file, 'utf-8'));
|
|
101
104
|
}
|
|
102
105
|
else {
|
|
103
106
|
rawContent = JSON.parse(node_fs_1.default.readFileSync(file, 'utf-8'));
|
package/dist/index.js
CHANGED
|
@@ -7,13 +7,13 @@ exports.checkUndefinedKeys = exports.checkUnusedKeys = exports.checkTranslations
|
|
|
7
7
|
const findMissingKeys_1 = require("./utils/findMissingKeys");
|
|
8
8
|
const findInvalidTranslations_1 = require("./utils/findInvalidTranslations");
|
|
9
9
|
const findInvalidI18NextTranslations_1 = require("./utils/findInvalidI18NextTranslations");
|
|
10
|
-
const cli_lib_1 = require("@formatjs/cli-lib");
|
|
11
10
|
const i18NextSrcParser_1 = require("./utils/i18NextSrcParser");
|
|
12
11
|
const nextIntlSrcParser_1 = require("./utils/nextIntlSrcParser");
|
|
13
12
|
const fs_1 = __importDefault(require("fs"));
|
|
14
13
|
const path_1 = __importDefault(require("path"));
|
|
15
14
|
const constants_1 = require("./utils/constants");
|
|
16
15
|
const ParseFormats = ['react-intl', 'i18next', 'next-intl'];
|
|
16
|
+
const CONTEXT_SEPARATOR = '_';
|
|
17
17
|
const checkInvalidTranslations = (source, targets, options = { format: 'icu' }) => {
|
|
18
18
|
return options.format === 'i18next'
|
|
19
19
|
? (0, findInvalidI18NextTranslations_1.findInvalidI18NextTranslations)(source, targets)
|
|
@@ -74,25 +74,28 @@ const checkUnusedKeys = async (translationFiles, filesToParse, options = {
|
|
|
74
74
|
return findUnusedI18NextTranslations(filteredTranslationFiles, filesToParse, componentFunctions);
|
|
75
75
|
}
|
|
76
76
|
else if (options.format === 'next-intl') {
|
|
77
|
-
return findUnusedNextIntlTranslations(filteredTranslationFiles, filesToParse);
|
|
77
|
+
return findUnusedNextIntlTranslations(filteredTranslationFiles, filesToParse, options);
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
80
|
exports.checkUnusedKeys = checkUnusedKeys;
|
|
81
81
|
const findUnusedReactIntlTranslations = async (translationFiles, filesToParse) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
return (async () => {
|
|
83
|
+
const { extract } = await import('@formatjs/cli-lib');
|
|
84
|
+
const unusedKeys = {};
|
|
85
|
+
const extracted = await extract(filesToParse, {});
|
|
86
|
+
const extractedResultSet = new Set(Object.keys(JSON.parse(extracted)));
|
|
87
|
+
translationFiles.forEach(({ name, content }) => {
|
|
88
|
+
const keysInSource = Object.keys(content);
|
|
89
|
+
const found = [];
|
|
90
|
+
for (const keyInSource of keysInSource) {
|
|
91
|
+
if (!extractedResultSet.has(keyInSource)) {
|
|
92
|
+
found.push(keyInSource);
|
|
93
|
+
}
|
|
91
94
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
unusedKeys[name] = found;
|
|
96
|
+
});
|
|
97
|
+
return unusedKeys;
|
|
98
|
+
})();
|
|
96
99
|
};
|
|
97
100
|
const findUnusedI18NextTranslations = async (source, filesToParse, componentFunctions = []) => {
|
|
98
101
|
const unusedKeys = {};
|
|
@@ -127,9 +130,9 @@ const findUnusedI18NextTranslations = async (source, filesToParse, componentFunc
|
|
|
127
130
|
});
|
|
128
131
|
return unusedKeys;
|
|
129
132
|
};
|
|
130
|
-
const findUnusedNextIntlTranslations = async (translationFiles, filesToParse) => {
|
|
133
|
+
const findUnusedNextIntlTranslations = async (translationFiles, filesToParse, options) => {
|
|
131
134
|
const unusedKeys = {};
|
|
132
|
-
const extracted = (0, nextIntlSrcParser_1.extract)(filesToParse);
|
|
135
|
+
const extracted = (0, nextIntlSrcParser_1.extract)(filesToParse, options);
|
|
133
136
|
const dynamicNamespaces = extracted.flatMap((namespace) => {
|
|
134
137
|
if (namespace.meta.dynamic) {
|
|
135
138
|
return [namespace.key];
|
|
@@ -189,27 +192,30 @@ exports.checkUndefinedKeys = checkUndefinedKeys;
|
|
|
189
192
|
const findUndefinedReactIntlKeys = async (translationFiles, filesToParse, options = {
|
|
190
193
|
ignore: [],
|
|
191
194
|
}) => {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (!(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
195
|
+
return (async () => {
|
|
196
|
+
const { extract } = await import('@formatjs/cli-lib');
|
|
197
|
+
const sourceKeys = new Set(translationFiles.flatMap(({ content }) => {
|
|
198
|
+
return Object.keys(content);
|
|
199
|
+
}));
|
|
200
|
+
const undefinedKeys = {};
|
|
201
|
+
const extractedResult = await extract(filesToParse, {
|
|
202
|
+
extractSourceLocation: true,
|
|
203
|
+
});
|
|
204
|
+
Object.entries(JSON.parse(extractedResult)).forEach(([key, meta]) => {
|
|
205
|
+
if (!sourceKeys.has(key) && !isIgnoredKey(options.ignore ?? [], key)) {
|
|
206
|
+
const data = meta;
|
|
207
|
+
if (!('file' in data) || typeof data.file !== 'string') {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const file = path_1.default.normalize(data.file);
|
|
211
|
+
if (!undefinedKeys[file]) {
|
|
212
|
+
undefinedKeys[file] = [];
|
|
213
|
+
}
|
|
214
|
+
undefinedKeys[file].push(key);
|
|
208
215
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
});
|
|
212
|
-
return undefinedKeys;
|
|
216
|
+
});
|
|
217
|
+
return undefinedKeys;
|
|
218
|
+
})();
|
|
213
219
|
};
|
|
214
220
|
const findUndefinedI18NextKeys = async (source, filesToParse, options = {
|
|
215
221
|
ignore: [],
|
|
@@ -219,7 +225,7 @@ const findUndefinedI18NextKeys = async (source, filesToParse, options = {
|
|
|
219
225
|
.flatMap(({ content }) => {
|
|
220
226
|
return Object.keys(content);
|
|
221
227
|
})
|
|
222
|
-
// Ensure that any plural
|
|
228
|
+
// Ensure that any plural definitions like key_one, key_other etc.
|
|
223
229
|
// are flatted into a single key
|
|
224
230
|
.map((key) => {
|
|
225
231
|
const pluralSuffix = constants_1.I18NEXT_PLURAL_SUFFIX.find((suffix) => {
|
|
@@ -249,7 +255,7 @@ const findUndefinedNextIntlKeys = async (translationFiles, filesToParse, options
|
|
|
249
255
|
const sourceKeys = new Set(translationFiles.flatMap(({ content }) => {
|
|
250
256
|
return Object.keys(content);
|
|
251
257
|
}));
|
|
252
|
-
const extractedResult = (0, nextIntlSrcParser_1.extract)(filesToParse);
|
|
258
|
+
const extractedResult = (0, nextIntlSrcParser_1.extract)(filesToParse, options);
|
|
253
259
|
const undefinedKeys = {};
|
|
254
260
|
extractedResult.forEach(({ key, meta }) => {
|
|
255
261
|
if (!meta.dynamic &&
|
|
@@ -302,7 +308,9 @@ const getI18NextKeysInCode = async (filesToParse, componentFunctions = []) => {
|
|
|
302
308
|
else {
|
|
303
309
|
extractedResult.push({
|
|
304
310
|
file,
|
|
305
|
-
key: entry.
|
|
311
|
+
key: entry.context
|
|
312
|
+
? `${entry.key}${CONTEXT_SEPARATOR}${entry.context}`
|
|
313
|
+
: entry.key,
|
|
306
314
|
namespace: entry.namespace,
|
|
307
315
|
});
|
|
308
316
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -10,9 +10,7 @@ const OPEN_PARENTHESIS = '(';
|
|
|
10
10
|
const OPEN_TAG = '<';
|
|
11
11
|
const CLOSE_TAG = '</';
|
|
12
12
|
const parse = (input) => {
|
|
13
|
-
|
|
14
|
-
ast = parseInput([input]);
|
|
15
|
-
return ast;
|
|
13
|
+
return parseInput([input]);
|
|
16
14
|
};
|
|
17
15
|
exports.parse = parse;
|
|
18
16
|
const parseInput = (input) => {
|
|
@@ -347,6 +347,49 @@ const extractFromExpression = (node, options) => {
|
|
|
347
347
|
}
|
|
348
348
|
entries[0].key = concatenatedString;
|
|
349
349
|
}
|
|
350
|
+
else if (ts.isFunctionExpression(keyArgument) ||
|
|
351
|
+
ts.isFunctionDeclaration(keyArgument) ||
|
|
352
|
+
ts.isArrowFunction(keyArgument)) {
|
|
353
|
+
// Try to find selector api definitions: ($) => $.a.b.c
|
|
354
|
+
if (!keyArgument.body) {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
// Check if the function contains a return statement
|
|
358
|
+
if (ts.isBlock(keyArgument.body)) {
|
|
359
|
+
const returnStatement = keyArgument.body.statements.find((statement) => ts.isReturnStatement(statement));
|
|
360
|
+
if (returnStatement &&
|
|
361
|
+
returnStatement.expression &&
|
|
362
|
+
ts.isPropertyAccessExpression(returnStatement.expression)) {
|
|
363
|
+
const [_, ...keys] = returnStatement.expression
|
|
364
|
+
.getFullText()
|
|
365
|
+
.split('.');
|
|
366
|
+
entries[0].key = keys.join('.');
|
|
367
|
+
}
|
|
368
|
+
// check if the access is defined as an array.
|
|
369
|
+
// $["a.b.c"]
|
|
370
|
+
else if (returnStatement &&
|
|
371
|
+
returnStatement.expression &&
|
|
372
|
+
ts.isElementAccessExpression(returnStatement.expression)) {
|
|
373
|
+
entries[0].key = returnStatement.expression.argumentExpression
|
|
374
|
+
.getFullText()
|
|
375
|
+
.replace(/['"]/g, '');
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
// check if the access is defined as an array.
|
|
381
|
+
// $["a.b.c"]
|
|
382
|
+
}
|
|
383
|
+
else if (ts.isElementAccessExpression(keyArgument.body)) {
|
|
384
|
+
entries[0].key = keyArgument.body.argumentExpression
|
|
385
|
+
.getFullText()
|
|
386
|
+
.replace(/['"]/g, '');
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
const [_, ...keys] = keyArgument.body.getFullText().split('.');
|
|
390
|
+
entries[0].key = keys.join('.');
|
|
391
|
+
}
|
|
392
|
+
}
|
|
350
393
|
else {
|
|
351
394
|
return null;
|
|
352
395
|
}
|
|
@@ -42,13 +42,15 @@ const ts = __importStar(require("typescript"));
|
|
|
42
42
|
const USE_TRANSLATIONS = 'useTranslations';
|
|
43
43
|
const GET_TRANSLATIONS = 'getTranslations';
|
|
44
44
|
const COMMENT_CONTAINS_STATIC_KEY_REGEX = /i18n-check t\((["'])(.*?[^\\])(["'])\)/;
|
|
45
|
-
const extract = (filesPaths) => {
|
|
46
|
-
return filesPaths
|
|
45
|
+
const extract = (filesPaths, options = {}) => {
|
|
46
|
+
return filesPaths
|
|
47
|
+
.flatMap((path) => getKeys(path, options))
|
|
48
|
+
.sort((a, b) => {
|
|
47
49
|
return a.key > b.key ? 1 : -1;
|
|
48
50
|
});
|
|
49
51
|
};
|
|
50
52
|
exports.extract = extract;
|
|
51
|
-
const getKeys = (path) => {
|
|
53
|
+
const getKeys = (path, options) => {
|
|
52
54
|
const content = node_fs_1.default.readFileSync(path, 'utf-8');
|
|
53
55
|
const sourceFile = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
|
|
54
56
|
const foundKeys = [];
|
|
@@ -328,6 +330,83 @@ const getKeys = (path) => {
|
|
|
328
330
|
}
|
|
329
331
|
}
|
|
330
332
|
}
|
|
333
|
+
// Third scenaro is if t function the type is
|
|
334
|
+
// an alias for ReturnType<typeof useTranslations>
|
|
335
|
+
const tFunctionAliasParam = node.parameters &&
|
|
336
|
+
node.parameters.find((param) => param.type &&
|
|
337
|
+
ts.isTypeReferenceNode(param.type) &&
|
|
338
|
+
param.type.typeName &&
|
|
339
|
+
ts.isIdentifier(param.type.typeName) &&
|
|
340
|
+
options &&
|
|
341
|
+
options.nextIntlTranslationFnTypeAlias !== undefined &&
|
|
342
|
+
options?.nextIntlTranslationFnTypeAlias.includes(param.type.typeName.text));
|
|
343
|
+
if (tFunctionAliasParam !== undefined &&
|
|
344
|
+
tFunctionAliasParam.type &&
|
|
345
|
+
ts.isTypeReferenceNode(tFunctionAliasParam.type)) {
|
|
346
|
+
const [namespaceArgument] = tFunctionAliasParam.type.typeArguments &&
|
|
347
|
+
tFunctionAliasParam.type.typeArguments.length > 0
|
|
348
|
+
? tFunctionAliasParam.type.typeArguments
|
|
349
|
+
: [];
|
|
350
|
+
if (ts.isIdentifier(tFunctionAliasParam.name)) {
|
|
351
|
+
const name = namespaceArgument &&
|
|
352
|
+
ts.isLiteralTypeNode(namespaceArgument) &&
|
|
353
|
+
ts.isStringLiteral(namespaceArgument.literal)
|
|
354
|
+
? namespaceArgument.literal.text
|
|
355
|
+
: '';
|
|
356
|
+
pushNamespace({
|
|
357
|
+
name,
|
|
358
|
+
variable: tFunctionAliasParam.name.text,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// Fourth scenario is the t function is defined as an object property and uses an alias:
|
|
363
|
+
// someFn({t}: {t: AliasForTheOriginalNextIntlType}>
|
|
364
|
+
const tFunctionParamAliasAsProperty = node.parameters &&
|
|
365
|
+
node.parameters.find((param) => param.type &&
|
|
366
|
+
ts.isTypeLiteralNode(param.type) &&
|
|
367
|
+
param.type.members.find((member) => {
|
|
368
|
+
return (ts.isPropertySignature(member) &&
|
|
369
|
+
member.type &&
|
|
370
|
+
ts.isTypeReferenceNode(member.type) &&
|
|
371
|
+
member.type.typeName &&
|
|
372
|
+
ts.isIdentifier(member.type.typeName) &&
|
|
373
|
+
options &&
|
|
374
|
+
options.nextIntlTranslationFnTypeAlias !== undefined &&
|
|
375
|
+
options?.nextIntlTranslationFnTypeAlias.includes(member.type.typeName.text));
|
|
376
|
+
}));
|
|
377
|
+
if (tFunctionParamAliasAsProperty !== undefined &&
|
|
378
|
+
tFunctionParamAliasAsProperty.type &&
|
|
379
|
+
ts.isTypeLiteralNode(tFunctionParamAliasAsProperty.type)) {
|
|
380
|
+
const fnType = tFunctionParamAliasAsProperty.type.members.find((member) => {
|
|
381
|
+
return (ts.isPropertySignature(member) &&
|
|
382
|
+
member.type &&
|
|
383
|
+
ts.isTypeReferenceNode(member.type) &&
|
|
384
|
+
member.type.typeName &&
|
|
385
|
+
ts.isIdentifier(member.type.typeName) &&
|
|
386
|
+
options &&
|
|
387
|
+
options.nextIntlTranslationFnTypeAlias !== undefined &&
|
|
388
|
+
options?.nextIntlTranslationFnTypeAlias.includes(member.type.typeName.text));
|
|
389
|
+
});
|
|
390
|
+
if (fnType &&
|
|
391
|
+
ts.isPropertySignature(fnType) &&
|
|
392
|
+
fnType.type &&
|
|
393
|
+
ts.isTypeReferenceNode(fnType.type)) {
|
|
394
|
+
const [namespaceArgument] = fnType.type.typeArguments && fnType.type.typeArguments.length > 0
|
|
395
|
+
? fnType.type.typeArguments
|
|
396
|
+
: [];
|
|
397
|
+
if (fnType.name && ts.isIdentifier(fnType.name)) {
|
|
398
|
+
const name = namespaceArgument &&
|
|
399
|
+
ts.isLiteralTypeNode(namespaceArgument) &&
|
|
400
|
+
ts.isStringLiteral(namespaceArgument.literal)
|
|
401
|
+
? namespaceArgument.literal.text
|
|
402
|
+
: '';
|
|
403
|
+
pushNamespace({
|
|
404
|
+
name,
|
|
405
|
+
variable: fnType.name.text,
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
331
410
|
}
|
|
332
411
|
// Search for `t()` calls
|
|
333
412
|
if (getCurrentNamespaces() !== null &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lingual/i18n-check",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "i18n translation messages check",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,24 +24,23 @@
|
|
|
24
24
|
"!dist/**/*.test.*"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@formatjs/cli-lib": "^8.
|
|
27
|
+
"@formatjs/cli-lib": "^8.5.1",
|
|
28
28
|
"@formatjs/icu-messageformat-parser": "^2.11.4",
|
|
29
29
|
"chalk": "^4.1.2",
|
|
30
30
|
"commander": "^12.1.0",
|
|
31
|
-
"glob": "
|
|
32
|
-
"
|
|
33
|
-
"
|
|
31
|
+
"glob": "^13.0.6",
|
|
32
|
+
"typescript": "^5.9.3",
|
|
33
|
+
"yaml": "^2.8.3"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@eslint/js": "^
|
|
37
|
-
"@types/
|
|
38
|
-
"@types/node": "^22.19.1",
|
|
36
|
+
"@eslint/js": "^10.0.1",
|
|
37
|
+
"@types/node": "^22.19.17",
|
|
39
38
|
"braces": "^3.0.3",
|
|
40
|
-
"eslint": "^
|
|
41
|
-
"globals": "^
|
|
42
|
-
"prettier": "^3.
|
|
43
|
-
"typescript-eslint": "^8.
|
|
44
|
-
"vitest": "^4.
|
|
39
|
+
"eslint": "^10.2.1",
|
|
40
|
+
"globals": "^17.5.0",
|
|
41
|
+
"prettier": "^3.8.3",
|
|
42
|
+
"typescript-eslint": "^8.59.0",
|
|
43
|
+
"vitest": "^4.1.5"
|
|
45
44
|
},
|
|
46
45
|
"repository": {
|
|
47
46
|
"type": "git",
|
|
@@ -50,5 +49,5 @@
|
|
|
50
49
|
"engines": {
|
|
51
50
|
"node": ">=20"
|
|
52
51
|
},
|
|
53
|
-
"packageManager": "pnpm@10.
|
|
52
|
+
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264"
|
|
54
53
|
}
|