@messagevisor/core 0.0.1 → 0.1.0
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/CHANGELOG.md +16 -0
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/jest.config.js +8 -0
- package/lib/benchmark/index.d.ts +2 -0
- package/lib/benchmark/index.js +417 -0
- package/lib/benchmark/index.js.map +1 -0
- package/lib/builder/index.d.ts +70 -0
- package/lib/builder/index.js +831 -0
- package/lib/builder/index.js.map +1 -0
- package/lib/cli/index.d.ts +28 -0
- package/lib/cli/index.js +182 -0
- package/lib/cli/index.js.map +1 -0
- package/lib/config/index.d.ts +61 -0
- package/lib/config/index.js +255 -0
- package/lib/config/index.js.map +1 -0
- package/lib/create/index.d.ts +2 -0
- package/lib/create/index.js +405 -0
- package/lib/create/index.js.map +1 -0
- package/lib/datasource/filesystemAdapter.d.ts +44 -0
- package/lib/datasource/filesystemAdapter.js +424 -0
- package/lib/datasource/filesystemAdapter.js.map +1 -0
- package/lib/datasource/index.d.ts +39 -0
- package/lib/datasource/index.js +96 -0
- package/lib/datasource/index.js.map +1 -0
- package/lib/error.d.ts +6 -0
- package/lib/error.js +49 -0
- package/lib/error.js.map +1 -0
- package/lib/evaluate/cli.d.ts +8 -0
- package/lib/evaluate/cli.js +179 -0
- package/lib/evaluate/cli.js.map +1 -0
- package/lib/evaluate/index.d.ts +10 -0
- package/lib/evaluate/index.js +131 -0
- package/lib/evaluate/index.js.map +1 -0
- package/lib/examples/coerceExampleIsoDates.d.ts +12 -0
- package/lib/examples/coerceExampleIsoDates.js +81 -0
- package/lib/examples/coerceExampleIsoDates.js.map +1 -0
- package/lib/examples/index.d.ts +63 -0
- package/lib/examples/index.js +713 -0
- package/lib/examples/index.js.map +1 -0
- package/lib/exporter/index.d.ts +60 -0
- package/lib/exporter/index.js +610 -0
- package/lib/exporter/index.js.map +1 -0
- package/lib/find-duplicates/index.d.ts +41 -0
- package/lib/find-duplicates/index.js +297 -0
- package/lib/find-duplicates/index.js.map +1 -0
- package/lib/generate-code/index.d.ts +11 -0
- package/lib/generate-code/index.js +157 -0
- package/lib/generate-code/index.js.map +1 -0
- package/lib/generate-code/typescript.d.ts +14 -0
- package/lib/generate-code/typescript.js +307 -0
- package/lib/generate-code/typescript.js.map +1 -0
- package/lib/importer/index.d.ts +64 -0
- package/lib/importer/index.js +1092 -0
- package/lib/importer/index.js.map +1 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +35 -0
- package/lib/index.js.map +1 -0
- package/lib/info/index.d.ts +17 -0
- package/lib/info/index.js +132 -0
- package/lib/info/index.js.map +1 -0
- package/lib/init/index.d.ts +30 -0
- package/lib/init/index.js +348 -0
- package/lib/init/index.js.map +1 -0
- package/lib/lint/index.d.ts +1 -0
- package/lib/lint/index.js +6 -0
- package/lib/lint/index.js.map +1 -0
- package/lib/linter/attributeSchema.d.ts +7 -0
- package/lib/linter/attributeSchema.js +36 -0
- package/lib/linter/attributeSchema.js.map +1 -0
- package/lib/linter/checkLocaleCircularDependency.d.ts +7 -0
- package/lib/linter/checkLocaleCircularDependency.js +42 -0
- package/lib/linter/checkLocaleCircularDependency.js.map +1 -0
- package/lib/linter/conditionSchema.d.ts +3 -0
- package/lib/linter/conditionSchema.js +283 -0
- package/lib/linter/conditionSchema.js.map +1 -0
- package/lib/linter/formatSchema.d.ts +325 -0
- package/lib/linter/formatSchema.js +165 -0
- package/lib/linter/formatSchema.js.map +1 -0
- package/lib/linter/icuStyleLint.d.ts +6 -0
- package/lib/linter/icuStyleLint.js +226 -0
- package/lib/linter/icuStyleLint.js.map +1 -0
- package/lib/linter/index.d.ts +34 -0
- package/lib/linter/index.js +557 -0
- package/lib/linter/index.js.map +1 -0
- package/lib/linter/localeSchema.d.ts +672 -0
- package/lib/linter/localeSchema.js +50 -0
- package/lib/linter/localeSchema.js.map +1 -0
- package/lib/linter/messageSchema.d.ts +35 -0
- package/lib/linter/messageSchema.js +115 -0
- package/lib/linter/messageSchema.js.map +1 -0
- package/lib/linter/printError.d.ts +8 -0
- package/lib/linter/printError.js +41 -0
- package/lib/linter/printError.js.map +1 -0
- package/lib/linter/schema.d.ts +33 -0
- package/lib/linter/schema.js +192 -0
- package/lib/linter/schema.js.map +1 -0
- package/lib/linter/segmentSchema.d.ts +8 -0
- package/lib/linter/segmentSchema.js +18 -0
- package/lib/linter/segmentSchema.js.map +1 -0
- package/lib/linter/targetSchema.d.ts +337 -0
- package/lib/linter/targetSchema.js +39 -0
- package/lib/linter/targetSchema.js.map +1 -0
- package/lib/linter/testSchema.d.ts +71 -0
- package/lib/linter/testSchema.js +165 -0
- package/lib/linter/testSchema.js.map +1 -0
- package/lib/linter/zodHelpers.d.ts +2 -0
- package/lib/linter/zodHelpers.js +15 -0
- package/lib/linter/zodHelpers.js.map +1 -0
- package/lib/list/index.d.ts +8 -0
- package/lib/list/index.js +524 -0
- package/lib/list/index.js.map +1 -0
- package/lib/matrix.d.ts +4 -0
- package/lib/matrix.js +66 -0
- package/lib/matrix.js.map +1 -0
- package/lib/promoter/index.d.ts +65 -0
- package/lib/promoter/index.js +1208 -0
- package/lib/promoter/index.js.map +1 -0
- package/lib/prune/index.d.ts +37 -0
- package/lib/prune/index.js +673 -0
- package/lib/prune/index.js.map +1 -0
- package/lib/sets.d.ts +10 -0
- package/lib/sets.js +120 -0
- package/lib/sets.js.map +1 -0
- package/lib/tester/cliFormat.d.ts +8 -0
- package/lib/tester/cliFormat.js +15 -0
- package/lib/tester/cliFormat.js.map +1 -0
- package/lib/tester/index.d.ts +35 -0
- package/lib/tester/index.js +713 -0
- package/lib/tester/index.js.map +1 -0
- package/lib/tester/matrix.d.ts +14 -0
- package/lib/tester/matrix.js +76 -0
- package/lib/tester/matrix.js.map +1 -0
- package/lib/tester/prettyDuration.d.ts +1 -0
- package/lib/tester/prettyDuration.js +30 -0
- package/lib/tester/prettyDuration.js.map +1 -0
- package/lib/tester/printTestResult.d.ts +2 -0
- package/lib/tester/printTestResult.js +32 -0
- package/lib/tester/printTestResult.js.map +1 -0
- package/lib/tester/types.d.ts +29 -0
- package/lib/tester/types.js +3 -0
- package/lib/tester/types.js.map +1 -0
- package/package.json +41 -13
- package/src/benchmark/index.spec.ts +375 -0
- package/src/benchmark/index.ts +433 -0
- package/src/builder/index.spec.ts +822 -0
- package/src/builder/index.ts +920 -0
- package/src/cli/index.spec.ts +54 -0
- package/src/cli/index.ts +150 -0
- package/src/config/index.spec.ts +70 -0
- package/src/config/index.ts +259 -0
- package/src/create/index.spec.ts +272 -0
- package/src/create/index.ts +295 -0
- package/src/datasource/filesystemAdapter.ts +313 -0
- package/src/datasource/index.ts +135 -0
- package/src/error.ts +33 -0
- package/src/evaluate/cli.spec.ts +368 -0
- package/src/evaluate/cli.ts +130 -0
- package/src/evaluate/index.ts +161 -0
- package/src/examples/coerceExampleIsoDates.spec.ts +81 -0
- package/src/examples/coerceExampleIsoDates.ts +98 -0
- package/src/examples/index.spec.ts +453 -0
- package/src/examples/index.ts +854 -0
- package/src/exporter/index.spec.ts +443 -0
- package/src/exporter/index.ts +643 -0
- package/src/find-duplicates/index.spec.ts +289 -0
- package/src/find-duplicates/index.ts +314 -0
- package/src/generate-code/index.ts +92 -0
- package/src/generate-code/typescript.spec.ts +241 -0
- package/src/generate-code/typescript.ts +284 -0
- package/src/importer/index.spec.ts +1101 -0
- package/src/importer/index.ts +1190 -0
- package/src/index.ts +18 -0
- package/src/info/index.ts +67 -0
- package/src/init/index.spec.ts +279 -0
- package/src/init/index.ts +292 -0
- package/src/lint/index.ts +1 -0
- package/src/linter/attributeSchema.ts +38 -0
- package/src/linter/checkLocaleCircularDependency.ts +51 -0
- package/src/linter/conditionSchema.ts +386 -0
- package/src/linter/formatSchema.ts +170 -0
- package/src/linter/icuStyleLint.ts +312 -0
- package/src/linter/index.spec.ts +824 -0
- package/src/linter/index.ts +460 -0
- package/src/linter/localeSchema.ts +70 -0
- package/src/linter/messageSchema.ts +152 -0
- package/src/linter/printError.ts +52 -0
- package/src/linter/schema.ts +230 -0
- package/src/linter/segmentSchema.ts +15 -0
- package/src/linter/targetSchema.ts +50 -0
- package/src/linter/testSchema.spec.ts +405 -0
- package/src/linter/testSchema.ts +239 -0
- package/src/linter/zodHelpers.ts +16 -0
- package/src/list/index.spec.ts +431 -0
- package/src/list/index.ts +463 -0
- package/src/matrix.ts +69 -0
- package/src/promoter/index.spec.ts +584 -0
- package/src/promoter/index.ts +1267 -0
- package/src/prune/index.spec.ts +418 -0
- package/src/prune/index.ts +693 -0
- package/src/sets.ts +74 -0
- package/src/tester/cliFormat.ts +11 -0
- package/src/tester/featurevisorIntegration.spec.ts +101 -0
- package/src/tester/index.spec.ts +577 -0
- package/src/tester/index.ts +679 -0
- package/src/tester/matrix.ts +106 -0
- package/src/tester/prettyDuration.ts +34 -0
- package/src/tester/printTestResult.ts +40 -0
- package/src/tester/types.ts +32 -0
- package/tsconfig.cjs.json +11 -0
- package/tsconfig.typecheck.json +4 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import type { FormatPresets, Locale, Message } from "@messagevisor/types";
|
|
2
|
+
|
|
3
|
+
import type { LintError } from "./index";
|
|
4
|
+
|
|
5
|
+
const IntlMessageFormat =
|
|
6
|
+
require("intl-messageformat").default || require("intl-messageformat").IntlMessageFormat;
|
|
7
|
+
|
|
8
|
+
type IcuFormatType = "number" | "date" | "time";
|
|
9
|
+
|
|
10
|
+
interface IcuStyleReference {
|
|
11
|
+
type: IcuFormatType;
|
|
12
|
+
style: string;
|
|
13
|
+
isSkeleton: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface LintMessageIcuOptions {
|
|
17
|
+
icuSkeleton: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
21
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function deepMerge<T>(parent?: T, child?: T): T | undefined {
|
|
25
|
+
if (typeof parent === "undefined") {
|
|
26
|
+
return child;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (typeof child === "undefined") {
|
|
30
|
+
return parent;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!isPlainObject(parent) || !isPlainObject(child)) {
|
|
34
|
+
return child;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const result: Record<string, unknown> = { ...parent };
|
|
38
|
+
|
|
39
|
+
for (const key of Object.keys(child)) {
|
|
40
|
+
result[key] = deepMerge(result[key], child[key]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return result as T;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function resolveLocaleFormatChain(localeKey: string, localesByKey: Record<string, Locale>) {
|
|
47
|
+
const chain: string[] = [];
|
|
48
|
+
const seen = new Set<string>();
|
|
49
|
+
let currentKey: string | undefined = localeKey;
|
|
50
|
+
|
|
51
|
+
while (currentKey && !seen.has(currentKey)) {
|
|
52
|
+
seen.add(currentKey);
|
|
53
|
+
chain.unshift(currentKey);
|
|
54
|
+
currentKey = localesByKey[currentKey]?.inheritFormatsFrom;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return chain;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function resolveLocaleFormats(localeKey: string, localesByKey: Record<string, Locale>) {
|
|
61
|
+
const chain = resolveLocaleFormatChain(localeKey, localesByKey);
|
|
62
|
+
let formats: FormatPresets | undefined;
|
|
63
|
+
|
|
64
|
+
for (const key of chain) {
|
|
65
|
+
formats = deepMerge(formats, localesByKey[key]?.formats);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return formats;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function findMatchingBrace(value: string, openIndex: number) {
|
|
72
|
+
let depth = 0;
|
|
73
|
+
|
|
74
|
+
for (let index = openIndex; index < value.length; index++) {
|
|
75
|
+
const character = value[index];
|
|
76
|
+
|
|
77
|
+
if (character === "{") {
|
|
78
|
+
depth++;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (character === "}") {
|
|
82
|
+
depth--;
|
|
83
|
+
|
|
84
|
+
if (depth === 0) {
|
|
85
|
+
return index;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return -1;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function splitTopLevelCommas(value: string) {
|
|
94
|
+
const parts: string[] = [];
|
|
95
|
+
let depth = 0;
|
|
96
|
+
let startIndex = 0;
|
|
97
|
+
|
|
98
|
+
for (let index = 0; index < value.length; index++) {
|
|
99
|
+
const character = value[index];
|
|
100
|
+
|
|
101
|
+
if (character === "{") {
|
|
102
|
+
depth++;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (character === "}") {
|
|
107
|
+
depth--;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (character === "," && depth === 0) {
|
|
112
|
+
parts.push(value.slice(startIndex, index).trim());
|
|
113
|
+
startIndex = index + 1;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
parts.push(value.slice(startIndex).trim());
|
|
118
|
+
|
|
119
|
+
return parts;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function normalizeStyle(style: string): { style: string; isSkeleton: boolean } {
|
|
123
|
+
const trimmedStyle = style.trim();
|
|
124
|
+
|
|
125
|
+
if (!trimmedStyle) {
|
|
126
|
+
return { style: "", isSkeleton: false };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (trimmedStyle.startsWith("::")) {
|
|
130
|
+
return { style: trimmedStyle, isSkeleton: true };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return { style: trimmedStyle.split(/\s+/)[0], isSkeleton: false };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function extractIcuStyleReferences(value: string): IcuStyleReference[] {
|
|
137
|
+
const references: IcuStyleReference[] = [];
|
|
138
|
+
let index = 0;
|
|
139
|
+
|
|
140
|
+
while (index < value.length) {
|
|
141
|
+
const openIndex = value.indexOf("{", index);
|
|
142
|
+
|
|
143
|
+
if (openIndex === -1) {
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const closeIndex = findMatchingBrace(value, openIndex);
|
|
148
|
+
|
|
149
|
+
if (closeIndex === -1) {
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const content = value.slice(openIndex + 1, closeIndex);
|
|
154
|
+
const parts = splitTopLevelCommas(content);
|
|
155
|
+
const type = parts[1]?.trim();
|
|
156
|
+
const styleReference = parts[2] ? normalizeStyle(parts[2]) : { style: "", isSkeleton: false };
|
|
157
|
+
|
|
158
|
+
if ((type === "number" || type === "date" || type === "time") && styleReference.style) {
|
|
159
|
+
references.push({ type, style: styleReference.style, isSkeleton: styleReference.isSkeleton });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
references.push(...extractIcuStyleReferences(content));
|
|
163
|
+
index = closeIndex + 1;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return references;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function hasFormatStyle(formats: FormatPresets | undefined, type: IcuFormatType, style: string) {
|
|
170
|
+
return typeof formats?.[type]?.[style] !== "undefined";
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function getTranslationErrors(
|
|
174
|
+
messageKey: string,
|
|
175
|
+
messageFilePath: string,
|
|
176
|
+
translation: string,
|
|
177
|
+
localeKey: string,
|
|
178
|
+
path: (string | number)[],
|
|
179
|
+
localesByKey: Record<string, Locale>,
|
|
180
|
+
options: LintMessageIcuOptions,
|
|
181
|
+
): LintError[] {
|
|
182
|
+
const errors: LintError[] = [];
|
|
183
|
+
const formats = resolveLocaleFormats(localeKey, localesByKey);
|
|
184
|
+
const reportedReferences = new Set<string>();
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
new IntlMessageFormat(translation, localeKey);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
errors.push({
|
|
190
|
+
level: "error",
|
|
191
|
+
filePath: messageFilePath,
|
|
192
|
+
entityType: "message",
|
|
193
|
+
entityKey: messageKey,
|
|
194
|
+
message: `Invalid ICU syntax for locale "${localeKey}" in message "${messageKey}". Fix the ICU message syntax before building datafiles. Parser reported: ${error instanceof Error ? error.message : String(error)}`,
|
|
195
|
+
path,
|
|
196
|
+
code: "invalid_icu_syntax",
|
|
197
|
+
value: translation,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return errors;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
for (const reference of extractIcuStyleReferences(translation)) {
|
|
204
|
+
const referenceKey = `${reference.type}:${reference.style}`;
|
|
205
|
+
|
|
206
|
+
if (reportedReferences.has(referenceKey)) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
reportedReferences.add(referenceKey);
|
|
211
|
+
|
|
212
|
+
if (reference.isSkeleton) {
|
|
213
|
+
if (!options.icuSkeleton) {
|
|
214
|
+
errors.push({
|
|
215
|
+
level: "error",
|
|
216
|
+
filePath: messageFilePath,
|
|
217
|
+
entityType: "message",
|
|
218
|
+
entityKey: messageKey,
|
|
219
|
+
message: `ICU skeleton style "${reference.style}" is not allowed for locale "${localeKey}" in message "${messageKey}" because messagevisor.config.js has icuSkeleton set to false. Use a named formats.${reference.type} preset instead, or enable icuSkeleton.`,
|
|
220
|
+
path,
|
|
221
|
+
code: "icu_skeleton_not_allowed",
|
|
222
|
+
value: reference.style,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (hasFormatStyle(formats, reference.type, reference.style)) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
errors.push({
|
|
234
|
+
level: "error",
|
|
235
|
+
filePath: messageFilePath,
|
|
236
|
+
entityType: "message",
|
|
237
|
+
entityKey: messageKey,
|
|
238
|
+
message: `Missing ICU ${reference.type} format style "${reference.style}" for locale "${localeKey}" in message "${messageKey}". Add formats.${reference.type}.${reference.style} to locale "${localeKey}" or one of its inheritFormatsFrom ancestors.`,
|
|
239
|
+
path,
|
|
240
|
+
code: "missing_icu_format_style",
|
|
241
|
+
value: reference.style,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return errors;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function lintMessageIcuFormatStyles(
|
|
249
|
+
messagesByKey: Record<string, Message>,
|
|
250
|
+
localesByKey: Record<string, Locale>,
|
|
251
|
+
getMessageFilePath: (key: string) => string,
|
|
252
|
+
options: LintMessageIcuOptions,
|
|
253
|
+
) {
|
|
254
|
+
const errors: LintError[] = [];
|
|
255
|
+
|
|
256
|
+
for (const messageKey of Object.keys(messagesByKey)) {
|
|
257
|
+
const message = messagesByKey[messageKey];
|
|
258
|
+
const messageFilePath = getMessageFilePath(messageKey);
|
|
259
|
+
const translations = isPlainObject(message?.translations) ? message.translations : {};
|
|
260
|
+
|
|
261
|
+
for (const localeKey of Object.keys(translations)) {
|
|
262
|
+
const translation = translations[localeKey];
|
|
263
|
+
|
|
264
|
+
if (typeof translation !== "string") {
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
errors.push(
|
|
269
|
+
...getTranslationErrors(
|
|
270
|
+
messageKey,
|
|
271
|
+
messageFilePath,
|
|
272
|
+
translation,
|
|
273
|
+
localeKey,
|
|
274
|
+
["translations", localeKey],
|
|
275
|
+
localesByKey,
|
|
276
|
+
options,
|
|
277
|
+
),
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const overrides = Array.isArray(message?.overrides) ? message.overrides : [];
|
|
282
|
+
|
|
283
|
+
for (let index = 0; index < overrides.length; index++) {
|
|
284
|
+
const override = overrides[index];
|
|
285
|
+
const overrideTranslations = isPlainObject(override?.translations)
|
|
286
|
+
? override.translations
|
|
287
|
+
: {};
|
|
288
|
+
|
|
289
|
+
for (const localeKey of Object.keys(overrideTranslations)) {
|
|
290
|
+
const translation = overrideTranslations[localeKey];
|
|
291
|
+
|
|
292
|
+
if (typeof translation !== "string") {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
errors.push(
|
|
297
|
+
...getTranslationErrors(
|
|
298
|
+
messageKey,
|
|
299
|
+
messageFilePath,
|
|
300
|
+
translation,
|
|
301
|
+
localeKey,
|
|
302
|
+
["overrides", index, "translations", localeKey],
|
|
303
|
+
localesByKey,
|
|
304
|
+
options,
|
|
305
|
+
),
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return errors;
|
|
312
|
+
}
|