@lingual/i18n-check 0.8.0 → 0.8.2

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.
@@ -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 const standardReporter: (result: StandardReporter[], flatten?: boolean) => string;
10
- export declare const summaryReporter: (result: {
11
- file: string;
12
- total: number;
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;
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createVerticalTable = exports.createTable = exports.summaryReporter = exports.standardReporter = exports.contextMapping = exports.CheckOptions = void 0;
4
- const console_1 = require("console");
5
- const stream_1 = require("stream");
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
9
  "invalidKeys",
8
10
  "missingKeys",
@@ -15,78 +17,62 @@ exports.contextMapping = {
15
17
  unused: "unused",
16
18
  undefined: "undefined",
17
19
  };
18
- const standardReporter = (result, flatten = false) => {
19
- if (flatten) {
20
- const data = result.reduce((acc, row) => {
21
- Object.entries(row).forEach(([info, result]) => {
22
- acc.push({ info, result });
23
- });
24
- return acc;
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 (0, exports.createTable)(result);
28
+ return [[["file", "total"]], rows];
29
29
  };
30
- exports.standardReporter = standardReporter;
31
- const summaryReporter = (result) => {
32
- return (0, exports.createTable)(result.map(({ file, total }) => ({ file, total })));
33
- };
34
- exports.summaryReporter = summaryReporter;
35
- const createTable = (input) => {
36
- // https://stackoverflow.com/a/67859384
37
- const ts = new stream_1.Transform({
38
- transform(chunk, enc, cb) {
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
- if (index > 3 && (index + 1) % 3 === 0 && index !== lines.length - 3) {
86
- output += firstLine;
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
- index++;
47
+ lines.push(formatSeparatorRow(colWidths, "├┼┤"));
89
48
  }
90
- return output.replace(/\n\n$/, "");
91
- };
92
- exports.createVerticalTable = createVerticalTable;
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 "./types";
1
+ import { CheckResult, InvalidTranslationsResult, Translation, TranslationFile } from "./types";
2
2
  import { Context } from "./errorReporters";
3
3
  export type Options = {
4
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) => CheckResult;
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: CheckResult | undefined;
11
+ invalidKeys: InvalidTranslationsResult | undefined;
12
12
  };
13
- export declare const checkUnusedKeys: (translationFiles: TranslationFile[], filesToParse: string[], options?: Options, componentFunctions?: never[]) => Promise<CheckResult | undefined>;
14
- export declare const checkUndefinedKeys: (source: TranslationFile[], filesToParse: string[], options?: Options, componentFunctions?: never[]) => Promise<CheckResult | undefined>;
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>;
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ const findInvalidi18nTranslations_1 = require("./utils/findInvalidi18nTranslatio
10
10
  const cli_lib_1 = require("@formatjs/cli-lib");
11
11
  const nextIntlSrcParser_1 = require("./utils/nextIntlSrcParser");
12
12
  const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
13
14
  const ParseFormats = ["react-intl", "i18next", "next-intl"];
14
15
  const checkInvalidTranslations = (source, targets, options = { format: "icu" }) => {
15
16
  return options.format === "i18next"
@@ -28,16 +29,14 @@ const checkTranslations = (source, targets, options = { format: "icu", checks: [
28
29
  const hasMissingKeys = checks.includes("missingKeys");
29
30
  const hasInvalidKeys = checks.includes("invalidKeys");
30
31
  source.forEach(({ name, content }) => {
31
- const files = targets
32
+ const files = Object.fromEntries(targets
32
33
  .filter(({ reference }) => reference === name)
33
- .reduce((obj, { name: key, content }) => {
34
- return Object.assign(obj, { [key]: content });
35
- }, {});
34
+ .map(({ name, content }) => [name, content]));
36
35
  if (hasMissingKeys) {
37
- Object.assign(missingKeys, (0, exports.checkMissingTranslations)(content, files));
36
+ merge(missingKeys, (0, exports.checkMissingTranslations)(content, files));
38
37
  }
39
38
  if (hasInvalidKeys) {
40
- Object.assign(invalidKeys, (0, exports.checkInvalidTranslations)(content, files, options));
39
+ merge(invalidKeys, (0, exports.checkInvalidTranslations)(content, files, options));
41
40
  }
42
41
  });
43
42
  return {
@@ -46,6 +45,11 @@ const checkTranslations = (source, targets, options = { format: "icu", checks: [
46
45
  };
47
46
  };
48
47
  exports.checkTranslations = checkTranslations;
48
+ function merge(left, right) {
49
+ for (let [k, v] of Object.entries(right)) {
50
+ left[k] = (left?.[k] ?? []).concat(v);
51
+ }
52
+ }
49
53
  const checkUnusedKeys = async (translationFiles, filesToParse, options = {
50
54
  format: "react-intl",
51
55
  checks: [],
@@ -68,7 +72,7 @@ const checkUnusedKeys = async (translationFiles, filesToParse, options = {
68
72
  };
69
73
  exports.checkUnusedKeys = checkUnusedKeys;
70
74
  const findUnusedReactIntlTranslations = async (translationFiles, filesToParse) => {
71
- let unusedKeys = {};
75
+ const unusedKeys = {};
72
76
  const extracted = await (0, cli_lib_1.extract)(filesToParse, {});
73
77
  const extractedResultSet = new Set(Object.keys(JSON.parse(extracted)));
74
78
  translationFiles.forEach(({ name, content }) => {
@@ -79,12 +83,12 @@ const findUnusedReactIntlTranslations = async (translationFiles, filesToParse) =
79
83
  found.push(keyInSource);
80
84
  }
81
85
  }
82
- Object.assign(unusedKeys, { [name]: found });
86
+ unusedKeys[name] = found;
83
87
  });
84
88
  return unusedKeys;
85
89
  };
86
90
  const findUnusedI18NextTranslations = async (source, filesToParse, componentFunctions = []) => {
87
- let unusedKeys = {};
91
+ const unusedKeys = {};
88
92
  const { extractedResult, skippableKeys } = await getI18NextKeysInCode(filesToParse, componentFunctions);
89
93
  const extractedResultSet = new Set(extractedResult.map(({ key }) => key));
90
94
  source.forEach(({ name, content }) => {
@@ -101,12 +105,12 @@ const findUnusedI18NextTranslations = async (source, filesToParse, componentFunc
101
105
  found.push(keyInSource);
102
106
  }
103
107
  }
104
- Object.assign(unusedKeys, { [name]: found });
108
+ unusedKeys[name] = found;
105
109
  });
106
110
  return unusedKeys;
107
111
  };
108
112
  const findUnusedNextIntlTranslations = async (translationFiles, filesToParse) => {
109
- let unusedKeys = {};
113
+ const unusedKeys = {};
110
114
  const extracted = (0, nextIntlSrcParser_1.extract)(filesToParse);
111
115
  const dynamicNamespaces = extracted.flatMap((namespace) => {
112
116
  if (namespace.meta.dynamic) {
@@ -139,7 +143,7 @@ const findUnusedNextIntlTranslations = async (translationFiles, filesToParse) =>
139
143
  found.push(keyInSource);
140
144
  }
141
145
  }
142
- Object.assign(unusedKeys, { [name]: found });
146
+ unusedKeys[name] = found;
143
147
  });
144
148
  return unusedKeys;
145
149
  };
@@ -174,8 +178,11 @@ const findUndefinedReactIntlKeys = async (translationFiles, filesToParse) => {
174
178
  let undefinedKeys = {};
175
179
  Object.entries(JSON.parse(extractedResult)).forEach(([key, meta]) => {
176
180
  if (!sourceKeys.has(key)) {
177
- // @ts-ignore
178
- const file = meta.file;
181
+ const data = meta;
182
+ if (!("file" in data) || typeof data.file !== "string") {
183
+ return;
184
+ }
185
+ const file = path_1.default.normalize(data.file);
179
186
  if (!undefinedKeys[file]) {
180
187
  undefinedKeys[file] = [];
181
188
  }
package/dist/types.d.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  export type Translation = Record<string, unknown>;
2
2
  export type CheckResult = Record<string, string[]>;
3
+ export type InvalidTranslationEntry = {
4
+ key: string;
5
+ msg: string;
6
+ };
7
+ export type InvalidTranslationsResult = Record<string, InvalidTranslationEntry[]>;
3
8
  export type TranslationFile = {
4
9
  reference: string | null;
5
10
  name: string;
@@ -1,8 +1,5 @@
1
1
  import { MessageFormatElement } from "@formatjs/icu-messageformat-parser";
2
- import { Translation } from "../types";
3
- export declare const findInvalidTranslations: (source: Translation, files: Record<string, Translation>) => {};
4
- export declare const compareTranslationFiles: (a: Translation, b: Translation) => {
5
- key: string;
6
- msg: string;
7
- }[];
2
+ import { InvalidTranslationEntry, InvalidTranslationsResult, Translation } from "../types";
3
+ export declare const findInvalidTranslations: (source: Translation, files: Record<string, Translation>) => InvalidTranslationsResult;
4
+ export declare const compareTranslationFiles: (a: Translation, b: Translation) => InvalidTranslationEntry[];
8
5
  export declare const hasDiff: (a: MessageFormatElement[], b: MessageFormatElement[]) => boolean;
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hasDiff = exports.compareTranslationFiles = exports.findInvalidTranslations = void 0;
4
4
  const icu_messageformat_parser_1 = require("@formatjs/icu-messageformat-parser");
5
5
  const findInvalidTranslations = (source, files) => {
6
- let differences = {};
6
+ const differences = {};
7
7
  if (Object.keys(files).length === 0) {
8
8
  return differences;
9
9
  }
10
10
  for (const [lang, file] of Object.entries(files)) {
11
11
  const result = (0, exports.compareTranslationFiles)(source, file);
12
12
  if (result.length > 0) {
13
- differences = Object.assign(differences, { [lang]: result });
13
+ differences[lang] = result;
14
14
  }
15
15
  }
16
16
  return differences;
@@ -27,7 +27,7 @@ const sortParsedKeys = (a, b) => {
27
27
  return a.type - b.type;
28
28
  };
29
29
  const compareTranslationFiles = (a, b) => {
30
- let diffs = [];
30
+ const diffs = [];
31
31
  for (const key in a) {
32
32
  if (b[key] === undefined) {
33
33
  continue;
@@ -5,7 +5,7 @@
5
5
  *
6
6
  */
7
7
  import { MessageFormatElement } from "./i18NextParser";
8
- import { Translation } from "../types";
9
- export declare const findInvalid18nTranslations: (source: Translation, targets: Record<string, Translation>) => {};
10
- export declare const compareTranslationFiles: (a: Translation, b: Translation) => unknown[];
8
+ import { InvalidTranslationEntry, InvalidTranslationsResult, Translation } from "../types";
9
+ export declare const findInvalid18nTranslations: (source: Translation, targets: Record<string, Translation>) => InvalidTranslationsResult;
10
+ export declare const compareTranslationFiles: (a: Translation, b: Translation) => InvalidTranslationEntry[];
11
11
  export declare const hasDiff: (a: MessageFormatElement[], b: MessageFormatElement[]) => boolean;
@@ -16,7 +16,7 @@ const findInvalid18nTranslations = (source, targets) => {
16
16
  for (const [lang, file] of Object.entries(targets)) {
17
17
  const result = (0, exports.compareTranslationFiles)(source, file);
18
18
  if (result.length > 0) {
19
- differences = Object.assign(differences, { [lang]: result });
19
+ differences[lang] = result;
20
20
  }
21
21
  }
22
22
  return differences;
@@ -1,3 +1,3 @@
1
1
  import { Translation } from "../types";
2
- export declare const findMissingKeys: (source: Translation, targets: Record<string, Translation>) => {};
2
+ export declare const findMissingKeys: (source: Translation, targets: Record<string, Translation>) => Record<string, string[]>;
3
3
  export declare const compareTranslationFiles: (a: Translation, b: Translation) => string[];
@@ -6,7 +6,7 @@ const findMissingKeys = (source, targets) => {
6
6
  for (const [lang, file] of Object.entries(targets)) {
7
7
  const result = (0, exports.compareTranslationFiles)(source, file);
8
8
  if (result.length > 0) {
9
- differences = Object.assign(differences, { [lang]: result });
9
+ differences[lang] = result;
10
10
  }
11
11
  }
12
12
  return differences;
@@ -18,7 +18,7 @@ const isTranslationObject = (entry) => {
18
18
  return typeof entry === "object";
19
19
  };
20
20
  const flattenEntry = (entry, keys = []) => {
21
- let result = {};
21
+ const result = {};
22
22
  if (!entry) {
23
23
  return result;
24
24
  }