@lingual/i18n-check 0.8.1 → 0.8.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/README.md +10 -18
- package/dist/bin/index.js +73 -99
- package/dist/bin/index.test.js +560 -472
- package/dist/errorReporters.d.ts +5 -7
- package/dist/errorReporters.js +67 -81
- package/dist/errorReporters.test.d.ts +1 -0
- package/dist/errorReporters.test.js +165 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.js +78 -54
- package/dist/types.d.ts +5 -0
- package/dist/utils/findInvalidTranslations.d.ts +4 -7
- package/dist/utils/findInvalidTranslations.js +23 -22
- package/dist/utils/findInvalidTranslations.test.js +30 -30
- package/dist/utils/findInvalidi18nTranslations.d.ts +4 -4
- package/dist/utils/findInvalidi18nTranslations.js +36 -36
- package/dist/utils/findInvalidi18nTranslations.test.js +72 -72
- package/dist/utils/findMissingKeys.d.ts +2 -2
- package/dist/utils/findMissingKeys.js +3 -3
- package/dist/utils/findMissingKeys.test.js +20 -20
- package/dist/utils/flattenTranslations.d.ts +1 -1
- package/dist/utils/flattenTranslations.js +4 -4
- package/dist/utils/flattenTranslations.test.js +13 -13
- package/dist/utils/i18NextParser.d.ts +6 -6
- package/dist/utils/i18NextParser.js +29 -29
- package/dist/utils/i18NextParser.test.js +104 -104
- package/dist/utils/nextIntlSrcParser.js +11 -11
- package/dist/utils/nextIntlSrcParser.test.js +206 -206
- package/package.json +14 -4
package/dist/errorReporters.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CheckResult, InvalidTranslationsResult } from './types';
|
|
1
2
|
export type StandardReporter = {
|
|
2
3
|
file: string;
|
|
3
4
|
key: string;
|
|
@@ -6,10 +7,7 @@ export type StandardReporter = {
|
|
|
6
7
|
export declare const CheckOptions: string[];
|
|
7
8
|
export type Context = (typeof CheckOptions)[number];
|
|
8
9
|
export declare const contextMapping: Record<Context, string>;
|
|
9
|
-
export declare
|
|
10
|
-
export declare
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}[]) => string;
|
|
14
|
-
export declare const createTable: (input: unknown[]) => string;
|
|
15
|
-
export declare const createVerticalTable: (input: unknown[]) => string;
|
|
10
|
+
export declare function formatSummaryTable<T>(result: Record<string, T[]>): string;
|
|
11
|
+
export declare function formatTable(rowGroups: string[][][], lineSep?: string): string;
|
|
12
|
+
export declare function formatCheckResultTable(result: CheckResult): string;
|
|
13
|
+
export declare function formatInvalidTranslationsResultTable(result: InvalidTranslationsResult): string;
|
package/dist/errorReporters.js
CHANGED
|
@@ -1,92 +1,78 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
exports.contextMapping = exports.CheckOptions = void 0;
|
|
4
|
+
exports.formatSummaryTable = formatSummaryTable;
|
|
5
|
+
exports.formatTable = formatTable;
|
|
6
|
+
exports.formatCheckResultTable = formatCheckResultTable;
|
|
7
|
+
exports.formatInvalidTranslationsResultTable = formatInvalidTranslationsResultTable;
|
|
6
8
|
exports.CheckOptions = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
'invalidKeys',
|
|
10
|
+
'missingKeys',
|
|
11
|
+
'unused',
|
|
12
|
+
'undefined',
|
|
11
13
|
];
|
|
12
14
|
exports.contextMapping = {
|
|
13
|
-
invalidKeys:
|
|
14
|
-
missingKeys:
|
|
15
|
-
unused:
|
|
16
|
-
undefined:
|
|
15
|
+
invalidKeys: 'invalid',
|
|
16
|
+
missingKeys: 'missing',
|
|
17
|
+
unused: 'unused',
|
|
18
|
+
undefined: 'undefined',
|
|
17
19
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}, []);
|
|
26
|
-
return (0, exports.createVerticalTable)(data);
|
|
20
|
+
function formatSummaryTable(result) {
|
|
21
|
+
return formatTable(getSummaryRows(result));
|
|
22
|
+
}
|
|
23
|
+
const getSummaryRows = (checkResult) => {
|
|
24
|
+
const rows = [];
|
|
25
|
+
for (const [file, keys] of Object.entries(checkResult)) {
|
|
26
|
+
rows.push([truncate(file), String(keys.length)]);
|
|
27
27
|
}
|
|
28
|
-
return
|
|
28
|
+
return [[['file', 'total']], rows];
|
|
29
29
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
cb(null, chunk);
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
const logger = new console_1.Console({ stdout: ts });
|
|
43
|
-
logger.table(input);
|
|
44
|
-
const table = (ts.read() || "").toString();
|
|
45
|
-
// https://stackoverflow.com/a/69874540
|
|
46
|
-
let output = "";
|
|
47
|
-
const lines = table.split(/[\r\n]+/);
|
|
48
|
-
for (let line of lines) {
|
|
49
|
-
output += `${line
|
|
50
|
-
.replace(/[^┬]*┬/, "┌")
|
|
51
|
-
.replace(/^├─*┼/, "├")
|
|
52
|
-
.replace(/│[^│]*/, "")
|
|
53
|
-
.replace(/^└─*┴/, "└")
|
|
54
|
-
.replace(/'/g, " ")}\n`;
|
|
55
|
-
}
|
|
56
|
-
return output.replace(/\n\n$/, "");
|
|
57
|
-
};
|
|
58
|
-
exports.createTable = createTable;
|
|
59
|
-
const createVerticalTable = (input) => {
|
|
60
|
-
// https://stackoverflow.com/a/67859384
|
|
61
|
-
const ts = new stream_1.Transform({
|
|
62
|
-
transform(chunk, enc, cb) {
|
|
63
|
-
cb(null, chunk);
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
const logger = new console_1.Console({ stdout: ts });
|
|
67
|
-
logger.table(input);
|
|
68
|
-
const table = (ts.read() || "").toString();
|
|
69
|
-
// https://stackoverflow.com/a/69874540
|
|
70
|
-
let output = "";
|
|
71
|
-
let firstLine = "";
|
|
72
|
-
let index = 0;
|
|
73
|
-
const lines = table.split(/[\r\n]+/);
|
|
74
|
-
for (let line of lines) {
|
|
75
|
-
const transformedLine = `${line
|
|
76
|
-
.replace(/[^┬]*┬/, "┌")
|
|
77
|
-
.replace(/^├─*┼/, "├")
|
|
78
|
-
.replace(/│[^│]*/, "")
|
|
79
|
-
.replace(/^└─*┴/, "└")
|
|
80
|
-
.replace(/'/g, " ")}\n`;
|
|
81
|
-
output += transformedLine;
|
|
82
|
-
if (index === 2) {
|
|
83
|
-
firstLine = transformedLine;
|
|
30
|
+
function formatTable(rowGroups, lineSep = '\n') {
|
|
31
|
+
// +2 for whitespace padding left and right
|
|
32
|
+
const padding = 2;
|
|
33
|
+
const colWidths = [];
|
|
34
|
+
for (const rows of rowGroups) {
|
|
35
|
+
for (const row of rows) {
|
|
36
|
+
for (let index = 0; index < row.length; ++index) {
|
|
37
|
+
colWidths[index] = Math.max(colWidths[index] ?? 0, row[index].length + padding);
|
|
38
|
+
}
|
|
84
39
|
}
|
|
85
|
-
|
|
86
|
-
|
|
40
|
+
}
|
|
41
|
+
const lines = [];
|
|
42
|
+
lines.push(formatSeparatorRow(colWidths, '┌┬┐'));
|
|
43
|
+
for (const rows of rowGroups) {
|
|
44
|
+
for (const row of rows) {
|
|
45
|
+
lines.push(formatRow(row, colWidths));
|
|
87
46
|
}
|
|
88
|
-
|
|
47
|
+
lines.push(formatSeparatorRow(colWidths, '├┼┤'));
|
|
89
48
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
49
|
+
lines[lines.length - 1] = formatSeparatorRow(colWidths, '└┴┘');
|
|
50
|
+
return lines.join(lineSep);
|
|
51
|
+
}
|
|
52
|
+
function formatSeparatorRow(widths, [left, middle, right]) {
|
|
53
|
+
return (left + widths.map((width) => ''.padEnd(width, '─')).join(middle) + right);
|
|
54
|
+
}
|
|
55
|
+
function formatRow(values, widths) {
|
|
56
|
+
return (`│` +
|
|
57
|
+
values
|
|
58
|
+
.map((val, index) => ` ${val} `.padEnd(widths[index], ' '))
|
|
59
|
+
.join('│') +
|
|
60
|
+
`│`);
|
|
61
|
+
}
|
|
62
|
+
const truncate = (chars, len = 80) => chars.length > 80 ? `${chars.substring(0, len)}...` : chars;
|
|
63
|
+
function formatCheckResultTable(result) {
|
|
64
|
+
return formatTable([
|
|
65
|
+
[['file', 'key']],
|
|
66
|
+
Object.entries(result).flatMap(([file, keys]) => keys.map((key) => [truncate(file), truncate(key)])),
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
function formatInvalidTranslationsResultTable(result) {
|
|
70
|
+
return formatTable([
|
|
71
|
+
[['info', 'result']],
|
|
72
|
+
...Object.entries(result).flatMap(([file, errors]) => errors.map(({ key, msg }) => [
|
|
73
|
+
['file', truncate(file)],
|
|
74
|
+
['key', truncate(key)],
|
|
75
|
+
['msg', truncate(msg, 120)],
|
|
76
|
+
])),
|
|
77
|
+
]);
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const errorReporters_1 = require("./errorReporters");
|
|
4
|
+
describe('formatTable', () => {
|
|
5
|
+
test('single col and row', () => {
|
|
6
|
+
expect((0, errorReporters_1.formatTable)([[['lorem ipsum']]])).toEqual(`
|
|
7
|
+
┌─────────────┐
|
|
8
|
+
│ lorem ipsum │
|
|
9
|
+
└─────────────┘
|
|
10
|
+
`.trim());
|
|
11
|
+
});
|
|
12
|
+
test('single col and two rows', () => {
|
|
13
|
+
expect((0, errorReporters_1.formatTable)([[['lorem ipsum'], ['foo bar']]])).toEqual(`
|
|
14
|
+
┌─────────────┐
|
|
15
|
+
│ lorem ipsum │
|
|
16
|
+
│ foo bar │
|
|
17
|
+
└─────────────┘
|
|
18
|
+
`.trim());
|
|
19
|
+
});
|
|
20
|
+
test('with two columns and two row groups', () => {
|
|
21
|
+
expect((0, errorReporters_1.formatTable)([
|
|
22
|
+
[['col1', 'col2']],
|
|
23
|
+
[
|
|
24
|
+
['lorem ipsum dolor', 'foobar'],
|
|
25
|
+
['baz', 'more text'],
|
|
26
|
+
],
|
|
27
|
+
])).toEqual(`
|
|
28
|
+
┌───────────────────┬───────────┐
|
|
29
|
+
│ col1 │ col2 │
|
|
30
|
+
├───────────────────┼───────────┤
|
|
31
|
+
│ lorem ipsum dolor │ foobar │
|
|
32
|
+
│ baz │ more text │
|
|
33
|
+
└───────────────────┴───────────┘
|
|
34
|
+
`.trim());
|
|
35
|
+
});
|
|
36
|
+
test('with two columns and three row groups', () => {
|
|
37
|
+
expect((0, errorReporters_1.formatTable)([
|
|
38
|
+
[['one', 'two']],
|
|
39
|
+
[
|
|
40
|
+
['lorem ipsum dolor', 'foobar'],
|
|
41
|
+
['baz', 'more text'],
|
|
42
|
+
],
|
|
43
|
+
[['hello world', 'here is more text for testing']],
|
|
44
|
+
])).toEqual(`
|
|
45
|
+
┌───────────────────┬───────────────────────────────┐
|
|
46
|
+
│ one │ two │
|
|
47
|
+
├───────────────────┼───────────────────────────────┤
|
|
48
|
+
│ lorem ipsum dolor │ foobar │
|
|
49
|
+
│ baz │ more text │
|
|
50
|
+
├───────────────────┼───────────────────────────────┤
|
|
51
|
+
│ hello world │ here is more text for testing │
|
|
52
|
+
└───────────────────┴───────────────────────────────┘
|
|
53
|
+
`.trim());
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('formatCheckResultTable', () => {
|
|
57
|
+
test('with one file and two keys', () => {
|
|
58
|
+
expect((0, errorReporters_1.formatCheckResultTable)({
|
|
59
|
+
'some/file.json': ['key.one', 'key.two'],
|
|
60
|
+
})).toEqual(`
|
|
61
|
+
┌────────────────┬─────────┐
|
|
62
|
+
│ file │ key │
|
|
63
|
+
├────────────────┼─────────┤
|
|
64
|
+
│ some/file.json │ key.one │
|
|
65
|
+
│ some/file.json │ key.two │
|
|
66
|
+
└────────────────┴─────────┘
|
|
67
|
+
`.trim());
|
|
68
|
+
});
|
|
69
|
+
test('with two files and three keys', () => {
|
|
70
|
+
expect((0, errorReporters_1.formatCheckResultTable)({
|
|
71
|
+
'some/de.json': ['key.one', 'key.two'],
|
|
72
|
+
'some/en.json': ['key.three'],
|
|
73
|
+
})).toEqual(`
|
|
74
|
+
┌──────────────┬───────────┐
|
|
75
|
+
│ file │ key │
|
|
76
|
+
├──────────────┼───────────┤
|
|
77
|
+
│ some/de.json │ key.one │
|
|
78
|
+
│ some/de.json │ key.two │
|
|
79
|
+
│ some/en.json │ key.three │
|
|
80
|
+
└──────────────┴───────────┘
|
|
81
|
+
`.trim());
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('formatInvalidTranslationsResultTable', () => {
|
|
85
|
+
test('with one file and one key', () => {
|
|
86
|
+
expect((0, errorReporters_1.formatInvalidTranslationsResultTable)({
|
|
87
|
+
'some/en.json': [{ key: 'key.one', msg: 'key one error msg' }],
|
|
88
|
+
})).toEqual(`
|
|
89
|
+
┌──────┬───────────────────┐
|
|
90
|
+
│ info │ result │
|
|
91
|
+
├──────┼───────────────────┤
|
|
92
|
+
│ file │ some/en.json │
|
|
93
|
+
│ key │ key.one │
|
|
94
|
+
│ msg │ key one error msg │
|
|
95
|
+
└──────┴───────────────────┘
|
|
96
|
+
`.trim());
|
|
97
|
+
});
|
|
98
|
+
test('with two files and three keys', () => {
|
|
99
|
+
expect((0, errorReporters_1.formatInvalidTranslationsResultTable)({
|
|
100
|
+
'some/en-US.json': [
|
|
101
|
+
{ key: 'key.one', msg: 'key one error msg' },
|
|
102
|
+
{ key: 'key.two', msg: 'another msg' },
|
|
103
|
+
],
|
|
104
|
+
'some/de.json': [{ key: 'key.three', msg: 'key three msg' }],
|
|
105
|
+
})).toEqual(`
|
|
106
|
+
┌──────┬───────────────────┐
|
|
107
|
+
│ info │ result │
|
|
108
|
+
├──────┼───────────────────┤
|
|
109
|
+
│ file │ some/en-US.json │
|
|
110
|
+
│ key │ key.one │
|
|
111
|
+
│ msg │ key one error msg │
|
|
112
|
+
├──────┼───────────────────┤
|
|
113
|
+
│ file │ some/en-US.json │
|
|
114
|
+
│ key │ key.two │
|
|
115
|
+
│ msg │ another msg │
|
|
116
|
+
├──────┼───────────────────┤
|
|
117
|
+
│ file │ some/de.json │
|
|
118
|
+
│ key │ key.three │
|
|
119
|
+
│ msg │ key three msg │
|
|
120
|
+
└──────┴───────────────────┘
|
|
121
|
+
`.trim());
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
describe('formatSummaryTable', () => {
|
|
125
|
+
test('with CheckResult with single file and key', () => {
|
|
126
|
+
expect((0, errorReporters_1.formatSummaryTable)({
|
|
127
|
+
'some/file.json': ['key.one'],
|
|
128
|
+
})).toEqual(`
|
|
129
|
+
┌────────────────┬───────┐
|
|
130
|
+
│ file │ total │
|
|
131
|
+
├────────────────┼───────┤
|
|
132
|
+
│ some/file.json │ 1 │
|
|
133
|
+
└────────────────┴───────┘
|
|
134
|
+
`.trim());
|
|
135
|
+
});
|
|
136
|
+
test('with CheckResult with two files and three keys', () => {
|
|
137
|
+
expect((0, errorReporters_1.formatSummaryTable)({
|
|
138
|
+
'some/de.json': ['key.one', 'key.two'],
|
|
139
|
+
'some/en.json': ['key.three'],
|
|
140
|
+
})).toEqual(`
|
|
141
|
+
┌──────────────┬───────┐
|
|
142
|
+
│ file │ total │
|
|
143
|
+
├──────────────┼───────┤
|
|
144
|
+
│ some/de.json │ 2 │
|
|
145
|
+
│ some/en.json │ 1 │
|
|
146
|
+
└──────────────┴───────┘
|
|
147
|
+
`.trim());
|
|
148
|
+
});
|
|
149
|
+
test('with InvalidTranslationsResult with two files and three keys', () => {
|
|
150
|
+
expect((0, errorReporters_1.formatSummaryTable)({
|
|
151
|
+
'some/en-US.json': [
|
|
152
|
+
{ key: 'key.one', msg: 'key one error msg' },
|
|
153
|
+
{ key: 'key.two', msg: 'another msg' },
|
|
154
|
+
],
|
|
155
|
+
'some/de.json': [{ key: 'key.three', msg: 'key three msg' }],
|
|
156
|
+
})).toEqual(`
|
|
157
|
+
┌─────────────────┬───────┐
|
|
158
|
+
│ file │ total │
|
|
159
|
+
├─────────────────┼───────┤
|
|
160
|
+
│ some/en-US.json │ 2 │
|
|
161
|
+
│ some/de.json │ 1 │
|
|
162
|
+
└─────────────────┴───────┘
|
|
163
|
+
`.trim());
|
|
164
|
+
});
|
|
165
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { CheckResult, Translation, TranslationFile } from
|
|
2
|
-
import { Context } from
|
|
1
|
+
import { CheckResult, InvalidTranslationsResult, Translation, TranslationFile } from './types';
|
|
2
|
+
import { Context } from './errorReporters';
|
|
3
3
|
export type Options = {
|
|
4
|
-
format?:
|
|
4
|
+
format?: 'icu' | 'i18next' | 'react-intl' | 'next-intl';
|
|
5
5
|
checks?: Context[];
|
|
6
6
|
};
|
|
7
|
-
export declare const checkInvalidTranslations: (source: Translation, targets: Record<string, Translation>, options?: Options) =>
|
|
7
|
+
export declare const checkInvalidTranslations: (source: Translation, targets: Record<string, Translation>, options?: Options) => InvalidTranslationsResult;
|
|
8
8
|
export declare const checkMissingTranslations: (source: Translation, targets: Record<string, Translation>) => CheckResult;
|
|
9
9
|
export declare const checkTranslations: (source: TranslationFile[], targets: TranslationFile[], options?: Options) => {
|
|
10
10
|
missingKeys: CheckResult | undefined;
|
|
11
|
-
invalidKeys:
|
|
11
|
+
invalidKeys: InvalidTranslationsResult | undefined;
|
|
12
12
|
};
|
|
13
|
-
export declare const checkUnusedKeys: (translationFiles: TranslationFile[], filesToParse: string[], options?: Options, componentFunctions?:
|
|
14
|
-
export declare const checkUndefinedKeys: (source: TranslationFile[], filesToParse: string[], options?: Options, componentFunctions?:
|
|
13
|
+
export declare const checkUnusedKeys: (translationFiles: TranslationFile[], filesToParse: string[], options?: Options, componentFunctions?: string[]) => Promise<CheckResult | undefined>;
|
|
14
|
+
export declare const checkUndefinedKeys: (source: TranslationFile[], filesToParse: string[], options?: Options, componentFunctions?: string[]) => Promise<CheckResult | undefined>;
|