@i18nprune/core 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/LICENSE +21 -0
- package/README.md +165 -0
- package/dist/adapters-gp1lXp0T.d.ts +12 -0
- package/dist/capabilities-x74cD2Hu.d.ts +48 -0
- package/dist/cleanup.d.ts +64 -0
- package/dist/cleanup.js +3999 -0
- package/dist/config.d.ts +201 -0
- package/dist/config.js +2865 -0
- package/dist/coreContext-DMaWLvmB.d.ts +388 -0
- package/dist/fs-BUYD8ZhA.d.ts +20 -0
- package/dist/generate.d.ts +487 -0
- package/dist/generate.js +9389 -0
- package/dist/humanEmit-ygNlYX-S.d.ts +79 -0
- package/dist/index-BQuLEQ9b.d.ts +7 -0
- package/dist/index-B_ow_Xvr.d.ts +97 -0
- package/dist/index-BgG01AKL.d.ts +287 -0
- package/dist/index-CIzZl4W8.d.ts +124 -0
- package/dist/index-Csm1w7XD.d.ts +58 -0
- package/dist/index-DLwTogCo.d.ts +43 -0
- package/dist/index-DVT26v11.d.ts +61 -0
- package/dist/index-DdjljwMj.d.ts +39 -0
- package/dist/index-DeIw-cZd.d.ts +52 -0
- package/dist/index-X50E1FIX.d.ts +50 -0
- package/dist/index.d.ts +9180 -0
- package/dist/index.js +21888 -0
- package/dist/init.d.ts +86 -0
- package/dist/init.js +848 -0
- package/dist/listWindow-XEFxQZi1.d.ts +30 -0
- package/dist/localeTargetCodes-BBIQjauw.d.ts +11 -0
- package/dist/locales.d.ts +39 -0
- package/dist/locales.js +2288 -0
- package/dist/missing-BVCvgUC8.d.ts +10 -0
- package/dist/missing.d.ts +85 -0
- package/dist/missing.js +5892 -0
- package/dist/modeResolve-cGVaY5Hh.d.ts +25 -0
- package/dist/path-Bfn3SAts.d.ts +11 -0
- package/dist/profile-BwOP9WKh.d.ts +9 -0
- package/dist/providers-0uMEfT6q.d.ts +82 -0
- package/dist/prune-c6hKZCv_.d.ts +33 -0
- package/dist/quality.d.ts +36 -0
- package/dist/quality.js +3868 -0
- package/dist/report-D5-6bVFj.d.ts +8 -0
- package/dist/report-schema.d.ts +102 -0
- package/dist/report-schema.js +42 -0
- package/dist/resumeCandidates-xR13eEwt.d.ts +200 -0
- package/dist/root-2-kCaBvQ.d.ts +1110 -0
- package/dist/runtime/edge.d.ts +21 -0
- package/dist/runtime/edge.js +87 -0
- package/dist/runtime/helpers/sync.d.ts +16 -0
- package/dist/runtime/helpers/sync.js +117 -0
- package/dist/runtime/node.d.ts +24 -0
- package/dist/runtime/node.js +204 -0
- package/dist/runtime/web.d.ts +21 -0
- package/dist/runtime/web.js +84 -0
- package/dist/shared.d.ts +1177 -0
- package/dist/shared.js +4897 -0
- package/dist/sourceContext-1LQg3HiQ.d.ts +36 -0
- package/dist/sourceSurface-mDtwGo1E.d.ts +122 -0
- package/dist/sync.d.ts +86 -0
- package/dist/sync.js +4971 -0
- package/dist/syncSegment-Bx6He2Mu.d.ts +149 -0
- package/dist/targets-EmtKyr6F.d.ts +23 -0
- package/dist/template-CGM-_WLT.d.ts +139 -0
- package/dist/translate-CIHYp7wi.d.ts +77 -0
- package/dist/types/shared.d.ts +21 -0
- package/dist/types/shared.js +1 -0
- package/dist/types.d.ts +1345 -0
- package/dist/types.js +1 -0
- package/dist/validate.d.ts +126 -0
- package/dist/validate.js +3717 -0
- package/package.json +128 -0
package/dist/shared.js
ADDED
|
@@ -0,0 +1,4897 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/shared/json/index.ts
|
|
8
|
+
var json_exports = {};
|
|
9
|
+
__export(json_exports, {
|
|
10
|
+
I18nPruneJsonParseError: () => I18nPruneJsonParseError,
|
|
11
|
+
applyPreserveFromSource: () => applyPreserveFromSource,
|
|
12
|
+
deepClone: () => deepClone,
|
|
13
|
+
deleteAtPath: () => deleteAtPath,
|
|
14
|
+
getAtPath: () => getAtPath,
|
|
15
|
+
getJsonParseLocation: () => getJsonParseLocation,
|
|
16
|
+
mergeToTemplateShape: () => mergeToTemplateShape,
|
|
17
|
+
parseJsonText: () => parseJsonText,
|
|
18
|
+
pruneToTemplateShape: () => pruneToTemplateShape,
|
|
19
|
+
setAtPath: () => setAtPath,
|
|
20
|
+
splitPath: () => splitPath,
|
|
21
|
+
targetLocaleCoversAllSourcePaths: () => targetLocaleCoversAllSourcePaths,
|
|
22
|
+
tryParseJsonText: () => tryParseJsonText
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// src/shared/json/clone.ts
|
|
26
|
+
function deepClone(x) {
|
|
27
|
+
if (x === null || typeof x !== "object") return x;
|
|
28
|
+
if (Array.isArray(x)) return x.map((e) => deepClone(e));
|
|
29
|
+
const o = {};
|
|
30
|
+
for (const k of Object.keys(x)) {
|
|
31
|
+
o[k] = deepClone(x[k]);
|
|
32
|
+
}
|
|
33
|
+
return o;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/shared/json/path.ts
|
|
37
|
+
function splitPath(pathStr) {
|
|
38
|
+
const parts = [];
|
|
39
|
+
const re = /[^.[\]]+|\[\d+\]/g;
|
|
40
|
+
let m;
|
|
41
|
+
const s = pathStr.trim();
|
|
42
|
+
while ((m = re.exec(s)) !== null) {
|
|
43
|
+
const tok = m[0];
|
|
44
|
+
if (tok.startsWith("[") && tok.endsWith("]")) {
|
|
45
|
+
parts.push(Number.parseInt(tok.slice(1, -1), 10));
|
|
46
|
+
} else {
|
|
47
|
+
parts.push(tok);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return parts;
|
|
51
|
+
}
|
|
52
|
+
function isPlainObject(x) {
|
|
53
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
54
|
+
}
|
|
55
|
+
function getAtPath(root, pathStr) {
|
|
56
|
+
let cur = root;
|
|
57
|
+
for (const seg of splitPath(pathStr)) {
|
|
58
|
+
if (cur === null || cur === void 0) return void 0;
|
|
59
|
+
if (typeof seg === "number") {
|
|
60
|
+
if (!Array.isArray(cur)) return void 0;
|
|
61
|
+
cur = cur[seg];
|
|
62
|
+
} else {
|
|
63
|
+
if (!isPlainObject(cur)) return void 0;
|
|
64
|
+
cur = cur[seg];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return cur;
|
|
68
|
+
}
|
|
69
|
+
function setAtPath(root, pathStr, value) {
|
|
70
|
+
const segs = splitPath(pathStr);
|
|
71
|
+
if (segs.length === 0) return root;
|
|
72
|
+
const clone = deepClone(root);
|
|
73
|
+
let cur = clone;
|
|
74
|
+
for (let i = 0; i < segs.length - 1; i += 1) {
|
|
75
|
+
const seg = segs[i];
|
|
76
|
+
const next = segs[i + 1];
|
|
77
|
+
if (typeof seg === "number") {
|
|
78
|
+
if (!Array.isArray(cur)) return clone;
|
|
79
|
+
ensureArraySlot(cur, seg, typeof next === "number" ? [] : {});
|
|
80
|
+
cur = cur[seg];
|
|
81
|
+
} else {
|
|
82
|
+
if (!isPlainObject(cur)) return clone;
|
|
83
|
+
if (!(seg in cur)) {
|
|
84
|
+
cur[seg] = typeof next === "number" ? [] : {};
|
|
85
|
+
}
|
|
86
|
+
cur = cur[seg];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const last = segs[segs.length - 1];
|
|
90
|
+
if (typeof last === "number") {
|
|
91
|
+
if (!Array.isArray(cur)) return clone;
|
|
92
|
+
ensureArraySlot(cur, last, null);
|
|
93
|
+
cur[last] = value;
|
|
94
|
+
} else {
|
|
95
|
+
if (!isPlainObject(cur)) return clone;
|
|
96
|
+
cur[last] = value;
|
|
97
|
+
}
|
|
98
|
+
return clone;
|
|
99
|
+
}
|
|
100
|
+
function ensureArraySlot(arr, index, fill) {
|
|
101
|
+
while (arr.length <= index) {
|
|
102
|
+
arr.push(fill);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function deleteAtPath(root, pathStr) {
|
|
106
|
+
const segs = splitPath(pathStr);
|
|
107
|
+
if (segs.length === 0) return root;
|
|
108
|
+
const clone = deepClone(root);
|
|
109
|
+
let cur = clone;
|
|
110
|
+
for (let i = 0; i < segs.length - 1; i += 1) {
|
|
111
|
+
const seg = segs[i];
|
|
112
|
+
if (typeof seg === "number") {
|
|
113
|
+
if (!Array.isArray(cur)) return clone;
|
|
114
|
+
cur = cur[seg];
|
|
115
|
+
} else {
|
|
116
|
+
if (!isPlainObject(cur)) return clone;
|
|
117
|
+
cur = cur[seg];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const last = segs[segs.length - 1];
|
|
121
|
+
if (typeof last === "number") {
|
|
122
|
+
if (Array.isArray(cur)) cur.splice(last, 1);
|
|
123
|
+
} else if (isPlainObject(cur)) {
|
|
124
|
+
delete cur[last];
|
|
125
|
+
}
|
|
126
|
+
return clone;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/shared/errors/index.ts
|
|
130
|
+
var errors_exports = {};
|
|
131
|
+
__export(errors_exports, {
|
|
132
|
+
I18nPruneError: () => I18nPruneError,
|
|
133
|
+
isErrnoCode: () => isErrnoCode,
|
|
134
|
+
issueFromI18nPruneError: () => issueFromI18nPruneError,
|
|
135
|
+
normalizeUnknownError: () => normalizeUnknownError,
|
|
136
|
+
rethrowAsI18n: () => rethrowAsI18n
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// src/shared/errors/internal.ts
|
|
140
|
+
var I18nPruneError = class extends Error {
|
|
141
|
+
code;
|
|
142
|
+
issueCode;
|
|
143
|
+
constructor(message, code, options) {
|
|
144
|
+
super(message, options?.cause !== void 0 ? { cause: options.cause } : void 0);
|
|
145
|
+
this.name = "I18nPruneError";
|
|
146
|
+
this.code = code;
|
|
147
|
+
this.issueCode = options?.issueCode;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// src/shared/constants/links.ts
|
|
152
|
+
var GITHUB_OWNER = "zamdevio";
|
|
153
|
+
var GITHUB_REPO = "i18nprune";
|
|
154
|
+
var GITHUB_REPO_URL = `https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}`;
|
|
155
|
+
var LICENSE_URL = `${GITHUB_REPO_URL}/blob/main/LICENSE`;
|
|
156
|
+
var DOCS_SITE_BASE = "https://docs.i18nprune.dev";
|
|
157
|
+
var META_WORKER_URL = "https://meta.i18nprune.dev";
|
|
158
|
+
var DEFAULT_WORKER_API_URL = "https://worker.i18nprune.dev";
|
|
159
|
+
var DEMO_REPORT_URL = "https://report.i18nprune.dev";
|
|
160
|
+
var DEMO_WEB_APP_BASE = "https://web.i18nprune.dev";
|
|
161
|
+
var NPM_PACKAGE_NAME = "i18nprune";
|
|
162
|
+
var NPM_PACKAGE_URL = `https://www.npmjs.com/package/${NPM_PACKAGE_NAME}`;
|
|
163
|
+
|
|
164
|
+
// src/shared/constants/docs.ts
|
|
165
|
+
var GITHUB_BASE = GITHUB_REPO_URL;
|
|
166
|
+
var GITHUB_DOCS_BASE = `${GITHUB_BASE}/blob/main/docs`;
|
|
167
|
+
var GITHUB_DOCS_TREE_BASE = `${GITHUB_BASE}/tree/main/docs`;
|
|
168
|
+
var DOCS_SITE_ORIGIN = DOCS_SITE_BASE;
|
|
169
|
+
var DOCS_ISSUES_PAGE_PATH = "/issues";
|
|
170
|
+
|
|
171
|
+
// src/shared/docs/issueAnchors.ts
|
|
172
|
+
var DOC_ISSUE_PARENT_SEGMENTS = /* @__PURE__ */ new Set([
|
|
173
|
+
"cli",
|
|
174
|
+
"cleanup",
|
|
175
|
+
"config",
|
|
176
|
+
"context",
|
|
177
|
+
"doctor",
|
|
178
|
+
"generate",
|
|
179
|
+
"io",
|
|
180
|
+
"languages",
|
|
181
|
+
"locale",
|
|
182
|
+
"locales",
|
|
183
|
+
"missing",
|
|
184
|
+
"patching",
|
|
185
|
+
"paths",
|
|
186
|
+
"project",
|
|
187
|
+
"quality",
|
|
188
|
+
"report",
|
|
189
|
+
"scan",
|
|
190
|
+
"share",
|
|
191
|
+
"sync",
|
|
192
|
+
"translate",
|
|
193
|
+
"validate"
|
|
194
|
+
]);
|
|
195
|
+
function issueDocHeadingSlug(raw) {
|
|
196
|
+
return raw.toLowerCase().replace(/[.\s_]+/g, "-").replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
197
|
+
}
|
|
198
|
+
function splitIssueCode(code) {
|
|
199
|
+
return code.trim().split(".");
|
|
200
|
+
}
|
|
201
|
+
function buildIssueCodeDocLinkParts(code) {
|
|
202
|
+
const trimmed = code.trim();
|
|
203
|
+
const parts = splitIssueCode(trimmed);
|
|
204
|
+
let parent = null;
|
|
205
|
+
if (parts.length >= 3 && parts[0] === "i18nprune") {
|
|
206
|
+
const p = parts[1];
|
|
207
|
+
if (DOC_ISSUE_PARENT_SEGMENTS.has(p)) parent = p;
|
|
208
|
+
}
|
|
209
|
+
let anchor;
|
|
210
|
+
if (parent) {
|
|
211
|
+
anchor = issueDocHeadingSlug(parts.slice(2).join("."));
|
|
212
|
+
} else {
|
|
213
|
+
anchor = issueDocHeadingSlug(trimmed.includes(".") ? trimmed.replace(/\./g, "_") : trimmed);
|
|
214
|
+
}
|
|
215
|
+
const sitePagePath = parent ? `${DOCS_ISSUES_PAGE_PATH}/${parent}` : DOCS_ISSUES_PAGE_PATH;
|
|
216
|
+
const repoDocPath = parent ? `issues/${parent}` : "issues";
|
|
217
|
+
return { parent, anchor, sitePagePath, repoDocPath };
|
|
218
|
+
}
|
|
219
|
+
function resolveIssueCodeDocLink(code) {
|
|
220
|
+
return buildIssueCodeDocLinkParts(code);
|
|
221
|
+
}
|
|
222
|
+
function issueCodeRepoDocPathForIssueCode(code) {
|
|
223
|
+
return buildIssueCodeDocLinkParts(code).repoDocPath;
|
|
224
|
+
}
|
|
225
|
+
function issueCodeDocHref(code) {
|
|
226
|
+
const { sitePagePath, anchor } = buildIssueCodeDocLinkParts(code);
|
|
227
|
+
return `${DOCS_SITE_BASE}${sitePagePath}#${anchor}`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/shared/errors/normalize.ts
|
|
231
|
+
function isErrnoCode(error, code) {
|
|
232
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
233
|
+
}
|
|
234
|
+
function normalizeUnknownError(error, input) {
|
|
235
|
+
if (error instanceof I18nPruneError) return error;
|
|
236
|
+
const extra = input.issueCode !== void 0 ? { issueCode: input.issueCode } : void 0;
|
|
237
|
+
if (error instanceof Error) {
|
|
238
|
+
return new I18nPruneError(`${input.when}: ${error.message}`, input.defaultCode, { cause: error, ...extra });
|
|
239
|
+
}
|
|
240
|
+
return new I18nPruneError(`${input.when}: ${String(error)}`, input.defaultCode, { cause: error, ...extra });
|
|
241
|
+
}
|
|
242
|
+
function issueFromI18nPruneError(error, input) {
|
|
243
|
+
const code = error.issueCode ?? input.codeByErrorCode?.[error.code] ?? input.fallbackCode;
|
|
244
|
+
const base = {
|
|
245
|
+
severity: "error",
|
|
246
|
+
code,
|
|
247
|
+
message: error.message
|
|
248
|
+
};
|
|
249
|
+
const withPath = input.path !== void 0 ? { ...base, path: input.path } : base;
|
|
250
|
+
if (!code.startsWith("i18nprune.")) return withPath;
|
|
251
|
+
return { ...withPath, docPath: issueCodeRepoDocPathForIssueCode(code) };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// src/shared/errors/wrap.ts
|
|
255
|
+
function rethrowAsI18n(err, message) {
|
|
256
|
+
if (err instanceof I18nPruneError) throw err;
|
|
257
|
+
throw normalizeUnknownError(err, { when: message, defaultCode: "INTERNAL" });
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/shared/json/parse.ts
|
|
261
|
+
var I18nPruneJsonParseError = class extends I18nPruneError {
|
|
262
|
+
filePath;
|
|
263
|
+
line;
|
|
264
|
+
column;
|
|
265
|
+
offset;
|
|
266
|
+
constructor(input) {
|
|
267
|
+
const options = input.issueCode !== void 0 ? { cause: input.cause, issueCode: input.issueCode } : { cause: input.cause };
|
|
268
|
+
super(input.message, input.code, options);
|
|
269
|
+
this.name = "I18nPruneJsonParseError";
|
|
270
|
+
this.filePath = input.filePath;
|
|
271
|
+
this.line = input.location.line;
|
|
272
|
+
this.column = input.location.column;
|
|
273
|
+
this.offset = input.location.offset;
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
function locationFromOffset(text, offset) {
|
|
277
|
+
let line = 1;
|
|
278
|
+
let column = 1;
|
|
279
|
+
const capped = Math.max(0, Math.min(offset, text.length));
|
|
280
|
+
for (let i = 0; i < capped; i += 1) {
|
|
281
|
+
if (text.charCodeAt(i) === 10) {
|
|
282
|
+
line += 1;
|
|
283
|
+
column = 1;
|
|
284
|
+
} else {
|
|
285
|
+
column += 1;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return { line, column, offset };
|
|
289
|
+
}
|
|
290
|
+
function getJsonParseLocation(error, text) {
|
|
291
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
292
|
+
const positionMatch = /\bposition\s+(\d+)\b/i.exec(message);
|
|
293
|
+
if (positionMatch?.[1]) {
|
|
294
|
+
return locationFromOffset(text, Number.parseInt(positionMatch[1], 10));
|
|
295
|
+
}
|
|
296
|
+
const lineColumnMatch = /\bline\s+(\d+)\s+column\s+(\d+)\b/i.exec(message);
|
|
297
|
+
if (lineColumnMatch?.[1] && lineColumnMatch[2]) {
|
|
298
|
+
return {
|
|
299
|
+
line: Number.parseInt(lineColumnMatch[1], 10),
|
|
300
|
+
column: Number.parseInt(lineColumnMatch[2], 10)
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
return {};
|
|
304
|
+
}
|
|
305
|
+
function formatJsonParseMessage(filePath, location, cause) {
|
|
306
|
+
const subject = filePath ? `Invalid JSON in ${filePath}` : "Invalid JSON";
|
|
307
|
+
const at = location.line !== void 0 && location.column !== void 0 ? ` at line ${String(location.line)}, column ${String(location.column)}` : location.offset !== void 0 ? ` at offset ${String(location.offset)}` : "";
|
|
308
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
309
|
+
return `${subject}${at}: ${detail}`;
|
|
310
|
+
}
|
|
311
|
+
function parseJsonText(text, options = {}) {
|
|
312
|
+
try {
|
|
313
|
+
return JSON.parse(text);
|
|
314
|
+
} catch (cause) {
|
|
315
|
+
const location = getJsonParseLocation(cause, text);
|
|
316
|
+
throw new I18nPruneJsonParseError({
|
|
317
|
+
message: formatJsonParseMessage(options.filePath, location, cause),
|
|
318
|
+
code: options.code ?? "IO",
|
|
319
|
+
cause,
|
|
320
|
+
location,
|
|
321
|
+
...options.issueCode !== void 0 ? { issueCode: options.issueCode } : {},
|
|
322
|
+
...options.filePath !== void 0 ? { filePath: options.filePath } : {}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function tryParseJsonText(text, options = {}) {
|
|
327
|
+
try {
|
|
328
|
+
return { ok: true, data: parseJsonText(text, options) };
|
|
329
|
+
} catch (error) {
|
|
330
|
+
if (error instanceof I18nPruneJsonParseError) return { ok: false, error };
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// src/shared/locales/leaves/index.ts
|
|
336
|
+
var leaves_exports = {};
|
|
337
|
+
__export(leaves_exports, {
|
|
338
|
+
applyLocaleLeafMode: () => applyLocaleLeafMode,
|
|
339
|
+
applyLocaleLeafNormalization: () => applyLocaleLeafNormalization,
|
|
340
|
+
collectTranslationSurfaceLeaves: () => collectTranslationSurfaceLeaves,
|
|
341
|
+
isCompleteStructuredLocaleLeafMeta: () => isCompleteStructuredLocaleLeafMeta,
|
|
342
|
+
isStructuredLocaleLeafNode: () => isStructuredLocaleLeafNode,
|
|
343
|
+
localeSegmentSourceForFile: () => localeSegmentSourceForFile,
|
|
344
|
+
metadataModeEnabledFromConfig: () => metadataModeEnabledFromConfig,
|
|
345
|
+
resolveLocaleLeafMode: () => resolveLocaleLeafMode
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// src/shared/json/localeLeafPath.ts
|
|
349
|
+
function isPlainObject2(x) {
|
|
350
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
351
|
+
}
|
|
352
|
+
function isLiteralDottedObjectKey(key) {
|
|
353
|
+
return key.includes(".");
|
|
354
|
+
}
|
|
355
|
+
function getLocaleLeafAtPath(root, pathStr) {
|
|
356
|
+
if (isPlainObject2(root) && Object.prototype.hasOwnProperty.call(root, pathStr)) {
|
|
357
|
+
return root[pathStr];
|
|
358
|
+
}
|
|
359
|
+
return getAtPath(root, pathStr);
|
|
360
|
+
}
|
|
361
|
+
function deleteLocaleLeafAtPath(root, pathStr) {
|
|
362
|
+
if (isPlainObject2(root) && Object.prototype.hasOwnProperty.call(root, pathStr)) {
|
|
363
|
+
const clone = deepClone(root);
|
|
364
|
+
delete clone[pathStr];
|
|
365
|
+
return clone;
|
|
366
|
+
}
|
|
367
|
+
return deleteAtPath(root, pathStr);
|
|
368
|
+
}
|
|
369
|
+
function stripLiteralDottedKeysAtLevel(root) {
|
|
370
|
+
if (!isPlainObject2(root)) {
|
|
371
|
+
if (Array.isArray(root)) return root.map((item) => stripLiteralDottedKeysAtLevel(item));
|
|
372
|
+
return root;
|
|
373
|
+
}
|
|
374
|
+
const out = {};
|
|
375
|
+
for (const [key, value] of Object.entries(root)) {
|
|
376
|
+
if (isLiteralDottedObjectKey(key)) continue;
|
|
377
|
+
out[key] = stripLiteralDottedKeysAtLevel(value);
|
|
378
|
+
}
|
|
379
|
+
return out;
|
|
380
|
+
}
|
|
381
|
+
function normalizeLocaleDocumentToNestedCanonical(root, knownLeafPaths) {
|
|
382
|
+
if (Array.isArray(root)) {
|
|
383
|
+
return root.map((item) => normalizeLocaleDocumentToNestedCanonical(item, knownLeafPaths));
|
|
384
|
+
}
|
|
385
|
+
if (!isPlainObject2(root)) return root;
|
|
386
|
+
const preservedNested = {};
|
|
387
|
+
const dottedAssignments = [];
|
|
388
|
+
for (const [key, value] of Object.entries(root)) {
|
|
389
|
+
if (isLiteralDottedObjectKey(key)) {
|
|
390
|
+
dottedAssignments.push({ path: key, value });
|
|
391
|
+
} else {
|
|
392
|
+
preservedNested[key] = normalizeLocaleDocumentToNestedCanonical(value, knownLeafPaths);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
let result = preservedNested;
|
|
396
|
+
for (const { path, value } of dottedAssignments) {
|
|
397
|
+
result = setAtPath(result, path, deepClone(value));
|
|
398
|
+
}
|
|
399
|
+
if (knownLeafPaths) {
|
|
400
|
+
for (const leafPath of knownLeafPaths) {
|
|
401
|
+
if (isLiteralDottedObjectKey(leafPath) && isPlainObject2(result) && Object.prototype.hasOwnProperty.call(result, leafPath)) {
|
|
402
|
+
result = deleteLocaleLeafAtPath(result, leafPath);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return stripLiteralDottedKeysAtLevel(result);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/shared/locales/leaves/mode/applyModeHelpers.ts
|
|
410
|
+
function isPlainObjectForLocaleLeaves(x) {
|
|
411
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
412
|
+
}
|
|
413
|
+
function bump(m, key) {
|
|
414
|
+
m[key] = (m[key] ?? 0) + 1;
|
|
415
|
+
}
|
|
416
|
+
function initReasonMap() {
|
|
417
|
+
return {
|
|
418
|
+
legacy_string_promoted: 0,
|
|
419
|
+
non_object_replaced: 0,
|
|
420
|
+
missing_value: 0,
|
|
421
|
+
invalid_status: 0,
|
|
422
|
+
invalid_confidence: 0,
|
|
423
|
+
invalid_needs_review: 0,
|
|
424
|
+
invalid_needs_translation_again: 0,
|
|
425
|
+
invalid_source: 0,
|
|
426
|
+
canonical_metadata_materialized: 0
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
var MATERIALIZED_STRUCTURED_KEYS = [
|
|
430
|
+
"value",
|
|
431
|
+
"status",
|
|
432
|
+
"confidence",
|
|
433
|
+
"needsReview",
|
|
434
|
+
"source",
|
|
435
|
+
"needsTranslationAgain"
|
|
436
|
+
];
|
|
437
|
+
function shouldMaterializeCanonicalStructuredFields(cur) {
|
|
438
|
+
for (const k of MATERIALIZED_STRUCTURED_KEYS) {
|
|
439
|
+
if (!(k in cur)) return true;
|
|
440
|
+
}
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
function classifyLeafRuntimeKind(cur) {
|
|
444
|
+
if (typeof cur === "undefined") return "missing";
|
|
445
|
+
if (typeof cur === "string") return "legacy_string";
|
|
446
|
+
if (!isPlainObjectForLocaleLeaves(cur)) return "other";
|
|
447
|
+
if (typeof cur.value === "string") {
|
|
448
|
+
const validStatus = cur.status === void 0 || typeof cur.status === "string" && cur.status.trim().length > 0;
|
|
449
|
+
const validConfidence = cur.confidence === void 0 || cur.confidence === null || typeof cur.confidence === "number" && Number.isFinite(cur.confidence);
|
|
450
|
+
const validNeedsReview = cur.needsReview === void 0 || typeof cur.needsReview === "boolean";
|
|
451
|
+
const validNeedsTranslationAgain = cur.needsTranslationAgain === void 0 || typeof cur.needsTranslationAgain === "boolean";
|
|
452
|
+
const validSource = cur.source === void 0 || typeof cur.source === "string" && cur.source.trim().length > 0;
|
|
453
|
+
return validStatus && validConfidence && validNeedsReview && validNeedsTranslationAgain && validSource ? "structured_valid" : "structured_corrupt";
|
|
454
|
+
}
|
|
455
|
+
return "structured_corrupt";
|
|
456
|
+
}
|
|
457
|
+
function normalizeStructuredLeaf(cur, sourceValue) {
|
|
458
|
+
const roundConfidence = (v) => Math.round(Math.max(0, Math.min(1, v)) * 100) / 100;
|
|
459
|
+
const reasons = [];
|
|
460
|
+
if (typeof cur === "string") {
|
|
461
|
+
reasons.push("legacy_string_promoted");
|
|
462
|
+
return {
|
|
463
|
+
leaf: {
|
|
464
|
+
value: cur,
|
|
465
|
+
status: "translated",
|
|
466
|
+
confidence: null,
|
|
467
|
+
needsReview: true,
|
|
468
|
+
needsTranslationAgain: false,
|
|
469
|
+
source: "manual"
|
|
470
|
+
},
|
|
471
|
+
changed: true,
|
|
472
|
+
reasons
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
if (!isPlainObjectForLocaleLeaves(cur)) {
|
|
476
|
+
reasons.push("non_object_replaced");
|
|
477
|
+
return {
|
|
478
|
+
leaf: {
|
|
479
|
+
value: sourceValue,
|
|
480
|
+
status: "pending",
|
|
481
|
+
confidence: null,
|
|
482
|
+
needsReview: true,
|
|
483
|
+
needsTranslationAgain: true,
|
|
484
|
+
source: "sync"
|
|
485
|
+
},
|
|
486
|
+
changed: true,
|
|
487
|
+
reasons
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
let changed = false;
|
|
491
|
+
const out = { value: sourceValue };
|
|
492
|
+
if (typeof cur.value === "string") out.value = cur.value;
|
|
493
|
+
else {
|
|
494
|
+
changed = true;
|
|
495
|
+
reasons.push("missing_value");
|
|
496
|
+
}
|
|
497
|
+
if (typeof cur.status === "string" && cur.status.trim().length > 0) {
|
|
498
|
+
out.status = cur.status;
|
|
499
|
+
} else if (cur.status === void 0) {
|
|
500
|
+
out.status = "translated";
|
|
501
|
+
} else {
|
|
502
|
+
out.status = "translated";
|
|
503
|
+
changed = true;
|
|
504
|
+
reasons.push("invalid_status");
|
|
505
|
+
}
|
|
506
|
+
if (typeof cur.confidence === "number" && Number.isFinite(cur.confidence)) out.confidence = roundConfidence(cur.confidence);
|
|
507
|
+
else if (cur.confidence === null || cur.confidence === void 0) out.confidence = null;
|
|
508
|
+
else {
|
|
509
|
+
out.confidence = null;
|
|
510
|
+
changed = true;
|
|
511
|
+
reasons.push("invalid_confidence");
|
|
512
|
+
}
|
|
513
|
+
if (typeof cur.needsReview === "boolean") {
|
|
514
|
+
out.needsReview = cur.needsReview;
|
|
515
|
+
} else if (cur.needsReview === void 0) {
|
|
516
|
+
out.needsReview = false;
|
|
517
|
+
} else {
|
|
518
|
+
out.needsReview = false;
|
|
519
|
+
changed = true;
|
|
520
|
+
reasons.push("invalid_needs_review");
|
|
521
|
+
}
|
|
522
|
+
if (typeof cur.source === "string" && cur.source.trim().length > 0) {
|
|
523
|
+
out.source = cur.source;
|
|
524
|
+
} else if (cur.source === void 0) {
|
|
525
|
+
out.source = "manual";
|
|
526
|
+
} else {
|
|
527
|
+
out.source = "manual";
|
|
528
|
+
changed = true;
|
|
529
|
+
reasons.push("invalid_source");
|
|
530
|
+
}
|
|
531
|
+
if (typeof cur.needsTranslationAgain === "boolean") out.needsTranslationAgain = cur.needsTranslationAgain;
|
|
532
|
+
else if ("needsTranslationAgain" in cur) {
|
|
533
|
+
out.needsTranslationAgain = false;
|
|
534
|
+
changed = true;
|
|
535
|
+
reasons.push("invalid_needs_translation_again");
|
|
536
|
+
} else {
|
|
537
|
+
out.needsTranslationAgain = false;
|
|
538
|
+
}
|
|
539
|
+
const materialized = isPlainObjectForLocaleLeaves(cur) && typeof cur.value === "string" && shouldMaterializeCanonicalStructuredFields(cur);
|
|
540
|
+
if (materialized && !changed) reasons.push("canonical_metadata_materialized");
|
|
541
|
+
const effectiveChanged = changed || materialized;
|
|
542
|
+
if (changed) {
|
|
543
|
+
out.needsReview = true;
|
|
544
|
+
}
|
|
545
|
+
return { leaf: out, changed: effectiveChanged, reasons };
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// src/shared/locales/leaves/mode/applyLocaleLeafMode.ts
|
|
549
|
+
function applyLocaleLeafMode(input) {
|
|
550
|
+
const changes = [];
|
|
551
|
+
const leafDecisions = [];
|
|
552
|
+
let next = input.localeJson;
|
|
553
|
+
let unchangedLeaves = 0;
|
|
554
|
+
let structuredLeavesWritten = 0;
|
|
555
|
+
let promotedLegacyLeaves = 0;
|
|
556
|
+
let repairedCorruptLeaves = 0;
|
|
557
|
+
let strippedStructuredLeaves = 0;
|
|
558
|
+
let missingPathsHydratedFromSource = 0;
|
|
559
|
+
const byReason = initReasonMap();
|
|
560
|
+
const sampleLimit = input.sampleLimit ?? 40;
|
|
561
|
+
for (const [leafPath, sourceValue] of input.sourceMap.entries()) {
|
|
562
|
+
const cur = getLocaleLeafAtPath(next, leafPath);
|
|
563
|
+
const beforeKind = classifyLeafRuntimeKind(cur);
|
|
564
|
+
const beforeValue = cur;
|
|
565
|
+
if (input.mode === "legacy_string") {
|
|
566
|
+
const nextValue = typeof cur === "string" ? cur : isPlainObjectForLocaleLeaves(cur) && typeof cur.value === "string" ? cur.value : sourceValue;
|
|
567
|
+
let action2 = "unchanged";
|
|
568
|
+
const reasons = [];
|
|
569
|
+
if (typeof cur === "undefined") {
|
|
570
|
+
missingPathsHydratedFromSource += 1;
|
|
571
|
+
action2 = "hydrated_missing";
|
|
572
|
+
}
|
|
573
|
+
if (isPlainObjectForLocaleLeaves(cur) && typeof cur.value === "string") {
|
|
574
|
+
strippedStructuredLeaves += 1;
|
|
575
|
+
action2 = "stripped_structured";
|
|
576
|
+
}
|
|
577
|
+
if (cur === nextValue) unchangedLeaves += 1;
|
|
578
|
+
else next = setAtPath(next, leafPath, nextValue);
|
|
579
|
+
const afterValue2 = getLocaleLeafAtPath(next, leafPath);
|
|
580
|
+
const afterKind2 = classifyLeafRuntimeKind(afterValue2);
|
|
581
|
+
leafDecisions.push({
|
|
582
|
+
path: leafPath,
|
|
583
|
+
sourceValue,
|
|
584
|
+
beforeKind,
|
|
585
|
+
afterKind: afterKind2,
|
|
586
|
+
action: action2,
|
|
587
|
+
reasons,
|
|
588
|
+
beforeValue,
|
|
589
|
+
afterValue: afterValue2
|
|
590
|
+
});
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
const normalized = normalizeStructuredLeaf(cur, sourceValue);
|
|
594
|
+
let action = "unchanged";
|
|
595
|
+
if (normalized.changed) {
|
|
596
|
+
next = setAtPath(next, leafPath, normalized.leaf);
|
|
597
|
+
structuredLeavesWritten += 1;
|
|
598
|
+
for (const reason of normalized.reasons) {
|
|
599
|
+
bump(byReason, reason);
|
|
600
|
+
if (changes.length < sampleLimit) changes.push({ path: leafPath, reason });
|
|
601
|
+
}
|
|
602
|
+
const hasLegacy = normalized.reasons.includes("legacy_string_promoted");
|
|
603
|
+
const hasCorruptRepair = normalized.reasons.some(
|
|
604
|
+
(r) => r !== "legacy_string_promoted" && r !== "canonical_metadata_materialized"
|
|
605
|
+
);
|
|
606
|
+
if (hasLegacy) {
|
|
607
|
+
promotedLegacyLeaves += 1;
|
|
608
|
+
action = "promoted_legacy";
|
|
609
|
+
}
|
|
610
|
+
if (hasCorruptRepair) {
|
|
611
|
+
repairedCorruptLeaves += 1;
|
|
612
|
+
if (!hasLegacy) action = "repaired_corrupt";
|
|
613
|
+
}
|
|
614
|
+
} else {
|
|
615
|
+
unchangedLeaves += 1;
|
|
616
|
+
}
|
|
617
|
+
if (typeof cur === "undefined") missingPathsHydratedFromSource += 1;
|
|
618
|
+
const afterValue = getLocaleLeafAtPath(next, leafPath);
|
|
619
|
+
const afterKind = classifyLeafRuntimeKind(afterValue);
|
|
620
|
+
leafDecisions.push({
|
|
621
|
+
path: leafPath,
|
|
622
|
+
sourceValue,
|
|
623
|
+
beforeKind,
|
|
624
|
+
afterKind,
|
|
625
|
+
action,
|
|
626
|
+
reasons: normalized.reasons,
|
|
627
|
+
beforeValue,
|
|
628
|
+
afterValue
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
const leafPaths = [...input.sourceMap.keys()];
|
|
632
|
+
next = normalizeLocaleDocumentToNestedCanonical(next, leafPaths);
|
|
633
|
+
return {
|
|
634
|
+
next,
|
|
635
|
+
report: {
|
|
636
|
+
mode: input.mode,
|
|
637
|
+
totalSourceLeafPaths: input.sourceMap.size,
|
|
638
|
+
unchangedLeaves,
|
|
639
|
+
structuredLeavesWritten,
|
|
640
|
+
promotedLegacyLeaves,
|
|
641
|
+
repairedCorruptLeaves,
|
|
642
|
+
strippedStructuredLeaves,
|
|
643
|
+
missingPathsHydratedFromSource,
|
|
644
|
+
byReason,
|
|
645
|
+
changedPathsSample: changes,
|
|
646
|
+
leafDecisions
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// src/shared/locales/leaves/mode/modeResolve.ts
|
|
652
|
+
function metadataModeEnabledFromConfig(mode) {
|
|
653
|
+
return mode === "structured";
|
|
654
|
+
}
|
|
655
|
+
function resolveLocaleLeafMode(input) {
|
|
656
|
+
if (input.stripMetadataFlag === true) {
|
|
657
|
+
return {
|
|
658
|
+
mode: "legacy_string",
|
|
659
|
+
conflict: input.metadataFlag === true,
|
|
660
|
+
reason: "strip_precedence"
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
if (input.metadataFlag === true) return { mode: "structured", conflict: false, reason: "explicit_metadata" };
|
|
664
|
+
if (metadataModeEnabledFromConfig(input.configMode)) {
|
|
665
|
+
return { mode: "structured", conflict: false, reason: "config_structured" };
|
|
666
|
+
}
|
|
667
|
+
return { mode: "legacy_string", conflict: false, reason: "default_legacy" };
|
|
668
|
+
}
|
|
669
|
+
function applyLocaleLeafNormalization(input) {
|
|
670
|
+
const modeDecision = resolveLocaleLeafMode(input.resolveInput);
|
|
671
|
+
const normalized = applyLocaleLeafMode({
|
|
672
|
+
localeJson: input.localeJson,
|
|
673
|
+
sourceMap: input.sourceMap,
|
|
674
|
+
mode: modeDecision.mode
|
|
675
|
+
});
|
|
676
|
+
return {
|
|
677
|
+
next: normalized.next,
|
|
678
|
+
report: normalized.report,
|
|
679
|
+
modeDecision
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// src/shared/locales/enumerate/parseSegmentLocale.ts
|
|
684
|
+
function localeCodeForSegment(structure, path, segment) {
|
|
685
|
+
if (structure === "locale_file") {
|
|
686
|
+
if (segment.relativePath.includes("/")) return null;
|
|
687
|
+
return path.basename(segment.absolutePath, ".json");
|
|
688
|
+
}
|
|
689
|
+
if (structure === "locale_per_dir") {
|
|
690
|
+
const slash = segment.relativePath.indexOf("/");
|
|
691
|
+
if (slash < 0) return null;
|
|
692
|
+
const locale = segment.relativePath.slice(0, slash);
|
|
693
|
+
return locale.length > 0 ? locale : null;
|
|
694
|
+
}
|
|
695
|
+
if (structure === "feature_bundle") {
|
|
696
|
+
return path.basename(segment.absolutePath, ".json");
|
|
697
|
+
}
|
|
698
|
+
return null;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// src/shared/locales/leaves/segmentSource/localeSegmentSourceForFile.ts
|
|
702
|
+
function localeSegmentSourceForFile(input) {
|
|
703
|
+
const { path, absoluteFile, localesDir, structure } = input;
|
|
704
|
+
let relativePath = path.relative(localesDir, absoluteFile);
|
|
705
|
+
if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
|
|
706
|
+
relativePath = path.basename(absoluteFile);
|
|
707
|
+
}
|
|
708
|
+
relativePath = relativePath.replace(/\\/g, "/");
|
|
709
|
+
const locale = localeCodeForSegment(structure, path, { absolutePath: absoluteFile, relativePath });
|
|
710
|
+
if (locale === null) return null;
|
|
711
|
+
return { file: absoluteFile, locale, relativePath };
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// src/shared/locales/leaves/walk/translationSurfaceWalk.ts
|
|
715
|
+
function isPlainObject3(x) {
|
|
716
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
717
|
+
}
|
|
718
|
+
function isStructuredLocaleLeafNode(x) {
|
|
719
|
+
return isPlainObject3(x) && typeof x.value === "string";
|
|
720
|
+
}
|
|
721
|
+
function readOptionalStatus(o) {
|
|
722
|
+
const s = o.status;
|
|
723
|
+
if (typeof s !== "string" || !s.trim()) return void 0;
|
|
724
|
+
return s;
|
|
725
|
+
}
|
|
726
|
+
function readOptionalLeafSource(o) {
|
|
727
|
+
const s = o.source;
|
|
728
|
+
if (typeof s !== "string" || !s.trim()) return void 0;
|
|
729
|
+
return s;
|
|
730
|
+
}
|
|
731
|
+
function readConfidence(o) {
|
|
732
|
+
const c = o.confidence;
|
|
733
|
+
if (c === null || c === void 0) return null;
|
|
734
|
+
if (typeof c !== "number" || !Number.isFinite(c)) return null;
|
|
735
|
+
const clamped = Math.max(0, Math.min(1, c));
|
|
736
|
+
return Math.round(clamped * 100) / 100;
|
|
737
|
+
}
|
|
738
|
+
function readNeedsReview(o) {
|
|
739
|
+
if (!("needsReview" in o)) return null;
|
|
740
|
+
return typeof o.needsReview === "boolean" ? o.needsReview : null;
|
|
741
|
+
}
|
|
742
|
+
function readNeedsTranslationAgain(o) {
|
|
743
|
+
if (!("needsTranslationAgain" in o)) return null;
|
|
744
|
+
return typeof o.needsTranslationAgain === "boolean" ? o.needsTranslationAgain : null;
|
|
745
|
+
}
|
|
746
|
+
function isCompleteStructuredLocaleLeafMeta(node) {
|
|
747
|
+
if (!isStructuredLocaleLeafNode(node)) return false;
|
|
748
|
+
const o = node;
|
|
749
|
+
if (typeof o.status !== "string" || !o.status.trim()) return false;
|
|
750
|
+
if (!(o.confidence === null || typeof o.confidence === "number" && Number.isFinite(o.confidence))) return false;
|
|
751
|
+
if (typeof o.needsReview !== "boolean") return false;
|
|
752
|
+
if (typeof o.needsTranslationAgain !== "boolean") return false;
|
|
753
|
+
if (typeof o.source !== "string" || !o.source.trim()) return false;
|
|
754
|
+
return true;
|
|
755
|
+
}
|
|
756
|
+
function pushStructuredRow(out, prefix, root, fileOrigin) {
|
|
757
|
+
out.push({
|
|
758
|
+
path: prefix,
|
|
759
|
+
value: root.value,
|
|
760
|
+
shape: "structured",
|
|
761
|
+
status: readOptionalStatus(root),
|
|
762
|
+
confidence: readConfidence(root),
|
|
763
|
+
needsReview: readNeedsReview(root),
|
|
764
|
+
needsTranslationAgain: readNeedsTranslationAgain(root),
|
|
765
|
+
source: readOptionalLeafSource(root),
|
|
766
|
+
structuredMetaComplete: isCompleteStructuredLocaleLeafMeta(root),
|
|
767
|
+
...fileOrigin ? { fileOrigin } : {}
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
function collectTranslationSurfaceLeaves(root, prefix = "", out = [], fileOrigin) {
|
|
771
|
+
if (typeof root === "string") {
|
|
772
|
+
if (prefix) {
|
|
773
|
+
out.push({
|
|
774
|
+
path: prefix,
|
|
775
|
+
value: root,
|
|
776
|
+
shape: "legacy_string",
|
|
777
|
+
confidence: null,
|
|
778
|
+
needsReview: null,
|
|
779
|
+
...fileOrigin ? { fileOrigin } : {}
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
return out;
|
|
783
|
+
}
|
|
784
|
+
if (isStructuredLocaleLeafNode(root)) {
|
|
785
|
+
if (prefix) pushStructuredRow(out, prefix, root, fileOrigin);
|
|
786
|
+
return out;
|
|
787
|
+
}
|
|
788
|
+
if (Array.isArray(root)) {
|
|
789
|
+
root.forEach((item, i) => {
|
|
790
|
+
const p = prefix ? `${prefix}[${i}]` : `[${i}]`;
|
|
791
|
+
collectTranslationSurfaceLeaves(item, p, out, fileOrigin);
|
|
792
|
+
});
|
|
793
|
+
return out;
|
|
794
|
+
}
|
|
795
|
+
if (isPlainObject3(root)) {
|
|
796
|
+
for (const k of Object.keys(root)) {
|
|
797
|
+
const p = prefix ? `${prefix}.${k}` : k;
|
|
798
|
+
collectTranslationSurfaceLeaves(root[k], p, out, fileOrigin);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
return out;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// src/shared/json/targetCoverage.ts
|
|
805
|
+
function targetLocaleCoversAllSourcePaths(sourceRaw, targetRaw) {
|
|
806
|
+
const sLeaves = collectTranslationSurfaceLeaves(sourceRaw);
|
|
807
|
+
return targetLocaleCoversAllSourceLeaves(sLeaves, targetRaw);
|
|
808
|
+
}
|
|
809
|
+
function targetLocaleCoversAllSourceLeaves(sourceLeaves, targetRaw) {
|
|
810
|
+
const tLeaves = collectTranslationSurfaceLeaves(targetRaw);
|
|
811
|
+
const targetSet = new Set(tLeaves.map((l) => l.path));
|
|
812
|
+
return sourceLeaves.every((l) => targetSet.has(l.path));
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// src/shared/reference/paths.ts
|
|
816
|
+
var paths_exports = {};
|
|
817
|
+
__export(paths_exports, {
|
|
818
|
+
pathUnderAnyUncertainPrefix: () => pathUnderAnyUncertainPrefix,
|
|
819
|
+
pathUnderUncertainPrefix: () => pathUnderUncertainPrefix
|
|
820
|
+
});
|
|
821
|
+
function pathUnderUncertainPrefix(keyPath, prefix) {
|
|
822
|
+
if (keyPath === prefix) return true;
|
|
823
|
+
if (keyPath.startsWith(`${prefix}.`)) return true;
|
|
824
|
+
if (keyPath.startsWith(`${prefix}[`)) return true;
|
|
825
|
+
return false;
|
|
826
|
+
}
|
|
827
|
+
function pathUnderAnyUncertainPrefix(keyPath, prefixes) {
|
|
828
|
+
for (const p of prefixes) {
|
|
829
|
+
if (pathUnderUncertainPrefix(keyPath, p)) return true;
|
|
830
|
+
}
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// src/shared/json/merge.ts
|
|
835
|
+
function isPlainObject4(x) {
|
|
836
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
837
|
+
}
|
|
838
|
+
var OMIT = /* @__PURE__ */ Symbol("i18nprune.merge.omit");
|
|
839
|
+
function mergeToTemplateShape(template, target, preserve, options) {
|
|
840
|
+
return mergeWalk(
|
|
841
|
+
template,
|
|
842
|
+
target,
|
|
843
|
+
preserve,
|
|
844
|
+
"",
|
|
845
|
+
options?.uncertainKeepPrefixes,
|
|
846
|
+
options?.skipFillPaths === void 0 ? void 0 : new Set(options.skipFillPaths),
|
|
847
|
+
options?.forceFillPaths === void 0 ? void 0 : new Set(options.forceFillPaths)
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
function mergeWalk(template, target, preserve, path, uncertainKeepPrefixes, skipFillPaths, forceFillPaths) {
|
|
851
|
+
if (typeof template === "string") {
|
|
852
|
+
if (skipFillPaths?.has(path)) return OMIT;
|
|
853
|
+
if (forceFillPaths?.has(path)) return template;
|
|
854
|
+
if (typeof target === "string") return target;
|
|
855
|
+
if (isPlainObject4(target) && typeof target.value === "string") {
|
|
856
|
+
return deepClone(target);
|
|
857
|
+
}
|
|
858
|
+
return template;
|
|
859
|
+
}
|
|
860
|
+
if (Array.isArray(template)) {
|
|
861
|
+
if (!Array.isArray(target)) target = [];
|
|
862
|
+
const out = [];
|
|
863
|
+
const tArr = target;
|
|
864
|
+
for (let i = 0; i < template.length; i += 1) {
|
|
865
|
+
const seg = path ? `${path}[${String(i)}]` : `[${String(i)}]`;
|
|
866
|
+
const next = mergeWalk(template[i], tArr[i], preserve, seg, uncertainKeepPrefixes, skipFillPaths, forceFillPaths);
|
|
867
|
+
if (next !== OMIT) out.push(next);
|
|
868
|
+
}
|
|
869
|
+
return out;
|
|
870
|
+
}
|
|
871
|
+
if (isPlainObject4(template)) {
|
|
872
|
+
const tObj = isPlainObject4(target) ? target : {};
|
|
873
|
+
const out = {};
|
|
874
|
+
for (const k of Object.keys(template)) {
|
|
875
|
+
const p = path ? `${path}.${k}` : k;
|
|
876
|
+
const next = mergeWalk(template[k], tObj[k], preserve, p, uncertainKeepPrefixes, skipFillPaths, forceFillPaths);
|
|
877
|
+
if (next !== OMIT) out[k] = next;
|
|
878
|
+
}
|
|
879
|
+
if (uncertainKeepPrefixes?.length) {
|
|
880
|
+
for (const k of Object.keys(tObj)) {
|
|
881
|
+
if (k in template) continue;
|
|
882
|
+
const p = path ? `${path}.${k}` : k;
|
|
883
|
+
if (pathUnderAnyUncertainPrefix(p, uncertainKeepPrefixes)) {
|
|
884
|
+
out[k] = deepClone(tObj[k]);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return out;
|
|
889
|
+
}
|
|
890
|
+
return deepClone(template);
|
|
891
|
+
}
|
|
892
|
+
function applyPreserveFromSource(target, source, paths) {
|
|
893
|
+
let out = deepClone(target);
|
|
894
|
+
for (const p of paths) {
|
|
895
|
+
const v = getAtPath(source, p);
|
|
896
|
+
if (v !== void 0) {
|
|
897
|
+
out = setAtPath(out, p, deepClone(v));
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
return out;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// src/shared/json/prune.ts
|
|
904
|
+
function isPlainObject5(x) {
|
|
905
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
906
|
+
}
|
|
907
|
+
function pruneToTemplateShape(template, target, options) {
|
|
908
|
+
return pruneWalk(template, target, "", options?.uncertainKeepPrefixes);
|
|
909
|
+
}
|
|
910
|
+
function pruneWalk(template, target, path, uncertainKeepPrefixes) {
|
|
911
|
+
if (template === null || typeof template !== "object") {
|
|
912
|
+
return target;
|
|
913
|
+
}
|
|
914
|
+
if (Array.isArray(template)) {
|
|
915
|
+
if (!Array.isArray(target)) return [];
|
|
916
|
+
const len = Math.min(template.length, target.length);
|
|
917
|
+
const out2 = [];
|
|
918
|
+
for (let i = 0; i < len; i += 1) {
|
|
919
|
+
const seg = path ? `${path}[${String(i)}]` : `[${String(i)}]`;
|
|
920
|
+
out2.push(pruneWalk(template[i], target[i], seg, uncertainKeepPrefixes));
|
|
921
|
+
}
|
|
922
|
+
return out2;
|
|
923
|
+
}
|
|
924
|
+
if (!isPlainObject5(template)) return target;
|
|
925
|
+
if (!isPlainObject5(target)) return {};
|
|
926
|
+
const out = {};
|
|
927
|
+
for (const k of Object.keys(template)) {
|
|
928
|
+
if (k in target) {
|
|
929
|
+
const p = path ? `${path}.${k}` : k;
|
|
930
|
+
out[k] = pruneWalk(template[k], target[k], p, uncertainKeepPrefixes);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
if (uncertainKeepPrefixes?.length) {
|
|
934
|
+
for (const k of Object.keys(target)) {
|
|
935
|
+
if (k in template) continue;
|
|
936
|
+
const p = path ? `${path}.${k}` : k;
|
|
937
|
+
if (pathUnderAnyUncertainPrefix(p, uncertainKeepPrefixes)) {
|
|
938
|
+
out[k] = deepClone(target[k]);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
return out;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// src/shared/scanner/index.ts
|
|
946
|
+
var scanner_exports = {};
|
|
947
|
+
__export(scanner_exports, {
|
|
948
|
+
scanSources: () => scanSources
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
// src/runtime/helpers/sync/assert.ts
|
|
952
|
+
function isThenable(value) {
|
|
953
|
+
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
954
|
+
}
|
|
955
|
+
function assertSyncPortResult(value, label, at) {
|
|
956
|
+
if (isThenable(value)) {
|
|
957
|
+
throw new I18nPruneError(
|
|
958
|
+
`Synchronous ${label} requires a plain value (got a Promise at ${at})`,
|
|
959
|
+
"USAGE"
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
return value;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// src/runtime/helpers/sync/fs.ts
|
|
966
|
+
function readRuntimeFsTextSync(filePath, fs) {
|
|
967
|
+
return assertSyncPortResult(fs.readText(filePath), "fs.readText", filePath);
|
|
968
|
+
}
|
|
969
|
+
function existsRuntimeFsSync(filePath, fs) {
|
|
970
|
+
return assertSyncPortResult(fs.exists(filePath), "fs.exists", filePath);
|
|
971
|
+
}
|
|
972
|
+
function listRuntimeFsDirSync(dirPath, fs) {
|
|
973
|
+
return assertSyncPortResult(fs.listDir(dirPath), "fs.listDir", dirPath);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// src/shared/constants/issueCodes.ts
|
|
977
|
+
var ISSUE_CONTEXT_DISCOVERY_WARNING = "i18nprune.context.discovery_warning";
|
|
978
|
+
var ISSUE_CONTEXT_RESOLUTION_FAILED = "i18nprune.context.resolution_failed";
|
|
979
|
+
var ISSUE_VALIDATE_MISSING_LITERAL_KEYS = "i18nprune.validate.missing_literal_keys";
|
|
980
|
+
var ISSUE_VALIDATE_DYNAMIC_KEY_SITES = "i18nprune.validate.dynamic_key_sites";
|
|
981
|
+
var ISSUE_VALIDATE_SOURCE_LOCALE_READ_FAILED = "i18nprune.validate.source_locale_unreadable";
|
|
982
|
+
var ISSUE_PROJECT_CONFIG_FILE_MISSING = "i18nprune.project.config_file_missing";
|
|
983
|
+
var ISSUE_PROJECT_SOURCE_LOCALE_UNAVAILABLE = "i18nprune.project.source_locale_unavailable";
|
|
984
|
+
var ISSUE_PROJECT_LOCALES_DIR_UNAVAILABLE = "i18nprune.project.locales_dir_unavailable";
|
|
985
|
+
var ISSUE_PROJECT_SRC_ROOT_UNAVAILABLE = "i18nprune.project.src_root_unavailable";
|
|
986
|
+
var ISSUE_PROJECT_LOCALES_STRUCTURE_REQUIRED = "i18nprune.project.locales_structure_required";
|
|
987
|
+
var ISSUE_PROJECT_LOCALES_SOURCE_NOT_LANGUAGE_CODE = "i18nprune.project.locales_source_not_language_code";
|
|
988
|
+
var ISSUE_PROJECT_LOCALES_SOURCE_NOT_IN_BUNDLE = "i18nprune.project.locales_source_not_in_bundle";
|
|
989
|
+
var ISSUE_PROJECT_SOURCE_LOCALE_MISSING_SEGMENTS = "i18nprune.project.source_locale_missing_segments";
|
|
990
|
+
var ISSUE_SCAN_DYNAMIC_KEY_SITES = "i18nprune.scan.dynamic_key_sites";
|
|
991
|
+
var ISSUE_MISSING_PATHS_NOT_IN_SCAN = "i18nprune.missing.paths_not_in_current_scan";
|
|
992
|
+
var ISSUE_SYNC_LOCALE_FILE_NOT_FOUND = "i18nprune.sync.locale_file_not_found";
|
|
993
|
+
var ISSUE_SYNC_METADATA_FLAG_CONFLICT = "i18nprune.sync.metadata_flag_conflict";
|
|
994
|
+
var ISSUE_LOCALE_SOURCE_PLACEHOLDER_LEAVES = "i18nprune.locale.source_placeholder_leaves";
|
|
995
|
+
var ISSUE_LOCALE_TARGET_PLACEHOLDER_LEAVES = "i18nprune.locale.target_placeholder_leaves";
|
|
996
|
+
var ISSUE_CLEANUP_UNCERTAIN_PATHS_EXCLUDED = "i18nprune.cleanup.uncertain_paths_excluded";
|
|
997
|
+
var ISSUE_CLEANUP_RIPGREP_UNAVAILABLE = "i18nprune.cleanup.ripgrep_unavailable";
|
|
998
|
+
var ISSUE_QUALITY_ENGLISH_IDENTICAL_LEAVES = "i18nprune.quality.english_identical_leaves";
|
|
999
|
+
var ISSUE_LANGUAGES_EMPTY_FILTER = "i18nprune.languages.empty_filter";
|
|
1000
|
+
var ISSUE_LANGUAGES_UNSUPPORTED_LANGUAGE_CODE = "i18nprune.languages.unsupported_language_code";
|
|
1001
|
+
var ISSUE_CONFIG_MISSING = "i18nprune.config.missing";
|
|
1002
|
+
var ISSUE_CONFIG_INVALID = "i18nprune.config.invalid";
|
|
1003
|
+
var ISSUE_CONFIG_LOAD_FAILED = "i18nprune.config.load_failed";
|
|
1004
|
+
var ISSUE_LOCALES_USAGE = "i18nprune.locales.usage";
|
|
1005
|
+
var ISSUE_LOCALE_TARGET_NOT_FOUND = "i18nprune.locale.target_not_found";
|
|
1006
|
+
var ISSUE_IO_READ_FAILED = "i18nprune.io.read_failed";
|
|
1007
|
+
var ISSUE_TRANSLATE_IDENTITY_STREAK_WARNING = "i18nprune.translate.identity_streak_warning";
|
|
1008
|
+
var ISSUE_TRANSLATE_IDENTITY_STREAK_ABORT = "i18nprune.translate.identity_streak_abort";
|
|
1009
|
+
var ISSUE_TRANSLATE_UNKNOWN_TRANSLATION_PROVIDER = "i18nprune.translate.unknown_translation_provider";
|
|
1010
|
+
var ISSUE_TRANSLATE_PROVIDER_NOT_IMPLEMENTED_YET = "i18nprune.translate.provider_not_implemented_yet";
|
|
1011
|
+
var ISSUE_TRANSLATE_MISSING_CREDENTIALS = "i18nprune.translate.missing_credentials";
|
|
1012
|
+
var ISSUE_TRANSLATE_CONFIG_DEFAULT_APPLIED = "i18nprune.translate.config_default_applied";
|
|
1013
|
+
var ISSUE_TRANSLATE_HANDOFF_NO_ELIGIBLE_PROVIDER = "i18nprune.translate.handoff_no_eligible_provider";
|
|
1014
|
+
var ISSUE_GENERATE_USAGE = "i18nprune.generate.usage";
|
|
1015
|
+
var ISSUE_GENERATE_SOURCE_EMPTY_STRING_LEAVES = "i18nprune.generate.source_empty_string_leaves";
|
|
1016
|
+
var ISSUE_GENERATE_TRANSLATE_RATE_LIMITED = "i18nprune.generate.translate_rate_limited";
|
|
1017
|
+
var ISSUE_GENERATE_TRANSLATE_NETWORK_ERROR = "i18nprune.generate.translate_network_error";
|
|
1018
|
+
var ISSUE_REPORT_INVALID_FORMAT = "i18nprune.report.invalid_format";
|
|
1019
|
+
var ISSUE_CLI_INVALID_JSON_PRETTY = "i18nprune.cli.invalid_json_pretty";
|
|
1020
|
+
var ISSUE_SHARE_JSON_REPAIRED = "i18nprune.share.json_repaired";
|
|
1021
|
+
var ISSUE_SHARE_CACHE_ENTRY_NOT_FOUND = "i18nprune.share.cache_entry_not_found";
|
|
1022
|
+
var ISSUE_SHARE_STALE_CACHE_ROW_REMOVED = "i18nprune.share.stale_cache_row_removed";
|
|
1023
|
+
var ISSUE_SHARE_CACHE_EMPTY = "i18nprune.share.cache_empty";
|
|
1024
|
+
var ISSUE_SHARE_JSON_WRITE_FAILED = "i18nprune.share.json_write_failed";
|
|
1025
|
+
var ISSUE_SHARE_REMOTE_PROJECT_NOT_FOUND = "i18nprune.share.remote_project_not_found";
|
|
1026
|
+
var ISSUE_SHARE_REMOTE_REPORT_NOT_FOUND = "i18nprune.share.remote_report_not_found";
|
|
1027
|
+
var ISSUE_SHARE_REMOTE_PAYLOAD_TOO_LARGE = "i18nprune.share.remote_payload_too_large";
|
|
1028
|
+
var ISSUE_SHARE_REMOTE_REPORT_REJECTED = "i18nprune.share.remote_report_rejected";
|
|
1029
|
+
var ISSUE_SHARE_REMOTE_UPLOAD_REJECTED = "i18nprune.share.remote_upload_rejected";
|
|
1030
|
+
var ISSUE_SHARE_REMOTE_UNAVAILABLE = "i18nprune.share.remote_unavailable";
|
|
1031
|
+
var ISSUE_SHARE_REMOTE_ERROR = "i18nprune.share.remote_error";
|
|
1032
|
+
var ISSUE_SHARE_SNAPSHOT_EMPTY = "i18nprune.share.snapshot_empty";
|
|
1033
|
+
var ISSUE_SHARE_ZIP_FAILED = "i18nprune.share.zip_failed";
|
|
1034
|
+
var ISSUE_PATCHING_CONFIG_SIZE_ANOMALY = "i18nprune.patching.config_size_anomaly";
|
|
1035
|
+
var ISSUE_PATCHING_CONFIG_TOO_LARGE = "i18nprune.patching.config_too_large";
|
|
1036
|
+
var ISSUE_PATCHING_CONFIG_INVALID_SCHEMA = "i18nprune.patching.config_invalid_schema";
|
|
1037
|
+
var ISSUE_PATCHING_CONFIG_PARSE_FAILED = "i18nprune.patching.config_parse_failed";
|
|
1038
|
+
var ISSUE_PATCHING_CONFIG_LOCALE_MISSING_FILE = "i18nprune.patching.config_locale_missing_file";
|
|
1039
|
+
var ISSUE_PATCHING_FILE_LOCALE_MISSING_CONFIG = "i18nprune.patching.file_locale_missing_config";
|
|
1040
|
+
var ISSUE_PATCHING_CATALOG_MISMATCH_ENGLISH = "i18nprune.patching.catalog_mismatch_english_name";
|
|
1041
|
+
var ISSUE_PATCHING_CATALOG_MISMATCH_NATIVE = "i18nprune.patching.catalog_mismatch_native_name";
|
|
1042
|
+
var ISSUE_PATCHING_CATALOG_MISMATCH_DIRECTION = "i18nprune.patching.catalog_mismatch_direction";
|
|
1043
|
+
var ISSUE_PATCHING_CONFIG_SECTION_INCOMPLETE = "i18nprune.patching.config_section_incomplete";
|
|
1044
|
+
var ISSUE_DOCTOR_RUNTIME_UNSUPPORTED_NODE = "i18nprune.doctor.runtime_unsupported_node";
|
|
1045
|
+
var ISSUE_DOCTOR_TOOLS_RG_NOT_ON_PATH = "i18nprune.doctor.tools_rg_not_on_path";
|
|
1046
|
+
var ISSUE_DOCTOR_CONFIG_MISSING_FILE = "i18nprune.doctor.config_missing_file";
|
|
1047
|
+
var ISSUE_DOCTOR_PATHS_SOURCE_LOCALE_MISSING = "i18nprune.doctor.paths_source_locale_missing";
|
|
1048
|
+
var ISSUE_DOCTOR_PATHS_DIRECTORIES_MISSING = "i18nprune.doctor.paths_directories_missing";
|
|
1049
|
+
var ISSUE_PATHS_WINDOWS_RESERVED_NAME = "i18nprune.paths.windows_reserved_name";
|
|
1050
|
+
var ISSUE_PATHS_WINDOWS_LONG_PATH = "i18nprune.paths.windows_long_path";
|
|
1051
|
+
var ISSUE_PATHS_NETWORK_DRIVE = "i18nprune.paths.network_drive";
|
|
1052
|
+
var ISSUE_PROJECT_HOSTED_SNAPSHOT_INVALID = "i18nprune.project.hosted_snapshot_invalid";
|
|
1053
|
+
var ISSUE_PROJECT_HOSTED_SNAPSHOT_SCHEMA_VERSION = "i18nprune.project.hosted_snapshot_schema_version";
|
|
1054
|
+
var ISSUE_PROJECT_UPLOAD_CONFIG_JSON_INVALID = "i18nprune.project.upload_config_json_invalid";
|
|
1055
|
+
var ISSUE_PROJECT_UPLOAD_CONFIG_REQUIRED = "i18nprune.project.upload_config_required";
|
|
1056
|
+
var ISSUE_PROJECT_SOURCE_LOCALE_NOT_FOUND = "i18nprune.project.source_locale_not_found";
|
|
1057
|
+
var ISSUE_PROJECT_SOURCE_LOCALE_INVALID_JSON = "i18nprune.project.source_locale_invalid_json";
|
|
1058
|
+
var ISSUE_PROJECT_SOURCE_LOCALE_INVALID_SHAPE = "i18nprune.project.source_locale_invalid_shape";
|
|
1059
|
+
var ISSUE_REPORT_HOSTED_REPORT_INVALID = "i18nprune.report.hosted_report_invalid";
|
|
1060
|
+
var ISSUE_SHARE_PREPARE_NOTHING_REQUESTED = "i18nprune.share.prepare_nothing_requested";
|
|
1061
|
+
var ISSUE_SHARE_PREPARE_REPORT_HOST_REQUIRED = "i18nprune.share.prepare_report_host_required";
|
|
1062
|
+
var ISSUE_SHARE_PREPARE_ANALYSIS_FAILED = "i18nprune.share.prepare_analysis_failed";
|
|
1063
|
+
var ISSUE_SHARE_PREPARE_REPORT_FROM_ARCHIVE_FAILED = "i18nprune.share.prepare_report_from_archive_failed";
|
|
1064
|
+
|
|
1065
|
+
// src/shared/options/runOptions.ts
|
|
1066
|
+
var run = {
|
|
1067
|
+
json: false,
|
|
1068
|
+
jsonPretty: true,
|
|
1069
|
+
quiet: false,
|
|
1070
|
+
silent: false,
|
|
1071
|
+
debugScan: false,
|
|
1072
|
+
debugCache: false,
|
|
1073
|
+
onScanDebug: void 0
|
|
1074
|
+
};
|
|
1075
|
+
function resetRunOptions() {
|
|
1076
|
+
run = {
|
|
1077
|
+
json: false,
|
|
1078
|
+
jsonPretty: true,
|
|
1079
|
+
quiet: false,
|
|
1080
|
+
silent: false,
|
|
1081
|
+
debugScan: false,
|
|
1082
|
+
debugCache: false,
|
|
1083
|
+
onScanDebug: void 0
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
function setRunOptions(partial) {
|
|
1087
|
+
run = { ...run, ...partial };
|
|
1088
|
+
}
|
|
1089
|
+
function getRunOptions() {
|
|
1090
|
+
return run;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// src/shared/scanner/presets.ts
|
|
1094
|
+
var SCAN_EXCLUDE_PRESETS = {
|
|
1095
|
+
production: {
|
|
1096
|
+
dirs: ["node_modules", "dist", "build", "compiled", "tests", "bench"],
|
|
1097
|
+
files: ["pnpm-lock.yaml", "package-lock.json", "yarn.lock"],
|
|
1098
|
+
extensions: ["test.ts", "test.tsx", "spec.ts", "spec.tsx", "test.js", "test.jsx", "spec.js", "spec.jsx"]
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1101
|
+
function mergeExcludeRules(base, extra) {
|
|
1102
|
+
if (!base && !extra) return void 0;
|
|
1103
|
+
return {
|
|
1104
|
+
useDefaultSkip: base?.useDefaultSkip ?? extra?.useDefaultSkip,
|
|
1105
|
+
dirs: [...extra?.dirs ?? [], ...base?.dirs ?? []],
|
|
1106
|
+
files: [...extra?.files ?? [], ...base?.files ?? []],
|
|
1107
|
+
extensions: [...extra?.extensions ?? [], ...base?.extensions ?? []],
|
|
1108
|
+
patterns: [...extra?.patterns ?? [], ...base?.patterns ?? []]
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
function resolveScanExcludeConfig(exclude) {
|
|
1112
|
+
if (!exclude) return void 0;
|
|
1113
|
+
const fromPreset = exclude.preset ? SCAN_EXCLUDE_PRESETS[exclude.preset] : void 0;
|
|
1114
|
+
return mergeExcludeRules(exclude, fromPreset);
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
// src/shared/scanner/files.ts
|
|
1118
|
+
function resolveScanDebugSink(listOpts) {
|
|
1119
|
+
const g = getRunOptions();
|
|
1120
|
+
if (g.silent) return void 0;
|
|
1121
|
+
return listOpts?.onScanDebug ?? g.onScanDebug;
|
|
1122
|
+
}
|
|
1123
|
+
function emitScanDebug(sink, event) {
|
|
1124
|
+
if (sink) sink(event);
|
|
1125
|
+
}
|
|
1126
|
+
var DEFAULT_SCAN_SKIP_DIR_NAMES = [
|
|
1127
|
+
"node_modules",
|
|
1128
|
+
"dist",
|
|
1129
|
+
"build",
|
|
1130
|
+
".git",
|
|
1131
|
+
"coverage",
|
|
1132
|
+
".next",
|
|
1133
|
+
"out"
|
|
1134
|
+
];
|
|
1135
|
+
var DEFAULT_SCAN_SKIP_DIR_SET = new Set(DEFAULT_SCAN_SKIP_DIR_NAMES);
|
|
1136
|
+
var SOURCE_FILE_NAME = /\.(tsx?|jsx?|mjs|cjs|vue|svelte)$/i;
|
|
1137
|
+
var MAX_SOURCE_TREE_WALK_DEPTH = 48;
|
|
1138
|
+
function walkDirectoryKey(dir, pathPort, fs) {
|
|
1139
|
+
if (fs.realpath) {
|
|
1140
|
+
try {
|
|
1141
|
+
return fs.realpath(dir);
|
|
1142
|
+
} catch {
|
|
1143
|
+
return pathPort.resolve(dir);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
return pathPort.resolve(dir);
|
|
1147
|
+
}
|
|
1148
|
+
function normExtToken(s) {
|
|
1149
|
+
const t = s.trim().toLowerCase();
|
|
1150
|
+
return t.startsWith(".") ? t.slice(1) : t;
|
|
1151
|
+
}
|
|
1152
|
+
function basenameExtensionSuffixes(fileBase) {
|
|
1153
|
+
const parts = fileBase.split(".");
|
|
1154
|
+
if (parts.length < 2) return [];
|
|
1155
|
+
const out = [];
|
|
1156
|
+
for (let i = 1; i < parts.length; i++) {
|
|
1157
|
+
out.push(parts.slice(i).join(".").toLowerCase());
|
|
1158
|
+
}
|
|
1159
|
+
out.sort((a, b) => b.length - a.length);
|
|
1160
|
+
return out;
|
|
1161
|
+
}
|
|
1162
|
+
function relPosix(pathPort, rootDir, absPath) {
|
|
1163
|
+
return pathPort.relative(rootDir, absPath).replace(/\\/g, "/");
|
|
1164
|
+
}
|
|
1165
|
+
function partitionRules(rules) {
|
|
1166
|
+
const strings = /* @__PURE__ */ new Set();
|
|
1167
|
+
const regexes = [];
|
|
1168
|
+
if (!rules) return { strings, regexes };
|
|
1169
|
+
for (const r of rules) {
|
|
1170
|
+
if (typeof r === "string") {
|
|
1171
|
+
const t = r.trim();
|
|
1172
|
+
if (t) strings.add(t);
|
|
1173
|
+
} else {
|
|
1174
|
+
regexes.push(r);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
return { strings, regexes };
|
|
1178
|
+
}
|
|
1179
|
+
function partitionExtRules(rules) {
|
|
1180
|
+
const strings = /* @__PURE__ */ new Set();
|
|
1181
|
+
const regexes = [];
|
|
1182
|
+
if (!rules) return { strings, regexes };
|
|
1183
|
+
for (const r of rules) {
|
|
1184
|
+
if (typeof r === "string") {
|
|
1185
|
+
const n = normExtToken(r);
|
|
1186
|
+
if (n) strings.add(n);
|
|
1187
|
+
} else {
|
|
1188
|
+
regexes.push(r);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
return { strings, regexes };
|
|
1192
|
+
}
|
|
1193
|
+
function compileScanExclude(exclude) {
|
|
1194
|
+
const resolved = resolveScanExcludeConfig(exclude);
|
|
1195
|
+
const useDefault = resolved?.useDefaultSkip !== false;
|
|
1196
|
+
const defaultDirs = useDefault ? DEFAULT_SCAN_SKIP_DIR_SET : null;
|
|
1197
|
+
const dirs = partitionRules(resolved?.dirs);
|
|
1198
|
+
const files = partitionRules(resolved?.files);
|
|
1199
|
+
const exts = partitionExtRules(resolved?.extensions);
|
|
1200
|
+
const pathPatterns = resolved?.patterns ?? [];
|
|
1201
|
+
const userRulesEmpty = dirs.strings.size === 0 && dirs.regexes.length === 0 && files.strings.size === 0 && files.regexes.length === 0 && exts.strings.size === 0 && exts.regexes.length === 0 && pathPatterns.length === 0;
|
|
1202
|
+
return {
|
|
1203
|
+
defaultDirs,
|
|
1204
|
+
dirStrings: dirs.strings,
|
|
1205
|
+
dirRegexes: dirs.regexes,
|
|
1206
|
+
fileStrings: files.strings,
|
|
1207
|
+
fileRegexes: files.regexes,
|
|
1208
|
+
extStrings: exts.strings,
|
|
1209
|
+
extRegexes: exts.regexes,
|
|
1210
|
+
pathPatterns,
|
|
1211
|
+
userRulesEmpty
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
function explainDirSkip(name, c) {
|
|
1215
|
+
if (c.defaultDirs?.has(name)) return `built-in directory skip (${name})`;
|
|
1216
|
+
if (c.userRulesEmpty) return null;
|
|
1217
|
+
if (c.dirStrings.has(name)) return `exclude.dirs (${name})`;
|
|
1218
|
+
for (const re of c.dirRegexes) {
|
|
1219
|
+
if (re.test(name)) return `exclude.dirs regex /${re.source}/`;
|
|
1220
|
+
}
|
|
1221
|
+
return null;
|
|
1222
|
+
}
|
|
1223
|
+
function explainFileSkip(relPosix2, baseName, c) {
|
|
1224
|
+
if (c.userRulesEmpty) return null;
|
|
1225
|
+
if (c.fileStrings.has(baseName)) return `exclude.files (${baseName})`;
|
|
1226
|
+
for (const re of c.fileRegexes) {
|
|
1227
|
+
if (re.test(baseName)) return `exclude.files regex /${re.source}/`;
|
|
1228
|
+
}
|
|
1229
|
+
if (c.extStrings.size > 0 || c.extRegexes.length > 0) {
|
|
1230
|
+
for (const suf of basenameExtensionSuffixes(baseName)) {
|
|
1231
|
+
if (c.extStrings.has(suf)) return `exclude.extensions (${suf})`;
|
|
1232
|
+
for (const re of c.extRegexes) {
|
|
1233
|
+
if (re.test(suf)) return `exclude.extensions regex /${re.source}/`;
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
for (const re of c.pathPatterns) {
|
|
1238
|
+
if (re.test(relPosix2)) return `exclude.patterns /${re.source}/ \u2190 ${relPosix2}`;
|
|
1239
|
+
}
|
|
1240
|
+
return null;
|
|
1241
|
+
}
|
|
1242
|
+
function listSourceFiles(runtime, rootDir, exclude, listOpts) {
|
|
1243
|
+
const { fs, path } = runtime;
|
|
1244
|
+
const compiled = compileScanExclude(exclude);
|
|
1245
|
+
const out = [];
|
|
1246
|
+
const debugSink = resolveScanDebugSink(listOpts);
|
|
1247
|
+
const visitedDirs = /* @__PURE__ */ new Set();
|
|
1248
|
+
function walk(dir, depth) {
|
|
1249
|
+
if (!existsRuntimeFsSync(dir, fs)) return;
|
|
1250
|
+
const dirKey = walkDirectoryKey(dir, path, fs);
|
|
1251
|
+
if (visitedDirs.has(dirKey)) {
|
|
1252
|
+
emitScanDebug(debugSink, {
|
|
1253
|
+
kind: "skip_directory",
|
|
1254
|
+
relativePath: relPosix(path, rootDir, dir),
|
|
1255
|
+
basename: path.basename(dir),
|
|
1256
|
+
reason: "directory already visited (symlink cycle or duplicate path)"
|
|
1257
|
+
});
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
visitedDirs.add(dirKey);
|
|
1261
|
+
if (depth > MAX_SOURCE_TREE_WALK_DEPTH) {
|
|
1262
|
+
emitScanDebug(debugSink, {
|
|
1263
|
+
kind: "skip_directory",
|
|
1264
|
+
relativePath: relPosix(path, rootDir, dir),
|
|
1265
|
+
basename: path.basename(dir),
|
|
1266
|
+
reason: `scan depth limit (${String(MAX_SOURCE_TREE_WALK_DEPTH)})`
|
|
1267
|
+
});
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
const entries = listRuntimeFsDirSync(dir, fs);
|
|
1271
|
+
for (const e of entries) {
|
|
1272
|
+
const p = path.join(dir, e.name);
|
|
1273
|
+
if (e.kind === "directory") {
|
|
1274
|
+
const why = explainDirSkip(e.name, compiled);
|
|
1275
|
+
if (why) {
|
|
1276
|
+
emitScanDebug(debugSink, {
|
|
1277
|
+
kind: "skip_directory",
|
|
1278
|
+
relativePath: relPosix(path, rootDir, p),
|
|
1279
|
+
basename: e.name,
|
|
1280
|
+
reason: why
|
|
1281
|
+
});
|
|
1282
|
+
continue;
|
|
1283
|
+
}
|
|
1284
|
+
walk(p, depth + 1);
|
|
1285
|
+
} else if (e.kind === "file") {
|
|
1286
|
+
const rel = relPosix(path, rootDir, p);
|
|
1287
|
+
if (!SOURCE_FILE_NAME.test(e.name)) {
|
|
1288
|
+
emitScanDebug(debugSink, {
|
|
1289
|
+
kind: "skip_file",
|
|
1290
|
+
relativePath: rel,
|
|
1291
|
+
basename: e.name,
|
|
1292
|
+
reason: `not a scanned source extension (${e.name})`
|
|
1293
|
+
});
|
|
1294
|
+
continue;
|
|
1295
|
+
}
|
|
1296
|
+
const whyF = explainFileSkip(rel, e.name, compiled);
|
|
1297
|
+
if (whyF) {
|
|
1298
|
+
emitScanDebug(debugSink, {
|
|
1299
|
+
kind: "skip_file",
|
|
1300
|
+
relativePath: rel,
|
|
1301
|
+
basename: e.name,
|
|
1302
|
+
reason: whyF
|
|
1303
|
+
});
|
|
1304
|
+
continue;
|
|
1305
|
+
}
|
|
1306
|
+
out.push(p);
|
|
1307
|
+
} else if (e.kind === "other") {
|
|
1308
|
+
emitScanDebug(debugSink, {
|
|
1309
|
+
kind: "skip_file",
|
|
1310
|
+
relativePath: relPosix(path, rootDir, p),
|
|
1311
|
+
basename: e.name,
|
|
1312
|
+
reason: "not a regular file or directory (symlink or special entry)"
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
walk(rootDir, 0);
|
|
1318
|
+
return out;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// src/shared/scanner/index.ts
|
|
1322
|
+
function scanSources(runtime, srcRoot, exclude, scanOpts) {
|
|
1323
|
+
const files = listSourceFiles(runtime, srcRoot, exclude, scanOpts);
|
|
1324
|
+
const parts = [];
|
|
1325
|
+
for (const f of files) {
|
|
1326
|
+
try {
|
|
1327
|
+
parts.push(readRuntimeFsTextSync(f, runtime.fs));
|
|
1328
|
+
} catch {
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
return { files, text: parts.join("\n") };
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// src/shared/placeholders/index.ts
|
|
1335
|
+
var placeholders_exports = {};
|
|
1336
|
+
__export(placeholders_exports, {
|
|
1337
|
+
mask: () => mask,
|
|
1338
|
+
restore: () => restore,
|
|
1339
|
+
validateRestored: () => validateRestored
|
|
1340
|
+
});
|
|
1341
|
+
var SENTINEL_RE = /__I18NPRUNE_(\d+)__/g;
|
|
1342
|
+
function mask(input) {
|
|
1343
|
+
const originals = [];
|
|
1344
|
+
const text = input.replace(/\{\{([^}]+)\}\}/g, (_, inner) => {
|
|
1345
|
+
const i = originals.length;
|
|
1346
|
+
originals.push(inner.trim());
|
|
1347
|
+
return `__I18NPRUNE_${i}__`;
|
|
1348
|
+
});
|
|
1349
|
+
return { text, originals };
|
|
1350
|
+
}
|
|
1351
|
+
function restore(masked, originals) {
|
|
1352
|
+
return masked.replace(SENTINEL_RE, (_, idx) => {
|
|
1353
|
+
const i = Number.parseInt(idx, 10);
|
|
1354
|
+
const o = originals[i];
|
|
1355
|
+
return o !== void 0 ? `{{${o}}}` : _;
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
function validateRestored(source, restored, originals) {
|
|
1359
|
+
if (/__I18NPRUNE_\d+__/.test(restored)) {
|
|
1360
|
+
throw new Error("Translation output still contains placeholder sentinels");
|
|
1361
|
+
}
|
|
1362
|
+
const srcMatches = [...source.matchAll(/\{\{([^}]+)\}\}/g)].map((m) => m[1].trim());
|
|
1363
|
+
if (srcMatches.length !== originals.length) {
|
|
1364
|
+
throw new Error("Placeholder count mismatch after translation");
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
// src/shared/translator/index.ts
|
|
1369
|
+
var translator_exports = {};
|
|
1370
|
+
__export(translator_exports, {
|
|
1371
|
+
localeJsonValueFromTranslation: () => localeJsonValueFromTranslation,
|
|
1372
|
+
translateLeaf: () => translateLeaf,
|
|
1373
|
+
validateLeafTranslationString: () => validateLeafTranslationString
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
// src/shared/translator/utils/metadata.ts
|
|
1377
|
+
function buildHeuristicLeafMeta(input) {
|
|
1378
|
+
const src = input.sourceText.trim();
|
|
1379
|
+
const tgt = input.translatedText.trim();
|
|
1380
|
+
const tag = `${input.providerId}-heuristic`;
|
|
1381
|
+
if (src.length === 0) {
|
|
1382
|
+
return {
|
|
1383
|
+
status: "translated",
|
|
1384
|
+
confidence: null,
|
|
1385
|
+
needsReview: true,
|
|
1386
|
+
source: tag,
|
|
1387
|
+
needsTranslationAgain: true
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
if (src === tgt) {
|
|
1391
|
+
return {
|
|
1392
|
+
status: "translated",
|
|
1393
|
+
confidence: null,
|
|
1394
|
+
needsReview: true,
|
|
1395
|
+
source: tag,
|
|
1396
|
+
needsTranslationAgain: true
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
const ratio = tgt.length / src.length;
|
|
1400
|
+
const drift = Math.abs(1 - Math.min(ratio, 2));
|
|
1401
|
+
const confidence = Math.max(0.35, Math.min(0.88, 0.62 + (1 - drift) * 0.25));
|
|
1402
|
+
return {
|
|
1403
|
+
status: "translated",
|
|
1404
|
+
confidence,
|
|
1405
|
+
needsReview: confidence < 0.52,
|
|
1406
|
+
source: tag,
|
|
1407
|
+
needsTranslationAgain: false
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// src/shared/translator/utils/pipeline.ts
|
|
1412
|
+
function unpackProviderTranslation(raw) {
|
|
1413
|
+
if (typeof raw === "string") return { text: raw, patch: {} };
|
|
1414
|
+
return { text: raw.text, patch: raw.leafMeta ?? {} };
|
|
1415
|
+
}
|
|
1416
|
+
function mergeTranslationLeafMeta(heuristic, provider) {
|
|
1417
|
+
return {
|
|
1418
|
+
status: provider.status ?? heuristic.status,
|
|
1419
|
+
confidence: "confidence" in provider ? provider.confidence ?? null : heuristic.confidence,
|
|
1420
|
+
needsReview: "needsReview" in provider ? provider.needsReview : heuristic.needsReview,
|
|
1421
|
+
needsTranslationAgain: "needsTranslationAgain" in provider ? provider.needsTranslationAgain : heuristic.needsTranslationAgain,
|
|
1422
|
+
source: provider.source ?? heuristic.source
|
|
1423
|
+
};
|
|
1424
|
+
}
|
|
1425
|
+
function finalizeTranslationLeafMeta(patch, decision) {
|
|
1426
|
+
const roundConfidence = (v) => {
|
|
1427
|
+
if (v === null || v === void 0) return null;
|
|
1428
|
+
if (!Number.isFinite(v)) return null;
|
|
1429
|
+
const clamped = Math.max(0, Math.min(1, v));
|
|
1430
|
+
return Math.round(clamped * 100) / 100;
|
|
1431
|
+
};
|
|
1432
|
+
return {
|
|
1433
|
+
status: patch.status ?? "translated",
|
|
1434
|
+
confidence: roundConfidence(patch.confidence),
|
|
1435
|
+
needsReview: decision === "review" ? true : patch.needsReview ?? false,
|
|
1436
|
+
needsTranslationAgain: patch.needsTranslationAgain ?? false,
|
|
1437
|
+
source: patch.source ?? "manual"
|
|
1438
|
+
};
|
|
1439
|
+
}
|
|
1440
|
+
function localeJsonValueFromTranslation(persistStructuredMetadata, tr) {
|
|
1441
|
+
if (!persistStructuredMetadata) return tr.text;
|
|
1442
|
+
return {
|
|
1443
|
+
value: tr.text,
|
|
1444
|
+
status: tr.leafMeta.status,
|
|
1445
|
+
confidence: tr.leafMeta.confidence,
|
|
1446
|
+
needsReview: tr.leafMeta.needsReview,
|
|
1447
|
+
needsTranslationAgain: tr.leafMeta.needsTranslationAgain,
|
|
1448
|
+
source: tr.leafMeta.source
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
function validateLeafTranslationString(value, context) {
|
|
1452
|
+
if (typeof value !== "string") {
|
|
1453
|
+
throw new I18nPruneError(
|
|
1454
|
+
`Translator returned non-string${context ? ` (${context})` : ""}`,
|
|
1455
|
+
"INTERNAL"
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1458
|
+
return value;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
// src/translator/policy/classify.ts
|
|
1462
|
+
function classifyTranslateFailure(err) {
|
|
1463
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1464
|
+
if (/\b429\b/.test(msg) || /\btoo many requests\b/i.test(msg)) {
|
|
1465
|
+
if (/MYMEMORY WARNING:\s*YOU USED ALL AVAILABLE FREE TRANSLATIONS FOR TODAY/i.test(msg)) {
|
|
1466
|
+
return "quota_exceeded";
|
|
1467
|
+
}
|
|
1468
|
+
return "rate_limited";
|
|
1469
|
+
}
|
|
1470
|
+
if (/\b401\b/.test(msg) || /\b403\b/.test(msg) || /\bunauthorized\b/i.test(msg) || /\bforbidden\b/i.test(msg)) {
|
|
1471
|
+
return "auth_failure";
|
|
1472
|
+
}
|
|
1473
|
+
if (isErrnoCode(err, "ECONNRESET") || isErrnoCode(err, "ETIMEDOUT") || isErrnoCode(err, "ENOTFOUND") || isErrnoCode(err, "EAI_AGAIN") || isErrnoCode(err, "ECONNREFUSED") || /fetch failed/i.test(msg) || /network/i.test(msg)) {
|
|
1474
|
+
return "transient_network";
|
|
1475
|
+
}
|
|
1476
|
+
if (/\b5\d{2}\b/.test(msg) || /\bservice unavailable\b/i.test(msg)) {
|
|
1477
|
+
return "provider_unavailable";
|
|
1478
|
+
}
|
|
1479
|
+
if (/invalid json/i.test(msg) || /malformed/i.test(msg) || /unexpected token/i.test(msg)) {
|
|
1480
|
+
return "malformed_response";
|
|
1481
|
+
}
|
|
1482
|
+
return "unknown_hard_stop";
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// src/shared/constants/translate.ts
|
|
1486
|
+
var TRANSLATE_WORKERS_CAP = 64;
|
|
1487
|
+
var ENV_TRANSLATE_MAX_WORKERS = "I18NPRUNE_TRANSLATE_MAX_WORKERS";
|
|
1488
|
+
var ENV_TRANSLATE_PROVIDER = "I18NPRUNE_TRANSLATE_PROVIDER";
|
|
1489
|
+
var ENV_TRANSLATE_DEEPL_API_KEY = "I18NPRUNE_TRANSLATE_DEEPL_API_KEY";
|
|
1490
|
+
var ENV_TRANSLATE_LIBRE_URL = "I18NPRUNE_TRANSLATE_LIBRE_URL";
|
|
1491
|
+
var ENV_TRANSLATE_LLM_API_KEY = "I18NPRUNE_TRANSLATE_LLM_API_KEY";
|
|
1492
|
+
var ENV_TRANSLATE_LLM_BASE_URL = "I18NPRUNE_TRANSLATE_LLM_BASE_URL";
|
|
1493
|
+
var ENV_TRANSLATE_LLM_MODEL = "I18NPRUNE_TRANSLATE_LLM_MODEL";
|
|
1494
|
+
|
|
1495
|
+
// src/shared/translator/index.ts
|
|
1496
|
+
var DEFAULT_DELAYS = [400, 900];
|
|
1497
|
+
async function sleep(ms) {
|
|
1498
|
+
await new Promise((r) => setTimeout(r, ms));
|
|
1499
|
+
}
|
|
1500
|
+
async function translateLeaf(provider, sourceText, sourceLang, targetLang, options) {
|
|
1501
|
+
const { text, originals } = mask(sourceText);
|
|
1502
|
+
const providerId = options?.providerId ?? "google";
|
|
1503
|
+
let lastErr;
|
|
1504
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
1505
|
+
try {
|
|
1506
|
+
const raw = await provider.translate(text, sourceLang, targetLang);
|
|
1507
|
+
const unpacked = unpackProviderTranslation(raw);
|
|
1508
|
+
const normalized = validateLeafTranslationString(unpacked.text, "translate");
|
|
1509
|
+
const restored = restore(normalized, originals);
|
|
1510
|
+
validateRestored(sourceText, restored, originals);
|
|
1511
|
+
const heuristic = buildHeuristicLeafMeta({
|
|
1512
|
+
sourceText,
|
|
1513
|
+
translatedText: restored,
|
|
1514
|
+
providerId
|
|
1515
|
+
});
|
|
1516
|
+
const merged = mergeTranslationLeafMeta(heuristic, unpacked.patch);
|
|
1517
|
+
const decision = merged.needsReview === true ? "review" : "translated";
|
|
1518
|
+
const leafMeta = finalizeTranslationLeafMeta(merged, decision);
|
|
1519
|
+
await options?.onTranslated?.(sourceText, restored);
|
|
1520
|
+
const attempts = attempt + 1;
|
|
1521
|
+
return {
|
|
1522
|
+
text: restored,
|
|
1523
|
+
leafMeta,
|
|
1524
|
+
decision,
|
|
1525
|
+
runtime: { attempts, retries: Math.max(0, attempts - 1) }
|
|
1526
|
+
};
|
|
1527
|
+
} catch (e) {
|
|
1528
|
+
lastErr = e;
|
|
1529
|
+
if (attempt < 2) await sleep(DEFAULT_DELAYS[attempt] ?? 500);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
const parseMyMemoryQuotaWait = (msg) => {
|
|
1533
|
+
const m = msg.match(/NEXT AVAILABLE IN\s+(\d+)\s+HOURS\s+(\d+)\s+MINUTES\s+(\d+)\s+SECONDS/i);
|
|
1534
|
+
if (!m) return null;
|
|
1535
|
+
const h = Number.parseInt(m[1] ?? "", 10);
|
|
1536
|
+
const min = Number.parseInt(m[2] ?? "", 10);
|
|
1537
|
+
const s = Number.parseInt(m[3] ?? "", 10);
|
|
1538
|
+
if (![h, min, s].every((n) => Number.isFinite(n) && n >= 0)) return null;
|
|
1539
|
+
const parts = [h ? `${String(h)}h` : "", min ? `${String(min)}m` : "", `${String(s)}s`].filter(Boolean);
|
|
1540
|
+
return parts.join(" ");
|
|
1541
|
+
};
|
|
1542
|
+
const outcome = classifyTranslateFailure(lastErr);
|
|
1543
|
+
const issueCode = outcome === "rate_limited" || outcome === "quota_exceeded" ? ISSUE_GENERATE_TRANSLATE_RATE_LIMITED : outcome === "transient_network" || outcome === "provider_unavailable" ? ISSUE_GENERATE_TRANSLATE_NETWORK_ERROR : void 0;
|
|
1544
|
+
const issues = issueCode !== void 0 ? [
|
|
1545
|
+
{
|
|
1546
|
+
severity: "error",
|
|
1547
|
+
code: issueCode,
|
|
1548
|
+
message: issueCode === ISSUE_GENERATE_TRANSLATE_RATE_LIMITED ? (() => {
|
|
1549
|
+
const msg = lastErr instanceof Error ? lastErr.message : String(lastErr);
|
|
1550
|
+
const wait = /MYMEMORY WARNING/i.test(msg) ? parseMyMemoryQuotaWait(msg) : null;
|
|
1551
|
+
const waitHint = wait ? ` Wait time reported by MyMemory: ${wait}.` : "";
|
|
1552
|
+
const limitsHint = /MYMEMORY WARNING/i.test(msg) ? " See MyMemory usage limits: https://mymemory.translated.net/doc/usagelimits.php." : "";
|
|
1553
|
+
return `Translation failed: backend rate limited the request(s) (HTTP 429). Reduce --workers, wait, or switch provider.${waitHint}${limitsHint}`;
|
|
1554
|
+
})() : "Translation failed: network error talking to the translation backend. Check connectivity/DNS/proxy and retry.",
|
|
1555
|
+
docPath: issueCodeRepoDocPathForIssueCode(issueCode)
|
|
1556
|
+
}
|
|
1557
|
+
] : [];
|
|
1558
|
+
const norm = normalizeUnknownError(lastErr, {
|
|
1559
|
+
when: "Translation failed after retries",
|
|
1560
|
+
defaultCode: "INTERNAL",
|
|
1561
|
+
...issueCode !== void 0 ? { issueCode } : {}
|
|
1562
|
+
});
|
|
1563
|
+
norm.issues = issues;
|
|
1564
|
+
throw norm;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
// src/shared/locales/layout/index.ts
|
|
1568
|
+
var layout_exports = {};
|
|
1569
|
+
__export(layout_exports, {
|
|
1570
|
+
isLocalesLayoutReadSupported: () => isLocalesLayoutReadSupported,
|
|
1571
|
+
isLocalesLayoutWriteSupported: () => isLocalesLayoutWriteSupported,
|
|
1572
|
+
resolveLocalesLayout: () => resolveLocalesLayout,
|
|
1573
|
+
resolveLocalesLayoutFromContext: () => resolveLocalesLayoutFromContext,
|
|
1574
|
+
sourceLocaleCodeForLayout: () => sourceLocaleCodeForLayout
|
|
1575
|
+
});
|
|
1576
|
+
|
|
1577
|
+
// src/shared/locales/layout/requireStructure.ts
|
|
1578
|
+
function localesMode(config) {
|
|
1579
|
+
return config.mode ?? "flat_file";
|
|
1580
|
+
}
|
|
1581
|
+
function resolveLocalesStructure(config) {
|
|
1582
|
+
if (config.structure !== void 0) {
|
|
1583
|
+
return config.structure;
|
|
1584
|
+
}
|
|
1585
|
+
if (localesMode(config) === "flat_file") {
|
|
1586
|
+
return "locale_file";
|
|
1587
|
+
}
|
|
1588
|
+
throw new Error("locales.structure is required when locales.mode is locale_directory");
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
// src/shared/locales/layout/resolveLayout.ts
|
|
1592
|
+
function resolveLocalesLayout(config, directoryAbsolute) {
|
|
1593
|
+
const mode = localesMode(config);
|
|
1594
|
+
const structure = resolveLocalesStructure(config);
|
|
1595
|
+
return { mode, structure, directoryAbsolute, config };
|
|
1596
|
+
}
|
|
1597
|
+
function resolveLocalesLayoutFromContext(ctx) {
|
|
1598
|
+
return resolveLocalesLayout(ctx.config.locales, ctx.paths.localesDir);
|
|
1599
|
+
}
|
|
1600
|
+
function isLocalesLayoutReadSupported(layout) {
|
|
1601
|
+
return layout.mode === "flat_file" && layout.structure === "locale_file" || layout.mode === "locale_directory" && (layout.structure === "locale_per_dir" || layout.structure === "feature_bundle");
|
|
1602
|
+
}
|
|
1603
|
+
function isLocalesLayoutWriteSupported(layout) {
|
|
1604
|
+
return layout.mode === "flat_file" && layout.structure === "locale_file" || layout.mode === "locale_directory" && (layout.structure === "locale_per_dir" || layout.structure === "feature_bundle");
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
// src/shared/languages/normalize.ts
|
|
1608
|
+
function normalizeLanguageCode(code) {
|
|
1609
|
+
return code.trim().toLowerCase().replace(/_/g, "-");
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
// src/shared/path/posix.ts
|
|
1613
|
+
function toPosixPath(value) {
|
|
1614
|
+
return value.replace(/\\/g, "/");
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
// src/shared/locales/enumerate/resolveSegmentPath.ts
|
|
1618
|
+
function resolveLocaleSegmentAbsolutePath(input) {
|
|
1619
|
+
const { layout, path, locale } = input;
|
|
1620
|
+
const rel = input.segmentRelativePath ?? `${locale}.json`;
|
|
1621
|
+
return toPosixPath(path.join(layout.directoryAbsolute, rel));
|
|
1622
|
+
}
|
|
1623
|
+
function localeSegmentRefFromAbsolute(input) {
|
|
1624
|
+
const { layout, path, absolutePath } = input;
|
|
1625
|
+
let relativePath = path.relative(layout.directoryAbsolute, absolutePath);
|
|
1626
|
+
if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
|
|
1627
|
+
return null;
|
|
1628
|
+
}
|
|
1629
|
+
relativePath = relativePath.replace(/\\/g, "/");
|
|
1630
|
+
if (!relativePath.endsWith(".json")) {
|
|
1631
|
+
return null;
|
|
1632
|
+
}
|
|
1633
|
+
const locale = localeCodeForSegment(layout.structure, path, { absolutePath, relativePath });
|
|
1634
|
+
if (locale === null) return null;
|
|
1635
|
+
return { locale, relativePath, absolutePath: toPosixPath(absolutePath) };
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
// src/shared/locales/layout/sourceLocaleCode.ts
|
|
1639
|
+
function sourceLocaleCodeForLayout(input) {
|
|
1640
|
+
const ref = localeSegmentRefFromAbsolute({
|
|
1641
|
+
layout: input.layout,
|
|
1642
|
+
path: input.path,
|
|
1643
|
+
absolutePath: input.sourceLocaleAbsolute
|
|
1644
|
+
});
|
|
1645
|
+
if (ref !== null) {
|
|
1646
|
+
return normalizeLanguageCode(ref.locale);
|
|
1647
|
+
}
|
|
1648
|
+
return normalizeLanguageCode(input.path.basename(input.sourceLocaleAbsolute, ".json"));
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
// src/shared/locales/read/index.ts
|
|
1652
|
+
var read_exports = {};
|
|
1653
|
+
__export(read_exports, {
|
|
1654
|
+
createLocaleReadCache: () => createLocaleReadCache,
|
|
1655
|
+
invalidateLocaleReadCacheForAbsolutePath: () => invalidateLocaleReadCacheForAbsolutePath,
|
|
1656
|
+
invalidateLocaleReadCacheForLocaleCode: () => invalidateLocaleReadCacheForLocaleCode,
|
|
1657
|
+
readFlatLocaleJsonSurface: () => readFlatLocaleJsonSurface,
|
|
1658
|
+
readLocaleBundle: () => readLocaleBundle,
|
|
1659
|
+
readLocaleCodeSurfaceFromContext: () => readLocaleCodeSurfaceFromContext,
|
|
1660
|
+
readLocaleJsonFromContextSync: () => readLocaleJsonFromContextSync,
|
|
1661
|
+
readLocalePerDirLocaleSurface: () => readLocalePerDirLocaleSurface,
|
|
1662
|
+
readLocaleSegmentFromContext: () => readLocaleSegmentFromContext
|
|
1663
|
+
});
|
|
1664
|
+
|
|
1665
|
+
// src/shared/locales/read/flatFileSurface.ts
|
|
1666
|
+
function readFlatLocaleJsonSurface(input) {
|
|
1667
|
+
const diagnostics = [];
|
|
1668
|
+
const emit = (d) => {
|
|
1669
|
+
diagnostics.push(d);
|
|
1670
|
+
input.onDiagnostic?.(d);
|
|
1671
|
+
};
|
|
1672
|
+
try {
|
|
1673
|
+
const text = readRuntimeFsTextSync(input.absoluteFile, input.fs);
|
|
1674
|
+
let json;
|
|
1675
|
+
try {
|
|
1676
|
+
json = parseJsonText(text, {
|
|
1677
|
+
filePath: input.absoluteFile,
|
|
1678
|
+
code: "IO",
|
|
1679
|
+
issueCode: ISSUE_IO_READ_FAILED
|
|
1680
|
+
});
|
|
1681
|
+
} catch (e) {
|
|
1682
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
1683
|
+
emit({ level: "error", code: "locale_json_parse_failed", message, path: input.absoluteFile });
|
|
1684
|
+
return { ok: false, leaves: [], diagnostics };
|
|
1685
|
+
}
|
|
1686
|
+
const fileOrigin = localeSegmentSourceForFile({
|
|
1687
|
+
path: input.path,
|
|
1688
|
+
absoluteFile: input.absoluteFile,
|
|
1689
|
+
localesDir: input.localesDir,
|
|
1690
|
+
structure: input.structure
|
|
1691
|
+
});
|
|
1692
|
+
const leaves = collectTranslationSurfaceLeaves(json, "", [], fileOrigin ?? void 0);
|
|
1693
|
+
return { ok: true, document: json, leaves, text, diagnostics };
|
|
1694
|
+
} catch (e) {
|
|
1695
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
1696
|
+
emit({ level: "error", code: "locale_fs_read_failed", message, path: input.absoluteFile });
|
|
1697
|
+
return { ok: false, leaves: [], diagnostics };
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
// src/shared/locales/read/bundle.ts
|
|
1702
|
+
function readLocaleBundle(input) {
|
|
1703
|
+
const diagnostics = [];
|
|
1704
|
+
const emit = (d) => {
|
|
1705
|
+
diagnostics.push(d);
|
|
1706
|
+
input.onDiagnostic?.(d);
|
|
1707
|
+
};
|
|
1708
|
+
if (!isLocalesLayoutReadSupported(input.layout)) {
|
|
1709
|
+
emit({
|
|
1710
|
+
level: "error",
|
|
1711
|
+
code: "locale_layout_unsupported",
|
|
1712
|
+
message: `locale read is not implemented for mode=${input.layout.mode} structure=${input.layout.structure}`,
|
|
1713
|
+
path: input.absoluteFile
|
|
1714
|
+
});
|
|
1715
|
+
return { ok: false, leaves: [], diagnostics };
|
|
1716
|
+
}
|
|
1717
|
+
const segmentRef = localeSegmentRefFromAbsolute({
|
|
1718
|
+
layout: input.layout,
|
|
1719
|
+
path: input.path,
|
|
1720
|
+
absolutePath: input.absoluteFile
|
|
1721
|
+
});
|
|
1722
|
+
if (segmentRef === null) {
|
|
1723
|
+
emit({
|
|
1724
|
+
level: "warn",
|
|
1725
|
+
code: "locale_read_path_layout_mismatch",
|
|
1726
|
+
message: `path does not match configured layout mode=${input.layout.mode} structure=${input.layout.structure}`,
|
|
1727
|
+
path: input.absoluteFile
|
|
1728
|
+
});
|
|
1729
|
+
return { ok: false, leaves: [], diagnostics };
|
|
1730
|
+
}
|
|
1731
|
+
return readFlatLocaleJsonSurface({
|
|
1732
|
+
fs: input.fs,
|
|
1733
|
+
path: input.path,
|
|
1734
|
+
absoluteFile: input.absoluteFile,
|
|
1735
|
+
localesDir: input.layout.directoryAbsolute,
|
|
1736
|
+
structure: input.layout.structure,
|
|
1737
|
+
onDiagnostic: input.onDiagnostic
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
// src/shared/locales/diagnostics/structuralParity.ts
|
|
1742
|
+
function localeStructuralSlot(structure, relativePath) {
|
|
1743
|
+
if (structure === "locale_per_dir") {
|
|
1744
|
+
const slash = relativePath.indexOf("/");
|
|
1745
|
+
if (slash < 0) return null;
|
|
1746
|
+
const slot = relativePath.slice(slash + 1);
|
|
1747
|
+
return slot.length > 0 ? slot : null;
|
|
1748
|
+
}
|
|
1749
|
+
if (structure === "feature_bundle") {
|
|
1750
|
+
const slash = relativePath.lastIndexOf("/");
|
|
1751
|
+
if (slash < 0) return null;
|
|
1752
|
+
const slot = relativePath.slice(0, slash);
|
|
1753
|
+
return slot.length > 0 ? slot : null;
|
|
1754
|
+
}
|
|
1755
|
+
return null;
|
|
1756
|
+
}
|
|
1757
|
+
function slotsByLocale(structure, segments) {
|
|
1758
|
+
const byLocale = /* @__PURE__ */ new Map();
|
|
1759
|
+
for (const segment of segments) {
|
|
1760
|
+
const slot = localeStructuralSlot(structure, segment.relativePath);
|
|
1761
|
+
if (slot === null) continue;
|
|
1762
|
+
let set = byLocale.get(segment.locale);
|
|
1763
|
+
if (!set) {
|
|
1764
|
+
set = /* @__PURE__ */ new Set();
|
|
1765
|
+
byLocale.set(segment.locale, set);
|
|
1766
|
+
}
|
|
1767
|
+
set.add(slot);
|
|
1768
|
+
}
|
|
1769
|
+
return byLocale;
|
|
1770
|
+
}
|
|
1771
|
+
function pickReferenceLocale(byLocale, preferred) {
|
|
1772
|
+
if (preferred !== void 0 && byLocale.has(preferred)) return preferred;
|
|
1773
|
+
let best = null;
|
|
1774
|
+
let bestSize = -1;
|
|
1775
|
+
for (const [locale, slots] of byLocale) {
|
|
1776
|
+
if (slots.size > bestSize) {
|
|
1777
|
+
best = locale;
|
|
1778
|
+
bestSize = slots.size;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
return best;
|
|
1782
|
+
}
|
|
1783
|
+
function collectLocaleStructuralParityDiagnostics(input) {
|
|
1784
|
+
const { structure, segments } = input;
|
|
1785
|
+
if (structure !== "locale_per_dir" && structure !== "feature_bundle") {
|
|
1786
|
+
return [];
|
|
1787
|
+
}
|
|
1788
|
+
const byLocale = slotsByLocale(structure, segments);
|
|
1789
|
+
if (byLocale.size < 2) return [];
|
|
1790
|
+
const reference = pickReferenceLocale(byLocale, input.referenceLocale);
|
|
1791
|
+
if (reference === null) return [];
|
|
1792
|
+
const referenceSlots = byLocale.get(reference);
|
|
1793
|
+
if (!referenceSlots || referenceSlots.size === 0) return [];
|
|
1794
|
+
const diagnostics = [];
|
|
1795
|
+
for (const [locale, slots] of byLocale) {
|
|
1796
|
+
if (locale === reference) continue;
|
|
1797
|
+
for (const slot of referenceSlots) {
|
|
1798
|
+
if (!slots.has(slot)) {
|
|
1799
|
+
diagnostics.push({
|
|
1800
|
+
level: "warn",
|
|
1801
|
+
code: "locale_structure_slot_missing",
|
|
1802
|
+
message: `locale ${locale} is missing segment slot ${slot} (present for reference locale ${reference})`
|
|
1803
|
+
});
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
for (const slot of slots) {
|
|
1807
|
+
if (!referenceSlots.has(slot)) {
|
|
1808
|
+
diagnostics.push({
|
|
1809
|
+
level: "warn",
|
|
1810
|
+
code: "locale_structure_slot_extra",
|
|
1811
|
+
message: `locale ${locale} has extra segment slot ${slot} (not present for reference locale ${reference})`
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
diagnostics.sort((a, b) => a.message.localeCompare(b.message));
|
|
1817
|
+
return diagnostics;
|
|
1818
|
+
}
|
|
1819
|
+
function collectSourceLocaleMissingSegmentDiagnostics(input) {
|
|
1820
|
+
const { structure, segments, sourceLocale } = input;
|
|
1821
|
+
if (structure !== "locale_per_dir" && structure !== "feature_bundle") {
|
|
1822
|
+
return [];
|
|
1823
|
+
}
|
|
1824
|
+
const byLocale = slotsByLocale(structure, segments);
|
|
1825
|
+
const sourceSlots = byLocale.get(sourceLocale);
|
|
1826
|
+
if (!sourceSlots) return [];
|
|
1827
|
+
const peerSlots = /* @__PURE__ */ new Set();
|
|
1828
|
+
for (const [locale, slots] of byLocale) {
|
|
1829
|
+
if (locale === sourceLocale) continue;
|
|
1830
|
+
for (const slot of slots) {
|
|
1831
|
+
peerSlots.add(slot);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
if (peerSlots.size === 0) return [];
|
|
1835
|
+
const diagnostics = [];
|
|
1836
|
+
for (const slot of peerSlots) {
|
|
1837
|
+
if (!sourceSlots.has(slot)) {
|
|
1838
|
+
diagnostics.push({
|
|
1839
|
+
level: "warn",
|
|
1840
|
+
code: "source_locale_segment_slot_missing",
|
|
1841
|
+
message: `source locale ${sourceLocale} is missing segment ${slot} (present for other locale(s) under locales.directory)`
|
|
1842
|
+
});
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
diagnostics.sort((a, b) => a.message.localeCompare(b.message));
|
|
1846
|
+
return diagnostics;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
// src/shared/constants/locales.ts
|
|
1850
|
+
var MAX_LOCALE_SEGMENT_TREE_DEPTH = 16;
|
|
1851
|
+
|
|
1852
|
+
// src/shared/locales/enumerate/walkJsonTree.ts
|
|
1853
|
+
function posixRelative(pathApi, root, absolute) {
|
|
1854
|
+
let rel = pathApi.relative(root, absolute);
|
|
1855
|
+
if (rel.startsWith("..") || pathApi.isAbsolute(rel)) {
|
|
1856
|
+
rel = pathApi.basename(absolute);
|
|
1857
|
+
}
|
|
1858
|
+
return rel.replace(/\\/g, "/");
|
|
1859
|
+
}
|
|
1860
|
+
function walkLocaleJsonSegments(input) {
|
|
1861
|
+
const { fs, path, rootAbsolute, recursive } = input;
|
|
1862
|
+
const maxDepth = input.maxDepth ?? MAX_LOCALE_SEGMENT_TREE_DEPTH;
|
|
1863
|
+
const out = [];
|
|
1864
|
+
function visit(dirAbsolute, depth) {
|
|
1865
|
+
if (!existsRuntimeFsSync(dirAbsolute, fs)) return;
|
|
1866
|
+
const entries = listRuntimeFsDirSync(dirAbsolute, fs);
|
|
1867
|
+
for (const entry of entries) {
|
|
1868
|
+
const childAbsolute = path.join(dirAbsolute, entry.name);
|
|
1869
|
+
if (entry.kind === "file" && entry.name.endsWith(".json")) {
|
|
1870
|
+
out.push({
|
|
1871
|
+
absolutePath: childAbsolute,
|
|
1872
|
+
relativePath: posixRelative(path, rootAbsolute, childAbsolute)
|
|
1873
|
+
});
|
|
1874
|
+
} else if (recursive && entry.kind === "directory" && depth < maxDepth) {
|
|
1875
|
+
visit(childAbsolute, depth + 1);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
visit(rootAbsolute, 0);
|
|
1880
|
+
return out;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
// src/shared/locales/enumerate/listLocaleSegments.ts
|
|
1884
|
+
function listLocaleSegments(input) {
|
|
1885
|
+
const diagnostics = [];
|
|
1886
|
+
const { layout, fs, path } = input;
|
|
1887
|
+
const recursive = layout.structure !== "locale_file";
|
|
1888
|
+
const walked = walkLocaleJsonSegments({
|
|
1889
|
+
fs,
|
|
1890
|
+
path,
|
|
1891
|
+
rootAbsolute: layout.directoryAbsolute,
|
|
1892
|
+
recursive
|
|
1893
|
+
});
|
|
1894
|
+
const segments = [];
|
|
1895
|
+
for (const segment of walked) {
|
|
1896
|
+
const locale = localeCodeForSegment(layout.structure, path, segment);
|
|
1897
|
+
if (locale === null) continue;
|
|
1898
|
+
segments.push({
|
|
1899
|
+
locale,
|
|
1900
|
+
relativePath: segment.relativePath,
|
|
1901
|
+
absolutePath: segment.absolutePath
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
segments.sort((a, b) => {
|
|
1905
|
+
const byLocale = a.locale.localeCompare(b.locale);
|
|
1906
|
+
if (byLocale !== 0) return byLocale;
|
|
1907
|
+
return a.relativePath.localeCompare(b.relativePath);
|
|
1908
|
+
});
|
|
1909
|
+
diagnostics.push(
|
|
1910
|
+
...collectLocaleStructuralParityDiagnostics({
|
|
1911
|
+
structure: layout.structure,
|
|
1912
|
+
segments
|
|
1913
|
+
})
|
|
1914
|
+
);
|
|
1915
|
+
return { segments, diagnostics };
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
// src/shared/locales/enumerate/listLocaleCodes.ts
|
|
1919
|
+
function listLocaleCodes(input) {
|
|
1920
|
+
const { segments, diagnostics } = listLocaleSegments(input);
|
|
1921
|
+
const codes = [...new Set(segments.map((s) => s.locale))].sort((a, b) => a.localeCompare(b));
|
|
1922
|
+
return { codes, diagnostics };
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
// src/shared/locales/enumerate/fromContext.ts
|
|
1926
|
+
function listLocaleSegmentsFromContext(ctx) {
|
|
1927
|
+
return listLocaleSegments({
|
|
1928
|
+
layout: resolveLocalesLayoutFromContext(ctx),
|
|
1929
|
+
fs: ctx.adapters.fs,
|
|
1930
|
+
path: ctx.adapters.path
|
|
1931
|
+
});
|
|
1932
|
+
}
|
|
1933
|
+
function listLocaleCodesFromContext(ctx) {
|
|
1934
|
+
return listLocaleCodes({
|
|
1935
|
+
layout: resolveLocalesLayoutFromContext(ctx),
|
|
1936
|
+
fs: ctx.adapters.fs,
|
|
1937
|
+
path: ctx.adapters.path
|
|
1938
|
+
});
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// src/shared/locales/targets/context.ts
|
|
1942
|
+
function normalizeCode(code) {
|
|
1943
|
+
return normalizeLanguageCode(code);
|
|
1944
|
+
}
|
|
1945
|
+
function listLocaleSegmentTargets(ctx) {
|
|
1946
|
+
const { segments } = listLocaleSegmentsFromContext(ctx);
|
|
1947
|
+
return segments.map((segment) => ({
|
|
1948
|
+
...segment,
|
|
1949
|
+
reportKey: segment.relativePath
|
|
1950
|
+
}));
|
|
1951
|
+
}
|
|
1952
|
+
function sourceLocaleCodeFromContext(ctx) {
|
|
1953
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
1954
|
+
const ref = localeSegmentRefFromAbsolute({
|
|
1955
|
+
layout,
|
|
1956
|
+
path: ctx.adapters.path,
|
|
1957
|
+
absolutePath: ctx.paths.sourceLocale
|
|
1958
|
+
});
|
|
1959
|
+
if (ref !== null) {
|
|
1960
|
+
return normalizeCode(ref.locale);
|
|
1961
|
+
}
|
|
1962
|
+
return normalizeCode(ctx.adapters.path.basename(ctx.paths.sourceLocale, ".json"));
|
|
1963
|
+
}
|
|
1964
|
+
function localeCodesFromContext(ctx) {
|
|
1965
|
+
return listLocaleCodesFromContext(ctx).codes.map((c) => normalizeCode(c));
|
|
1966
|
+
}
|
|
1967
|
+
function targetLocaleCodesFromContext(ctx) {
|
|
1968
|
+
const source = sourceLocaleCodeFromContext(ctx);
|
|
1969
|
+
return localeCodesFromContext(ctx).filter((c) => c !== source);
|
|
1970
|
+
}
|
|
1971
|
+
function segmentsForLocaleCode(ctx, localeCode) {
|
|
1972
|
+
const want = normalizeCode(localeCode);
|
|
1973
|
+
return listLocaleSegmentTargets(ctx).filter((s) => normalizeCode(s.locale) === want);
|
|
1974
|
+
}
|
|
1975
|
+
function primarySegmentForLocale(ctx, localeCode) {
|
|
1976
|
+
const segments = segmentsForLocaleCode(ctx, localeCode);
|
|
1977
|
+
if (segments.length === 0) return void 0;
|
|
1978
|
+
const sourceResolved = ctx.adapters.path.resolve(ctx.paths.sourceLocale);
|
|
1979
|
+
const sourceMatch = segments.find((s) => ctx.adapters.path.resolve(s.absolutePath) === sourceResolved);
|
|
1980
|
+
if (sourceMatch) return sourceMatch;
|
|
1981
|
+
return segments.slice().sort((a, b) => a.relativePath.localeCompare(b.relativePath))[0];
|
|
1982
|
+
}
|
|
1983
|
+
function resolveLocaleSegmentTargets(ctx, input) {
|
|
1984
|
+
const source = sourceLocaleCodeFromContext(ctx);
|
|
1985
|
+
const all = listLocaleSegmentTargets(ctx).filter((s) => normalizeCode(s.locale) !== source);
|
|
1986
|
+
if (input.selection.mode === "all") {
|
|
1987
|
+
return { segments: all, missingLocaleCodes: [] };
|
|
1988
|
+
}
|
|
1989
|
+
const missingLocaleCodes = [];
|
|
1990
|
+
const segments = [];
|
|
1991
|
+
for (const code of input.selection.codes) {
|
|
1992
|
+
const norm = normalizeCode(code);
|
|
1993
|
+
const forCode = all.filter((s) => normalizeCode(s.locale) === norm);
|
|
1994
|
+
if (forCode.length === 0) {
|
|
1995
|
+
missingLocaleCodes.push(norm);
|
|
1996
|
+
continue;
|
|
1997
|
+
}
|
|
1998
|
+
segments.push(...forCode);
|
|
1999
|
+
}
|
|
2000
|
+
segments.sort((a, b) => {
|
|
2001
|
+
const byLocale = a.locale.localeCompare(b.locale);
|
|
2002
|
+
if (byLocale !== 0) return byLocale;
|
|
2003
|
+
return a.relativePath.localeCompare(b.relativePath);
|
|
2004
|
+
});
|
|
2005
|
+
return { segments, missingLocaleCodes };
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
// src/shared/locales/read/cache.ts
|
|
2009
|
+
function createLocaleReadCache() {
|
|
2010
|
+
return {
|
|
2011
|
+
segments: /* @__PURE__ */ new Map(),
|
|
2012
|
+
localeCodes: /* @__PURE__ */ new Map()
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
function invalidateLocaleReadCacheForAbsolutePath(ctx, absolutePath) {
|
|
2016
|
+
ctx.localeRead.segments.delete(absolutePath);
|
|
2017
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
2018
|
+
const ref = localeSegmentRefFromAbsolute({
|
|
2019
|
+
layout,
|
|
2020
|
+
path: ctx.adapters.path,
|
|
2021
|
+
absolutePath
|
|
2022
|
+
});
|
|
2023
|
+
if (ref !== null) {
|
|
2024
|
+
ctx.localeRead.localeCodes.delete(normalizeLanguageCode(ref.locale));
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
function dropLocaleCodeReadCache(ctx, localeCode) {
|
|
2028
|
+
ctx.localeRead.localeCodes.delete(normalizeLanguageCode(localeCode));
|
|
2029
|
+
}
|
|
2030
|
+
function invalidateLocaleReadCacheForLocaleCode(ctx, localeCode) {
|
|
2031
|
+
const normalized = normalizeLanguageCode(localeCode);
|
|
2032
|
+
dropLocaleCodeReadCache(ctx, normalized);
|
|
2033
|
+
for (const segment of segmentsForLocaleCode(ctx, normalized)) {
|
|
2034
|
+
ctx.localeRead.segments.delete(segment.absolutePath);
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
// src/shared/locales/read/fromContext.ts
|
|
2039
|
+
function storeSegmentSnapshot(ctx, absoluteFile, snapshot) {
|
|
2040
|
+
ctx.localeRead.segments.set(absoluteFile, snapshot);
|
|
2041
|
+
if (snapshot.ok) {
|
|
2042
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
2043
|
+
const ref = localeSegmentRefFromAbsolute({
|
|
2044
|
+
layout,
|
|
2045
|
+
path: ctx.adapters.path,
|
|
2046
|
+
absolutePath: absoluteFile
|
|
2047
|
+
});
|
|
2048
|
+
if (ref !== null) {
|
|
2049
|
+
dropLocaleCodeReadCache(ctx, ref.locale);
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
function segmentSnapshotToResult(snapshot) {
|
|
2054
|
+
if (snapshot.ok) {
|
|
2055
|
+
return {
|
|
2056
|
+
ok: true,
|
|
2057
|
+
document: snapshot.document,
|
|
2058
|
+
leaves: snapshot.leaves,
|
|
2059
|
+
text: snapshot.text,
|
|
2060
|
+
diagnostics: []
|
|
2061
|
+
};
|
|
2062
|
+
}
|
|
2063
|
+
return { ok: false, leaves: [], diagnostics: snapshot.diagnostics };
|
|
2064
|
+
}
|
|
2065
|
+
function readLocaleSegmentFromContext(ctx, absoluteFile, onDiagnostic) {
|
|
2066
|
+
const cached = ctx.localeRead.segments.get(absoluteFile);
|
|
2067
|
+
if (cached !== void 0) {
|
|
2068
|
+
return segmentSnapshotToResult(cached);
|
|
2069
|
+
}
|
|
2070
|
+
const result = readLocaleBundle({
|
|
2071
|
+
layout: resolveLocalesLayoutFromContext(ctx),
|
|
2072
|
+
fs: ctx.adapters.fs,
|
|
2073
|
+
path: ctx.adapters.path,
|
|
2074
|
+
absoluteFile,
|
|
2075
|
+
onDiagnostic
|
|
2076
|
+
});
|
|
2077
|
+
if (result.ok) {
|
|
2078
|
+
storeSegmentSnapshot(ctx, absoluteFile, {
|
|
2079
|
+
ok: true,
|
|
2080
|
+
absolutePath: absoluteFile,
|
|
2081
|
+
document: result.document,
|
|
2082
|
+
leaves: result.leaves,
|
|
2083
|
+
text: result.text
|
|
2084
|
+
});
|
|
2085
|
+
} else {
|
|
2086
|
+
storeSegmentSnapshot(ctx, absoluteFile, {
|
|
2087
|
+
ok: false,
|
|
2088
|
+
absolutePath: absoluteFile,
|
|
2089
|
+
diagnostics: result.diagnostics
|
|
2090
|
+
});
|
|
2091
|
+
}
|
|
2092
|
+
return result;
|
|
2093
|
+
}
|
|
2094
|
+
function storeLocaleCodeSnapshot(ctx, snapshot) {
|
|
2095
|
+
ctx.localeRead.localeCodes.set(normalizeLanguageCode(snapshot.localeCode), snapshot);
|
|
2096
|
+
}
|
|
2097
|
+
function readLocaleCodeSurfaceFromContext(ctx, localeCode, onDiagnostic) {
|
|
2098
|
+
const normalized = normalizeLanguageCode(localeCode);
|
|
2099
|
+
const cached = ctx.localeRead.localeCodes.get(normalized);
|
|
2100
|
+
if (cached !== void 0) {
|
|
2101
|
+
return {
|
|
2102
|
+
ok: true,
|
|
2103
|
+
document: cached.document,
|
|
2104
|
+
leaves: cached.leaves,
|
|
2105
|
+
text: "",
|
|
2106
|
+
diagnostics: []
|
|
2107
|
+
};
|
|
2108
|
+
}
|
|
2109
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
2110
|
+
if (layout.mode === "flat_file") {
|
|
2111
|
+
const segment = primarySegmentForLocale(ctx, normalized);
|
|
2112
|
+
const absoluteFile = segment?.absolutePath ?? ctx.paths.sourceLocale;
|
|
2113
|
+
const read = readLocaleSegmentFromContext(ctx, absoluteFile, onDiagnostic);
|
|
2114
|
+
if (!read.ok) return read;
|
|
2115
|
+
storeLocaleCodeSnapshot(ctx, {
|
|
2116
|
+
localeCode: normalized,
|
|
2117
|
+
document: read.document,
|
|
2118
|
+
leaves: read.leaves
|
|
2119
|
+
});
|
|
2120
|
+
return read;
|
|
2121
|
+
}
|
|
2122
|
+
const diagnostics = [];
|
|
2123
|
+
const { segments, diagnostics: listDiagnostics } = listLocaleSegments({
|
|
2124
|
+
layout,
|
|
2125
|
+
fs: ctx.adapters.fs,
|
|
2126
|
+
path: ctx.adapters.path
|
|
2127
|
+
});
|
|
2128
|
+
diagnostics.push(...listDiagnostics);
|
|
2129
|
+
const forLocale = segments.filter((s) => normalizeLanguageCode(s.locale) === normalized);
|
|
2130
|
+
if (forLocale.length === 0) {
|
|
2131
|
+
const empty = { localeCode: normalized, document: {}, leaves: [] };
|
|
2132
|
+
storeLocaleCodeSnapshot(ctx, empty);
|
|
2133
|
+
return { ok: true, document: {}, leaves: [], text: "{}", diagnostics };
|
|
2134
|
+
}
|
|
2135
|
+
const allLeaves = [];
|
|
2136
|
+
const documents = [];
|
|
2137
|
+
let combinedText = "";
|
|
2138
|
+
for (const segment of forLocale) {
|
|
2139
|
+
const read = readLocaleSegmentFromContext(ctx, segment.absolutePath, onDiagnostic);
|
|
2140
|
+
diagnostics.push(...read.diagnostics);
|
|
2141
|
+
if (!read.ok) return { ok: false, leaves: [], diagnostics };
|
|
2142
|
+
allLeaves.push(...read.leaves);
|
|
2143
|
+
documents.push(read.document);
|
|
2144
|
+
combinedText = read.text;
|
|
2145
|
+
}
|
|
2146
|
+
const document = documents.length === 1 ? documents[0] : documents;
|
|
2147
|
+
storeLocaleCodeSnapshot(ctx, {
|
|
2148
|
+
localeCode: normalized,
|
|
2149
|
+
document,
|
|
2150
|
+
leaves: allLeaves
|
|
2151
|
+
});
|
|
2152
|
+
return {
|
|
2153
|
+
ok: true,
|
|
2154
|
+
document,
|
|
2155
|
+
leaves: allLeaves,
|
|
2156
|
+
text: combinedText,
|
|
2157
|
+
diagnostics
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2160
|
+
function readLocaleJsonFromContextSync(ctx, absoluteFile) {
|
|
2161
|
+
const read = readLocaleSegmentFromContext(ctx, absoluteFile);
|
|
2162
|
+
if (!read.ok) {
|
|
2163
|
+
const message = read.diagnostics.map((d) => d.message).join(" \xB7 ") || "failed to read locale JSON";
|
|
2164
|
+
throw new I18nPruneError(message, "IO", { issueCode: ISSUE_IO_READ_FAILED });
|
|
2165
|
+
}
|
|
2166
|
+
return read.document;
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
// src/shared/locales/read/perDirLocaleSurface.ts
|
|
2170
|
+
function readLocalePerDirLocaleSurface(input) {
|
|
2171
|
+
const diagnostics = [];
|
|
2172
|
+
const emit = (d) => {
|
|
2173
|
+
diagnostics.push(d);
|
|
2174
|
+
input.onDiagnostic?.(d);
|
|
2175
|
+
};
|
|
2176
|
+
const { segments, diagnostics: listDiagnostics } = listLocaleSegments({
|
|
2177
|
+
layout: input.layout,
|
|
2178
|
+
fs: input.fs,
|
|
2179
|
+
path: input.path
|
|
2180
|
+
});
|
|
2181
|
+
diagnostics.push(...listDiagnostics);
|
|
2182
|
+
const forLocale = segments.filter((s) => s.locale === input.localeCode);
|
|
2183
|
+
if (forLocale.length === 0) {
|
|
2184
|
+
emit({
|
|
2185
|
+
level: "warn",
|
|
2186
|
+
code: "locale_segment_not_found",
|
|
2187
|
+
message: `no locale segments found for code ${input.localeCode}`
|
|
2188
|
+
});
|
|
2189
|
+
return { ok: true, document: {}, leaves: [], text: "{}", diagnostics };
|
|
2190
|
+
}
|
|
2191
|
+
const allLeaves = [];
|
|
2192
|
+
const documents = [];
|
|
2193
|
+
let combinedText = "";
|
|
2194
|
+
for (const segment of forLocale) {
|
|
2195
|
+
const read = readFlatLocaleJsonSurface({
|
|
2196
|
+
fs: input.fs,
|
|
2197
|
+
path: input.path,
|
|
2198
|
+
absoluteFile: segment.absolutePath,
|
|
2199
|
+
localesDir: input.layout.directoryAbsolute,
|
|
2200
|
+
structure: input.layout.structure,
|
|
2201
|
+
onDiagnostic: input.onDiagnostic
|
|
2202
|
+
});
|
|
2203
|
+
diagnostics.push(...read.diagnostics);
|
|
2204
|
+
if (!read.ok) return { ok: false, leaves: [], diagnostics };
|
|
2205
|
+
allLeaves.push(...read.leaves);
|
|
2206
|
+
documents.push(read.document);
|
|
2207
|
+
combinedText = read.text;
|
|
2208
|
+
}
|
|
2209
|
+
return {
|
|
2210
|
+
ok: true,
|
|
2211
|
+
document: documents.length === 1 ? documents[0] : documents,
|
|
2212
|
+
leaves: allLeaves,
|
|
2213
|
+
text: combinedText,
|
|
2214
|
+
diagnostics
|
|
2215
|
+
};
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
// src/shared/locales/write/index.ts
|
|
2219
|
+
var write_exports = {};
|
|
2220
|
+
__export(write_exports, {
|
|
2221
|
+
writeFlatLocaleJsonDocument: () => writeFlatLocaleJsonDocument,
|
|
2222
|
+
writeLocaleBundle: () => writeLocaleBundle,
|
|
2223
|
+
writeLocaleJsonFromContextSync: () => writeLocaleJsonFromContextSync
|
|
2224
|
+
});
|
|
2225
|
+
|
|
2226
|
+
// src/shared/json/sortKeys.ts
|
|
2227
|
+
function isPlainObject6(x) {
|
|
2228
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
2229
|
+
}
|
|
2230
|
+
function sortJsonObjectKeysAsc(value) {
|
|
2231
|
+
if (Array.isArray(value)) {
|
|
2232
|
+
return value.map((item) => sortJsonObjectKeysAsc(item));
|
|
2233
|
+
}
|
|
2234
|
+
if (!isPlainObject6(value)) return value;
|
|
2235
|
+
const sorted = {};
|
|
2236
|
+
for (const key of Object.keys(value).sort()) {
|
|
2237
|
+
sorted[key] = sortJsonObjectKeysAsc(value[key]);
|
|
2238
|
+
}
|
|
2239
|
+
return sorted;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
// src/shared/locales/write/flatFileLocaleJson.ts
|
|
2243
|
+
function writeFlatLocaleJsonDocument(input) {
|
|
2244
|
+
const diagnostics = [];
|
|
2245
|
+
const emit = (d) => {
|
|
2246
|
+
diagnostics.push(d);
|
|
2247
|
+
input.onDiagnostic?.(d);
|
|
2248
|
+
};
|
|
2249
|
+
const indent = input.indent ?? 2;
|
|
2250
|
+
let body;
|
|
2251
|
+
try {
|
|
2252
|
+
body = `${JSON.stringify(sortJsonObjectKeysAsc(input.data), null, indent)}
|
|
2253
|
+
`;
|
|
2254
|
+
} catch (e) {
|
|
2255
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
2256
|
+
emit({ level: "error", code: "locale_json_serialize_failed", message, path: input.absoluteFile });
|
|
2257
|
+
return { ok: false, diagnostics };
|
|
2258
|
+
}
|
|
2259
|
+
try {
|
|
2260
|
+
input.fs.mkdirp(input.path.dirname(input.absoluteFile));
|
|
2261
|
+
input.fs.writeText(input.absoluteFile, body);
|
|
2262
|
+
return { ok: true, diagnostics };
|
|
2263
|
+
} catch (e) {
|
|
2264
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
2265
|
+
emit({ level: "error", code: "locale_fs_write_failed", message, path: input.absoluteFile });
|
|
2266
|
+
return { ok: false, diagnostics };
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
// src/shared/locales/write/bundle.ts
|
|
2271
|
+
function writeLocaleBundle(input) {
|
|
2272
|
+
const diagnostics = [];
|
|
2273
|
+
const emit = (d) => {
|
|
2274
|
+
diagnostics.push(d);
|
|
2275
|
+
input.onDiagnostic?.(d);
|
|
2276
|
+
};
|
|
2277
|
+
if (!isLocalesLayoutWriteSupported(input.layout)) {
|
|
2278
|
+
emit({
|
|
2279
|
+
level: "error",
|
|
2280
|
+
code: "locale_layout_unsupported",
|
|
2281
|
+
message: `locale write is not implemented for mode=${input.layout.mode} structure=${input.layout.structure}`,
|
|
2282
|
+
path: input.absoluteFile
|
|
2283
|
+
});
|
|
2284
|
+
return { ok: false, diagnostics };
|
|
2285
|
+
}
|
|
2286
|
+
const segmentRef = localeSegmentRefFromAbsolute({
|
|
2287
|
+
layout: input.layout,
|
|
2288
|
+
path: input.path,
|
|
2289
|
+
absolutePath: input.absoluteFile
|
|
2290
|
+
});
|
|
2291
|
+
if (segmentRef === null) {
|
|
2292
|
+
emit({
|
|
2293
|
+
level: "warn",
|
|
2294
|
+
code: "locale_write_path_layout_mismatch",
|
|
2295
|
+
message: `path does not match configured layout mode=${input.layout.mode} structure=${input.layout.structure}`,
|
|
2296
|
+
path: input.absoluteFile
|
|
2297
|
+
});
|
|
2298
|
+
return { ok: false, diagnostics };
|
|
2299
|
+
}
|
|
2300
|
+
return writeFlatLocaleJsonDocument({
|
|
2301
|
+
fs: input.fs,
|
|
2302
|
+
path: input.path,
|
|
2303
|
+
absoluteFile: input.absoluteFile,
|
|
2304
|
+
data: input.data,
|
|
2305
|
+
indent: input.indent,
|
|
2306
|
+
onDiagnostic: input.onDiagnostic
|
|
2307
|
+
});
|
|
2308
|
+
}
|
|
2309
|
+
function writeLocaleJsonFromContextSync(ctx, absoluteFile, data) {
|
|
2310
|
+
const result = writeLocaleBundle({
|
|
2311
|
+
layout: resolveLocalesLayoutFromContext(ctx),
|
|
2312
|
+
fs: ctx.adapters.fs,
|
|
2313
|
+
path: ctx.adapters.path,
|
|
2314
|
+
absoluteFile,
|
|
2315
|
+
data
|
|
2316
|
+
});
|
|
2317
|
+
if (!result.ok) {
|
|
2318
|
+
const message = result.diagnostics.map((d) => d.message).join(" \xB7 ") || "failed to write locale JSON";
|
|
2319
|
+
throw new I18nPruneError(message, "IO", { issueCode: ISSUE_IO_READ_FAILED });
|
|
2320
|
+
}
|
|
2321
|
+
invalidateLocaleReadCacheForAbsolutePath(ctx, absoluteFile);
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
// src/shared/projects/index.ts
|
|
2325
|
+
var projects_exports = {};
|
|
2326
|
+
__export(projects_exports, {
|
|
2327
|
+
translationSurfacePathValueMap: () => translationSurfacePathValueMap
|
|
2328
|
+
});
|
|
2329
|
+
|
|
2330
|
+
// src/shared/projects/localeSurfaceMap.ts
|
|
2331
|
+
function translationSurfacePathValueMap(localeJson) {
|
|
2332
|
+
const m = /* @__PURE__ */ new Map();
|
|
2333
|
+
for (const row of collectTranslationSurfaceLeaves(localeJson)) {
|
|
2334
|
+
m.set(row.path, row.value);
|
|
2335
|
+
}
|
|
2336
|
+
return m;
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
// src/shared/sourcePlaceholders/index.ts
|
|
2340
|
+
var sourcePlaceholders_exports = {};
|
|
2341
|
+
__export(sourcePlaceholders_exports, {
|
|
2342
|
+
detectLocalePlaceholderLeaves: () => detectLocalePlaceholderLeaves,
|
|
2343
|
+
detectSourcePlaceholderLeaves: () => detectSourcePlaceholderLeaves,
|
|
2344
|
+
formatSourcePlaceholderMessage: () => formatSourcePlaceholderMessage,
|
|
2345
|
+
formatSyncSourcePlaceholderMessage: () => formatSyncSourcePlaceholderMessage,
|
|
2346
|
+
formatTargetPlaceholderMessage: () => formatTargetPlaceholderMessage,
|
|
2347
|
+
issuesFromSourcePlaceholderLeaves: () => issuesFromSourcePlaceholderLeaves,
|
|
2348
|
+
issuesFromTargetPlaceholderLeaves: () => issuesFromTargetPlaceholderLeaves,
|
|
2349
|
+
sourcePlaceholderValues: () => sourcePlaceholderValues
|
|
2350
|
+
});
|
|
2351
|
+
|
|
2352
|
+
// src/shared/constants/missing.ts
|
|
2353
|
+
var DEFAULT_MISSING_LEAF_PLACEHOLDER = "__I18NPRUNE_MISSING__";
|
|
2354
|
+
var MAX_MISSING_TARGET_SUGGESTIONS = 3;
|
|
2355
|
+
|
|
2356
|
+
// src/missing/placeholder.ts
|
|
2357
|
+
var MISSING_LEAF_PLACEHOLDER_MAX_LEN = 256;
|
|
2358
|
+
function resolveMissingLeafPlaceholder(raw) {
|
|
2359
|
+
const warnings = [];
|
|
2360
|
+
const def = DEFAULT_MISSING_LEAF_PLACEHOLDER;
|
|
2361
|
+
if (raw === void 0) return { placeholder: def, warnings };
|
|
2362
|
+
if (typeof raw !== "string") {
|
|
2363
|
+
warnings.push(
|
|
2364
|
+
`missing.placeholder must be a string; got ${typeof raw}. Using default ${JSON.stringify(def)} for reliable detection.`
|
|
2365
|
+
);
|
|
2366
|
+
return { placeholder: def, warnings };
|
|
2367
|
+
}
|
|
2368
|
+
const t = raw.trim();
|
|
2369
|
+
if (t.length === 0) {
|
|
2370
|
+
warnings.push(
|
|
2371
|
+
`missing.placeholder is empty or whitespace-only; using default ${JSON.stringify(def)} so missing tooling can detect scaffolded paths.`
|
|
2372
|
+
);
|
|
2373
|
+
return { placeholder: def, warnings };
|
|
2374
|
+
}
|
|
2375
|
+
if (t.length > MISSING_LEAF_PLACEHOLDER_MAX_LEN) {
|
|
2376
|
+
warnings.push(
|
|
2377
|
+
`missing.placeholder exceeds ${String(MISSING_LEAF_PLACEHOLDER_MAX_LEN)} characters; using default ${JSON.stringify(def)}.`
|
|
2378
|
+
);
|
|
2379
|
+
return { placeholder: def, warnings };
|
|
2380
|
+
}
|
|
2381
|
+
return { placeholder: t, warnings };
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
// src/shared/sourcePlaceholders/index.ts
|
|
2385
|
+
function sourcePlaceholderValues(configuredPlaceholder) {
|
|
2386
|
+
const resolved = resolveMissingLeafPlaceholder(configuredPlaceholder).placeholder;
|
|
2387
|
+
return [...new Set([DEFAULT_MISSING_LEAF_PLACEHOLDER, resolved].filter((value) => value.trim().length > 0))];
|
|
2388
|
+
}
|
|
2389
|
+
function detectSourcePlaceholderLeaves(leaves, placeholderValues) {
|
|
2390
|
+
const sentinels = new Set(placeholderValues);
|
|
2391
|
+
if (sentinels.size === 0) return [];
|
|
2392
|
+
return leaves.filter((leaf) => sentinels.has(leaf.value)).map((leaf) => ({ path: leaf.path, value: leaf.value }));
|
|
2393
|
+
}
|
|
2394
|
+
function detectLocalePlaceholderLeaves(input) {
|
|
2395
|
+
return detectSourcePlaceholderLeaves(input.leaves, input.placeholderValues).map((leaf) => ({
|
|
2396
|
+
...leaf,
|
|
2397
|
+
localeRole: input.localeRole,
|
|
2398
|
+
localeCode: input.localeCode,
|
|
2399
|
+
...input.localePath !== void 0 ? { localePath: input.localePath } : {}
|
|
2400
|
+
}));
|
|
2401
|
+
}
|
|
2402
|
+
function formatSourcePlaceholderMessage(input) {
|
|
2403
|
+
const sample = input.samplePaths.join(", ");
|
|
2404
|
+
return `Source locale has ${String(input.count)} missing placeholder value(s). Run \`i18nprune missing --full\` to list placeholder paths. Replace them with real source copy, then run \`i18nprune sync\` and \`i18nprune generate --resume\` for target locales. Sample paths: ${sample}`;
|
|
2405
|
+
}
|
|
2406
|
+
function formatSyncSourcePlaceholderMessage(input) {
|
|
2407
|
+
const sample = input.samplePaths.join(", ");
|
|
2408
|
+
return `Source locale has ${String(input.count)} missing placeholder value(s); sync skipped those path(s) so placeholders are not copied to target locales. Run \`i18nprune missing --full\` to list placeholder paths. Replace them with real source copy, then run \`i18nprune sync\` and \`i18nprune generate --resume\`. Sample paths: ${sample}`;
|
|
2409
|
+
}
|
|
2410
|
+
function formatTargetPlaceholderMessage(input) {
|
|
2411
|
+
const sample = input.samplePaths.join(", ");
|
|
2412
|
+
const target = input.targetLabel === void 0 ? "Target locale" : `Target locale ${input.targetLabel}`;
|
|
2413
|
+
const listCommand = input.targetLabel === void 0 ? "i18nprune missing --target all --full" : `i18nprune missing --target ${input.targetLabel} --full`;
|
|
2414
|
+
return `${target} has ${String(input.count)} missing placeholder value(s). Run \`${listCommand}\` to list placeholder paths, then \`i18nprune sync\` and \`i18nprune generate --resume\` to refill translations. Sample paths: ${sample}`;
|
|
2415
|
+
}
|
|
2416
|
+
function issuesFromSourcePlaceholderLeaves(leaves) {
|
|
2417
|
+
if (leaves.length === 0) return [];
|
|
2418
|
+
return [
|
|
2419
|
+
{
|
|
2420
|
+
severity: "warning",
|
|
2421
|
+
code: ISSUE_LOCALE_SOURCE_PLACEHOLDER_LEAVES,
|
|
2422
|
+
message: formatSourcePlaceholderMessage({
|
|
2423
|
+
count: leaves.length,
|
|
2424
|
+
samplePaths: leaves.slice(0, 5).map((leaf) => leaf.path)
|
|
2425
|
+
}),
|
|
2426
|
+
docPath: issueCodeRepoDocPathForIssueCode(ISSUE_LOCALE_SOURCE_PLACEHOLDER_LEAVES)
|
|
2427
|
+
}
|
|
2428
|
+
];
|
|
2429
|
+
}
|
|
2430
|
+
function issuesFromTargetPlaceholderLeaves(leaves) {
|
|
2431
|
+
const targetLeaves = leaves.filter((leaf) => leaf.localeRole === "target");
|
|
2432
|
+
if (targetLeaves.length === 0) return [];
|
|
2433
|
+
return [
|
|
2434
|
+
{
|
|
2435
|
+
severity: "warning",
|
|
2436
|
+
code: ISSUE_LOCALE_TARGET_PLACEHOLDER_LEAVES,
|
|
2437
|
+
message: formatTargetPlaceholderMessage({
|
|
2438
|
+
count: targetLeaves.length,
|
|
2439
|
+
samplePaths: targetLeaves.slice(0, 5).map((leaf) => `${leaf.localeCode}:${leaf.path}`),
|
|
2440
|
+
...new Set(targetLeaves.map((leaf) => leaf.localeCode)).size === 1 ? { targetLabel: targetLeaves[0].localeCode } : {}
|
|
2441
|
+
}),
|
|
2442
|
+
docPath: issueCodeRepoDocPathForIssueCode(ISSUE_LOCALE_TARGET_PLACEHOLDER_LEAVES)
|
|
2443
|
+
}
|
|
2444
|
+
];
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
// src/shared/options/index.ts
|
|
2448
|
+
var options_exports = {};
|
|
2449
|
+
__export(options_exports, {
|
|
2450
|
+
LIST_WINDOW_DEFAULT_TOP: () => LIST_WINDOW_DEFAULT_TOP,
|
|
2451
|
+
LIST_WINDOW_HARD_CAP: () => LIST_WINDOW_HARD_CAP,
|
|
2452
|
+
applyListWindow: () => applyListWindow,
|
|
2453
|
+
getRunOptions: () => getRunOptions,
|
|
2454
|
+
resetRunOptions: () => resetRunOptions,
|
|
2455
|
+
resolveListWindow: () => resolveListWindow,
|
|
2456
|
+
setRunOptions: () => setRunOptions
|
|
2457
|
+
});
|
|
2458
|
+
|
|
2459
|
+
// src/shared/options/listWindow.ts
|
|
2460
|
+
var LIST_WINDOW_DEFAULT_TOP = 200;
|
|
2461
|
+
var LIST_WINDOW_HARD_CAP = 1e4;
|
|
2462
|
+
function clampPositiveInt(raw, fallback) {
|
|
2463
|
+
if (typeof raw !== "number" || !Number.isFinite(raw) || !Number.isInteger(raw) || raw < 1) {
|
|
2464
|
+
return fallback;
|
|
2465
|
+
}
|
|
2466
|
+
return raw;
|
|
2467
|
+
}
|
|
2468
|
+
function resolveListWindow(input, options) {
|
|
2469
|
+
const hardCap = clampPositiveInt(options?.hardCap, LIST_WINDOW_HARD_CAP);
|
|
2470
|
+
const defaultTopRaw = clampPositiveInt(options?.defaultTop, LIST_WINDOW_DEFAULT_TOP);
|
|
2471
|
+
const defaultTop = Math.min(defaultTopRaw, hardCap);
|
|
2472
|
+
if (input?.full === true) {
|
|
2473
|
+
return {
|
|
2474
|
+
top: hardCap,
|
|
2475
|
+
full: true,
|
|
2476
|
+
limit: hardCap,
|
|
2477
|
+
hardCap,
|
|
2478
|
+
clamped: false
|
|
2479
|
+
};
|
|
2480
|
+
}
|
|
2481
|
+
const requestedTop = input?.top;
|
|
2482
|
+
const top = clampPositiveInt(requestedTop, defaultTop);
|
|
2483
|
+
const limit = Math.min(top, hardCap);
|
|
2484
|
+
const isRequestedValidNumber = typeof requestedTop === "number" && Number.isFinite(requestedTop) && Number.isInteger(requestedTop);
|
|
2485
|
+
return {
|
|
2486
|
+
top,
|
|
2487
|
+
full: false,
|
|
2488
|
+
limit,
|
|
2489
|
+
hardCap,
|
|
2490
|
+
clamped: isRequestedValidNumber && requestedTop > hardCap
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
2493
|
+
function applyListWindow(items, window) {
|
|
2494
|
+
return items.slice(0, window.limit);
|
|
2495
|
+
}
|
|
2496
|
+
|
|
2497
|
+
// src/shared/run/index.ts
|
|
2498
|
+
var run_exports = {};
|
|
2499
|
+
__export(run_exports, {
|
|
2500
|
+
emitIssuesAsRunErrors: () => emitIssuesAsRunErrors,
|
|
2501
|
+
emitRunErrorFromUnknown: () => emitRunErrorFromUnknown,
|
|
2502
|
+
emitRunEvent: () => emitRunEvent,
|
|
2503
|
+
emitRunMessage: () => emitRunMessage,
|
|
2504
|
+
isProgressEvent: () => isProgressEvent,
|
|
2505
|
+
noopRunEmitter: () => noopRunEmitter,
|
|
2506
|
+
nowMs: () => nowMs
|
|
2507
|
+
});
|
|
2508
|
+
var noopRunEmitter = () => {
|
|
2509
|
+
};
|
|
2510
|
+
function emitRunEvent(emit, event) {
|
|
2511
|
+
if (!emit) return;
|
|
2512
|
+
try {
|
|
2513
|
+
emit(event);
|
|
2514
|
+
} catch {
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
function emitRunMessage(emit, input) {
|
|
2518
|
+
emitRunEvent(emit, {
|
|
2519
|
+
type: "run.message",
|
|
2520
|
+
op: input.op,
|
|
2521
|
+
runId: input.runId,
|
|
2522
|
+
at: input.at ?? nowMs(),
|
|
2523
|
+
level: input.level,
|
|
2524
|
+
...input.channel !== void 0 ? { channel: input.channel } : {},
|
|
2525
|
+
message: input.message,
|
|
2526
|
+
...input.target !== void 0 ? { target: input.target } : {},
|
|
2527
|
+
...input.path !== void 0 ? { path: input.path } : {},
|
|
2528
|
+
...input.data !== void 0 ? { data: input.data } : {}
|
|
2529
|
+
});
|
|
2530
|
+
}
|
|
2531
|
+
function nowMs() {
|
|
2532
|
+
return Date.now();
|
|
2533
|
+
}
|
|
2534
|
+
function isProgressEvent(event) {
|
|
2535
|
+
return event.type.startsWith("run.progress.");
|
|
2536
|
+
}
|
|
2537
|
+
function emitIssuesAsRunErrors(emit, input) {
|
|
2538
|
+
const at = input.at ?? nowMs();
|
|
2539
|
+
for (const issue of input.issues) {
|
|
2540
|
+
emitRunEvent(emit, {
|
|
2541
|
+
type: "run.error",
|
|
2542
|
+
op: input.op,
|
|
2543
|
+
runId: input.runId,
|
|
2544
|
+
at,
|
|
2545
|
+
issue,
|
|
2546
|
+
recoverable: input.recoverable
|
|
2547
|
+
});
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
function emitRunErrorFromUnknown(emit, input) {
|
|
2551
|
+
const normalized = normalizeUnknownError(input.err, {
|
|
2552
|
+
when: "Run error",
|
|
2553
|
+
defaultCode: "INTERNAL"
|
|
2554
|
+
});
|
|
2555
|
+
emitRunEvent(emit, {
|
|
2556
|
+
type: "run.error",
|
|
2557
|
+
op: input.op,
|
|
2558
|
+
runId: input.runId,
|
|
2559
|
+
at: input.at ?? nowMs(),
|
|
2560
|
+
issue: {
|
|
2561
|
+
severity: "error",
|
|
2562
|
+
code: input.code,
|
|
2563
|
+
message: normalized.message
|
|
2564
|
+
},
|
|
2565
|
+
recoverable: input.recoverable
|
|
2566
|
+
});
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
// src/shared/result/index.ts
|
|
2570
|
+
var result_exports = {};
|
|
2571
|
+
__export(result_exports, {
|
|
2572
|
+
DOCS_SITE_ORIGIN: () => DOCS_SITE_ORIGIN,
|
|
2573
|
+
buildCliJsonEnvelope: () => buildCliJsonEnvelope,
|
|
2574
|
+
enrichIssuesWithDocHrefs: () => enrichIssuesWithDocHrefs,
|
|
2575
|
+
issueCodeDocHref: () => issueCodeDocHref,
|
|
2576
|
+
normalizeRepoDocPath: () => normalizeRepoDocPath,
|
|
2577
|
+
resolveIssueCodeDocLink: () => resolveIssueCodeDocLink,
|
|
2578
|
+
stringifyCliCommandJson: () => stringifyCliCommandJson,
|
|
2579
|
+
stringifyEnvelope: () => stringifyEnvelope
|
|
2580
|
+
});
|
|
2581
|
+
|
|
2582
|
+
// src/shared/constants/result.ts
|
|
2583
|
+
var RESULT_API_VERSION = "1";
|
|
2584
|
+
|
|
2585
|
+
// src/shared/docs/urls.ts
|
|
2586
|
+
function parseDocsLinkInput(input) {
|
|
2587
|
+
const hashIdx = input.indexOf("#");
|
|
2588
|
+
const hash = hashIdx >= 0 ? input.slice(hashIdx) : "";
|
|
2589
|
+
let p = (hashIdx >= 0 ? input.slice(0, hashIdx) : input).trim().replace(/^\/+/, "");
|
|
2590
|
+
p = p.replace(/\/+$/g, "");
|
|
2591
|
+
if (p.endsWith(".md")) p = p.slice(0, -3);
|
|
2592
|
+
if (p.endsWith(".mdx")) p = p.slice(0, -4);
|
|
2593
|
+
if (p === "README" || p.endsWith("/README")) {
|
|
2594
|
+
p = p === "README" ? "" : p.slice(0, -"/README".length);
|
|
2595
|
+
}
|
|
2596
|
+
p = p.replace(/\/+$/g, "");
|
|
2597
|
+
p = p.replace(/\/+/g, "/");
|
|
2598
|
+
return { core: p, hash };
|
|
2599
|
+
}
|
|
2600
|
+
function docsCommandUrl(command) {
|
|
2601
|
+
const slug = command.trim().toLowerCase();
|
|
2602
|
+
return `${DOCS_SITE_BASE}/commands/${slug}`;
|
|
2603
|
+
}
|
|
2604
|
+
function getDocsUrl(path = "") {
|
|
2605
|
+
const { core, hash } = parseDocsLinkInput(path);
|
|
2606
|
+
if (!core) {
|
|
2607
|
+
return `${DOCS_SITE_BASE}${hash}`;
|
|
2608
|
+
}
|
|
2609
|
+
return `${DOCS_SITE_BASE}/${core}${hash}`;
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
// src/shared/docs/repoPaths.ts
|
|
2613
|
+
function normalizeRepoDocPath(docPath) {
|
|
2614
|
+
const t = docPath.trim();
|
|
2615
|
+
if (t === "") return t;
|
|
2616
|
+
if (t.startsWith("docs/")) return t;
|
|
2617
|
+
if (/^https?:\/\//i.test(t)) return t;
|
|
2618
|
+
return `docs/${t}`;
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
// src/shared/result/issueDocLinks.ts
|
|
2622
|
+
function enrichIssuesWithDocHrefs(issues) {
|
|
2623
|
+
return issues.map((issue) => {
|
|
2624
|
+
const withPath = issue.docPath !== void 0 ? { ...issue, docPath: normalizeRepoDocPath(issue.docPath) } : issue;
|
|
2625
|
+
if (!withPath.code.startsWith("i18nprune.")) return withPath;
|
|
2626
|
+
if (withPath.docHref !== void 0) return withPath;
|
|
2627
|
+
return { ...withPath, docHref: issueCodeDocHref(withPath.code) };
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
// src/shared/result/cliJson.ts
|
|
2632
|
+
function dataWithoutRedundantKind(envelopeKind, data) {
|
|
2633
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) return data;
|
|
2634
|
+
if (!("kind" in data)) return data;
|
|
2635
|
+
const k = data.kind;
|
|
2636
|
+
if (k !== envelopeKind) return data;
|
|
2637
|
+
const { kind: _omit, ...rest } = data;
|
|
2638
|
+
return rest;
|
|
2639
|
+
}
|
|
2640
|
+
function buildCliJsonEnvelope(kind, data, options) {
|
|
2641
|
+
return {
|
|
2642
|
+
ok: options.ok,
|
|
2643
|
+
kind,
|
|
2644
|
+
data: dataWithoutRedundantKind(kind, data),
|
|
2645
|
+
issues: enrichIssuesWithDocHrefs(options.issues ?? []),
|
|
2646
|
+
meta: {
|
|
2647
|
+
apiVersion: RESULT_API_VERSION,
|
|
2648
|
+
...options.schemaVersion !== void 0 ? { schemaVersion: options.schemaVersion } : {},
|
|
2649
|
+
...options.cwd !== void 0 ? { cwd: options.cwd } : {}
|
|
2650
|
+
}
|
|
2651
|
+
};
|
|
2652
|
+
}
|
|
2653
|
+
function stringifyCliCommandJson(input) {
|
|
2654
|
+
const { kind, data, ok, issues, cwd, pretty } = input;
|
|
2655
|
+
const resolvedPretty = pretty ?? getRunOptions().jsonPretty;
|
|
2656
|
+
const envelope = buildCliJsonEnvelope(kind, data, {
|
|
2657
|
+
ok,
|
|
2658
|
+
issues,
|
|
2659
|
+
...cwd !== void 0 ? { cwd } : {}
|
|
2660
|
+
});
|
|
2661
|
+
return resolvedPretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope);
|
|
2662
|
+
}
|
|
2663
|
+
function stringifyEnvelope(envelope, pretty) {
|
|
2664
|
+
const resolvedPretty = pretty ?? getRunOptions().jsonPretty;
|
|
2665
|
+
return resolvedPretty ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope);
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
// src/shared/languages/catalog/index.ts
|
|
2669
|
+
var catalog_exports = {};
|
|
2670
|
+
__export(catalog_exports, {
|
|
2671
|
+
buildLanguageCatalog: () => buildLanguageCatalog,
|
|
2672
|
+
filterLanguageCatalog: () => filterLanguageCatalog,
|
|
2673
|
+
generatedLanguageCatalog: () => generatedLanguageCatalog,
|
|
2674
|
+
getLanguageByCodeFromCatalog: () => getLanguageByCodeFromCatalog,
|
|
2675
|
+
suggestCatalogCodesForInvalidInputFromCatalog: () => suggestCatalogCodesForInvalidInputFromCatalog
|
|
2676
|
+
});
|
|
2677
|
+
|
|
2678
|
+
// src/shared/languages/catalog/languages.json
|
|
2679
|
+
var languages_default = [
|
|
2680
|
+
{
|
|
2681
|
+
code: "ab",
|
|
2682
|
+
english: "Abkhazian",
|
|
2683
|
+
native: "Abkhazian",
|
|
2684
|
+
direction: "ltr"
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
code: "ace",
|
|
2688
|
+
english: "Acehnese",
|
|
2689
|
+
native: "Acehnese",
|
|
2690
|
+
direction: "ltr"
|
|
2691
|
+
},
|
|
2692
|
+
{
|
|
2693
|
+
code: "ach",
|
|
2694
|
+
english: "Acoli",
|
|
2695
|
+
native: "Acoli",
|
|
2696
|
+
direction: "ltr"
|
|
2697
|
+
},
|
|
2698
|
+
{
|
|
2699
|
+
code: "af",
|
|
2700
|
+
english: "Afrikaans",
|
|
2701
|
+
native: "Afrikaans",
|
|
2702
|
+
direction: "ltr"
|
|
2703
|
+
},
|
|
2704
|
+
{
|
|
2705
|
+
code: "ak",
|
|
2706
|
+
english: "Akan",
|
|
2707
|
+
native: "Akan",
|
|
2708
|
+
direction: "ltr"
|
|
2709
|
+
},
|
|
2710
|
+
{
|
|
2711
|
+
code: "alz",
|
|
2712
|
+
english: "alz",
|
|
2713
|
+
native: "alz",
|
|
2714
|
+
direction: "ltr"
|
|
2715
|
+
},
|
|
2716
|
+
{
|
|
2717
|
+
code: "am",
|
|
2718
|
+
english: "Amharic",
|
|
2719
|
+
native: "\u12A0\u121B\u122D\u129B",
|
|
2720
|
+
direction: "ltr"
|
|
2721
|
+
},
|
|
2722
|
+
{
|
|
2723
|
+
code: "ar",
|
|
2724
|
+
english: "Arabic",
|
|
2725
|
+
native: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629",
|
|
2726
|
+
direction: "rtl"
|
|
2727
|
+
},
|
|
2728
|
+
{
|
|
2729
|
+
code: "ar-sa",
|
|
2730
|
+
english: "Arabic (Saudi Arabia)",
|
|
2731
|
+
native: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629 (\u0627\u0644\u0645\u0645\u0644\u0643\u0629 \u0627\u0644\u0639\u0631\u0628\u064A\u0629 \u0627\u0644\u0633\u0639\u0648\u062F\u064A\u0629)",
|
|
2732
|
+
direction: "rtl"
|
|
2733
|
+
},
|
|
2734
|
+
{
|
|
2735
|
+
code: "as",
|
|
2736
|
+
english: "Assamese",
|
|
2737
|
+
native: "\u0985\u09B8\u09AE\u09C0\u09AF\u09BC\u09BE",
|
|
2738
|
+
direction: "ltr"
|
|
2739
|
+
},
|
|
2740
|
+
{
|
|
2741
|
+
code: "awa",
|
|
2742
|
+
english: "Awadhi",
|
|
2743
|
+
native: "Awadhi",
|
|
2744
|
+
direction: "ltr"
|
|
2745
|
+
},
|
|
2746
|
+
{
|
|
2747
|
+
code: "ay",
|
|
2748
|
+
english: "Aymara",
|
|
2749
|
+
native: "Aymara",
|
|
2750
|
+
direction: "ltr"
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
code: "az",
|
|
2754
|
+
english: "Azerbaijani",
|
|
2755
|
+
native: "az\u0259rbaycan",
|
|
2756
|
+
direction: "ltr"
|
|
2757
|
+
},
|
|
2758
|
+
{
|
|
2759
|
+
code: "ba",
|
|
2760
|
+
english: "Bashkir",
|
|
2761
|
+
native: "Bashkir",
|
|
2762
|
+
direction: "ltr"
|
|
2763
|
+
},
|
|
2764
|
+
{
|
|
2765
|
+
code: "ban",
|
|
2766
|
+
english: "Balinese",
|
|
2767
|
+
native: "Balinese",
|
|
2768
|
+
direction: "ltr"
|
|
2769
|
+
},
|
|
2770
|
+
{
|
|
2771
|
+
code: "bbc",
|
|
2772
|
+
english: "Batak Toba",
|
|
2773
|
+
native: "Batak Toba",
|
|
2774
|
+
direction: "ltr"
|
|
2775
|
+
},
|
|
2776
|
+
{
|
|
2777
|
+
code: "be",
|
|
2778
|
+
english: "Belarusian",
|
|
2779
|
+
native: "\u0431\u0435\u043B\u0430\u0440\u0443\u0441\u043A\u0430\u044F",
|
|
2780
|
+
direction: "ltr"
|
|
2781
|
+
},
|
|
2782
|
+
{
|
|
2783
|
+
code: "bem",
|
|
2784
|
+
english: "Bemba",
|
|
2785
|
+
native: "Ichibemba",
|
|
2786
|
+
direction: "ltr"
|
|
2787
|
+
},
|
|
2788
|
+
{
|
|
2789
|
+
code: "bew",
|
|
2790
|
+
english: "Betawi",
|
|
2791
|
+
native: "Betawi",
|
|
2792
|
+
direction: "ltr"
|
|
2793
|
+
},
|
|
2794
|
+
{
|
|
2795
|
+
code: "bg",
|
|
2796
|
+
english: "Bulgarian",
|
|
2797
|
+
native: "\u0431\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438",
|
|
2798
|
+
direction: "ltr"
|
|
2799
|
+
},
|
|
2800
|
+
{
|
|
2801
|
+
code: "bho",
|
|
2802
|
+
english: "Bhojpuri",
|
|
2803
|
+
native: "\u092D\u094B\u091C\u092A\u0941\u0930\u0940",
|
|
2804
|
+
direction: "ltr"
|
|
2805
|
+
},
|
|
2806
|
+
{
|
|
2807
|
+
code: "bik",
|
|
2808
|
+
english: "Bikol",
|
|
2809
|
+
native: "Bikol",
|
|
2810
|
+
direction: "ltr"
|
|
2811
|
+
},
|
|
2812
|
+
{
|
|
2813
|
+
code: "bm",
|
|
2814
|
+
english: "Bambara",
|
|
2815
|
+
native: "bamanakan",
|
|
2816
|
+
direction: "ltr"
|
|
2817
|
+
},
|
|
2818
|
+
{
|
|
2819
|
+
code: "bn",
|
|
2820
|
+
english: "Bangla",
|
|
2821
|
+
native: "\u09AC\u09BE\u0982\u09B2\u09BE",
|
|
2822
|
+
direction: "ltr"
|
|
2823
|
+
},
|
|
2824
|
+
{
|
|
2825
|
+
code: "bn-in",
|
|
2826
|
+
english: "Bangla (India)",
|
|
2827
|
+
native: "\u09AC\u09BE\u0982\u09B2\u09BE (\u09AD\u09BE\u09B0\u09A4)",
|
|
2828
|
+
direction: "ltr"
|
|
2829
|
+
},
|
|
2830
|
+
{
|
|
2831
|
+
code: "br",
|
|
2832
|
+
english: "Breton",
|
|
2833
|
+
native: "brezhoneg",
|
|
2834
|
+
direction: "ltr"
|
|
2835
|
+
},
|
|
2836
|
+
{
|
|
2837
|
+
code: "bs",
|
|
2838
|
+
english: "Bosnian",
|
|
2839
|
+
native: "bosanski",
|
|
2840
|
+
direction: "ltr"
|
|
2841
|
+
},
|
|
2842
|
+
{
|
|
2843
|
+
code: "bs-cyrl",
|
|
2844
|
+
english: "Bosnian (Cyrillic)",
|
|
2845
|
+
native: "\u0431\u043E\u0441\u0430\u043D\u0441\u043A\u0438 (\u045B\u0438\u0440\u0438\u043B\u0438\u0446\u0430)",
|
|
2846
|
+
direction: "ltr"
|
|
2847
|
+
},
|
|
2848
|
+
{
|
|
2849
|
+
code: "bts",
|
|
2850
|
+
english: "bts",
|
|
2851
|
+
native: "bts",
|
|
2852
|
+
direction: "ltr"
|
|
2853
|
+
},
|
|
2854
|
+
{
|
|
2855
|
+
code: "btx",
|
|
2856
|
+
english: "btx",
|
|
2857
|
+
native: "btx",
|
|
2858
|
+
direction: "ltr"
|
|
2859
|
+
},
|
|
2860
|
+
{
|
|
2861
|
+
code: "bua",
|
|
2862
|
+
english: "Buriat",
|
|
2863
|
+
native: "Buriat",
|
|
2864
|
+
direction: "ltr"
|
|
2865
|
+
},
|
|
2866
|
+
{
|
|
2867
|
+
code: "ca",
|
|
2868
|
+
english: "Catalan",
|
|
2869
|
+
native: "catal\xE0",
|
|
2870
|
+
direction: "ltr"
|
|
2871
|
+
},
|
|
2872
|
+
{
|
|
2873
|
+
code: "ceb",
|
|
2874
|
+
english: "Cebuano",
|
|
2875
|
+
native: "Cebuano",
|
|
2876
|
+
direction: "ltr"
|
|
2877
|
+
},
|
|
2878
|
+
{
|
|
2879
|
+
code: "cgg",
|
|
2880
|
+
english: "Chiga",
|
|
2881
|
+
native: "Rukiga",
|
|
2882
|
+
direction: "ltr"
|
|
2883
|
+
},
|
|
2884
|
+
{
|
|
2885
|
+
code: "chm",
|
|
2886
|
+
english: "Mari",
|
|
2887
|
+
native: "Mari",
|
|
2888
|
+
direction: "ltr"
|
|
2889
|
+
},
|
|
2890
|
+
{
|
|
2891
|
+
code: "ckb",
|
|
2892
|
+
english: "Central Kurdish",
|
|
2893
|
+
native: "\u06A9\u0648\u0631\u062F\u06CC\u06CC \u0646\u0627\u0648\u06D5\u0646\u062F\u06CC",
|
|
2894
|
+
direction: "rtl"
|
|
2895
|
+
},
|
|
2896
|
+
{
|
|
2897
|
+
code: "cnh",
|
|
2898
|
+
english: "cnh",
|
|
2899
|
+
native: "cnh",
|
|
2900
|
+
direction: "ltr"
|
|
2901
|
+
},
|
|
2902
|
+
{
|
|
2903
|
+
code: "co",
|
|
2904
|
+
english: "Corsican",
|
|
2905
|
+
native: "Corsican",
|
|
2906
|
+
direction: "ltr"
|
|
2907
|
+
},
|
|
2908
|
+
{
|
|
2909
|
+
code: "crh",
|
|
2910
|
+
english: "Crimean Tatar",
|
|
2911
|
+
native: "Crimean Tatar",
|
|
2912
|
+
direction: "ltr"
|
|
2913
|
+
},
|
|
2914
|
+
{
|
|
2915
|
+
code: "crs",
|
|
2916
|
+
english: "Seselwa Creole French",
|
|
2917
|
+
native: "Seselwa Creole French",
|
|
2918
|
+
direction: "ltr"
|
|
2919
|
+
},
|
|
2920
|
+
{
|
|
2921
|
+
code: "cs",
|
|
2922
|
+
english: "Czech",
|
|
2923
|
+
native: "\u010De\u0161tina",
|
|
2924
|
+
direction: "ltr"
|
|
2925
|
+
},
|
|
2926
|
+
{
|
|
2927
|
+
code: "cv",
|
|
2928
|
+
english: "Chuvash",
|
|
2929
|
+
native: "\u0447\u04D1\u0432\u0430\u0448",
|
|
2930
|
+
direction: "ltr"
|
|
2931
|
+
},
|
|
2932
|
+
{
|
|
2933
|
+
code: "cy",
|
|
2934
|
+
english: "Welsh",
|
|
2935
|
+
native: "Cymraeg",
|
|
2936
|
+
direction: "ltr"
|
|
2937
|
+
},
|
|
2938
|
+
{
|
|
2939
|
+
code: "da",
|
|
2940
|
+
english: "Danish",
|
|
2941
|
+
native: "dansk",
|
|
2942
|
+
direction: "ltr"
|
|
2943
|
+
},
|
|
2944
|
+
{
|
|
2945
|
+
code: "de",
|
|
2946
|
+
english: "German",
|
|
2947
|
+
native: "Deutsch",
|
|
2948
|
+
direction: "ltr"
|
|
2949
|
+
},
|
|
2950
|
+
{
|
|
2951
|
+
code: "din",
|
|
2952
|
+
english: "Dinka",
|
|
2953
|
+
native: "Dinka",
|
|
2954
|
+
direction: "ltr"
|
|
2955
|
+
},
|
|
2956
|
+
{
|
|
2957
|
+
code: "doi",
|
|
2958
|
+
english: "Dogri",
|
|
2959
|
+
native: "\u0921\u094B\u0917\u0930\u0940",
|
|
2960
|
+
direction: "ltr"
|
|
2961
|
+
},
|
|
2962
|
+
{
|
|
2963
|
+
code: "dov",
|
|
2964
|
+
english: "dov",
|
|
2965
|
+
native: "dov",
|
|
2966
|
+
direction: "ltr"
|
|
2967
|
+
},
|
|
2968
|
+
{
|
|
2969
|
+
code: "dv",
|
|
2970
|
+
english: "Divehi",
|
|
2971
|
+
native: "Divehi",
|
|
2972
|
+
direction: "rtl"
|
|
2973
|
+
},
|
|
2974
|
+
{
|
|
2975
|
+
code: "dz",
|
|
2976
|
+
english: "Dzongkha",
|
|
2977
|
+
native: "\u0F62\u0FAB\u0F7C\u0F44\u0F0B\u0F41",
|
|
2978
|
+
direction: "ltr"
|
|
2979
|
+
},
|
|
2980
|
+
{
|
|
2981
|
+
code: "ee",
|
|
2982
|
+
english: "Ewe",
|
|
2983
|
+
native: "E\u028Begbe",
|
|
2984
|
+
direction: "ltr"
|
|
2985
|
+
},
|
|
2986
|
+
{
|
|
2987
|
+
code: "el",
|
|
2988
|
+
english: "Greek",
|
|
2989
|
+
native: "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC",
|
|
2990
|
+
direction: "ltr"
|
|
2991
|
+
},
|
|
2992
|
+
{
|
|
2993
|
+
code: "en",
|
|
2994
|
+
english: "English",
|
|
2995
|
+
native: "English",
|
|
2996
|
+
direction: "ltr"
|
|
2997
|
+
},
|
|
2998
|
+
{
|
|
2999
|
+
code: "en-au",
|
|
3000
|
+
english: "Australian English",
|
|
3001
|
+
native: "Australian English",
|
|
3002
|
+
direction: "ltr"
|
|
3003
|
+
},
|
|
3004
|
+
{
|
|
3005
|
+
code: "en-ca",
|
|
3006
|
+
english: "Canadian English",
|
|
3007
|
+
native: "Canadian English",
|
|
3008
|
+
direction: "ltr"
|
|
3009
|
+
},
|
|
3010
|
+
{
|
|
3011
|
+
code: "en-gb",
|
|
3012
|
+
english: "British English",
|
|
3013
|
+
native: "British English",
|
|
3014
|
+
direction: "ltr"
|
|
3015
|
+
},
|
|
3016
|
+
{
|
|
3017
|
+
code: "en-nz",
|
|
3018
|
+
english: "English (New Zealand)",
|
|
3019
|
+
native: "English (New Zealand)",
|
|
3020
|
+
direction: "ltr"
|
|
3021
|
+
},
|
|
3022
|
+
{
|
|
3023
|
+
code: "en-ph",
|
|
3024
|
+
english: "English (Philippines)",
|
|
3025
|
+
native: "English (Philippines)",
|
|
3026
|
+
direction: "ltr"
|
|
3027
|
+
},
|
|
3028
|
+
{
|
|
3029
|
+
code: "en-us",
|
|
3030
|
+
english: "American English",
|
|
3031
|
+
native: "American English",
|
|
3032
|
+
direction: "ltr"
|
|
3033
|
+
},
|
|
3034
|
+
{
|
|
3035
|
+
code: "en-za",
|
|
3036
|
+
english: "English (South Africa)",
|
|
3037
|
+
native: "English (South Africa)",
|
|
3038
|
+
direction: "ltr"
|
|
3039
|
+
},
|
|
3040
|
+
{
|
|
3041
|
+
code: "eo",
|
|
3042
|
+
english: "Esperanto",
|
|
3043
|
+
native: "Esperanto",
|
|
3044
|
+
direction: "ltr"
|
|
3045
|
+
},
|
|
3046
|
+
{
|
|
3047
|
+
code: "es",
|
|
3048
|
+
english: "Spanish",
|
|
3049
|
+
native: "espa\xF1ol",
|
|
3050
|
+
direction: "ltr"
|
|
3051
|
+
},
|
|
3052
|
+
{
|
|
3053
|
+
code: "es-419",
|
|
3054
|
+
english: "Latin American Spanish",
|
|
3055
|
+
native: "espa\xF1ol latinoamericano",
|
|
3056
|
+
direction: "ltr"
|
|
3057
|
+
},
|
|
3058
|
+
{
|
|
3059
|
+
code: "es-ar",
|
|
3060
|
+
english: "Spanish (Argentina)",
|
|
3061
|
+
native: "espa\xF1ol (Argentina)",
|
|
3062
|
+
direction: "ltr"
|
|
3063
|
+
},
|
|
3064
|
+
{
|
|
3065
|
+
code: "es-cl",
|
|
3066
|
+
english: "Spanish (Chile)",
|
|
3067
|
+
native: "espa\xF1ol (Chile)",
|
|
3068
|
+
direction: "ltr"
|
|
3069
|
+
},
|
|
3070
|
+
{
|
|
3071
|
+
code: "es-co",
|
|
3072
|
+
english: "Spanish (Colombia)",
|
|
3073
|
+
native: "espa\xF1ol (Colombia)",
|
|
3074
|
+
direction: "ltr"
|
|
3075
|
+
},
|
|
3076
|
+
{
|
|
3077
|
+
code: "es-cr",
|
|
3078
|
+
english: "Spanish (Costa Rica)",
|
|
3079
|
+
native: "espa\xF1ol (Costa Rica)",
|
|
3080
|
+
direction: "ltr"
|
|
3081
|
+
},
|
|
3082
|
+
{
|
|
3083
|
+
code: "es-ec",
|
|
3084
|
+
english: "Spanish (Ecuador)",
|
|
3085
|
+
native: "espa\xF1ol (Ecuador)",
|
|
3086
|
+
direction: "ltr"
|
|
3087
|
+
},
|
|
3088
|
+
{
|
|
3089
|
+
code: "es-es",
|
|
3090
|
+
english: "European Spanish",
|
|
3091
|
+
native: "espa\xF1ol de Espa\xF1a",
|
|
3092
|
+
direction: "ltr"
|
|
3093
|
+
},
|
|
3094
|
+
{
|
|
3095
|
+
code: "es-gt",
|
|
3096
|
+
english: "Spanish (Guatemala)",
|
|
3097
|
+
native: "espa\xF1ol (Guatemala)",
|
|
3098
|
+
direction: "ltr"
|
|
3099
|
+
},
|
|
3100
|
+
{
|
|
3101
|
+
code: "es-hn",
|
|
3102
|
+
english: "Spanish (Honduras)",
|
|
3103
|
+
native: "espa\xF1ol (Honduras)",
|
|
3104
|
+
direction: "ltr"
|
|
3105
|
+
},
|
|
3106
|
+
{
|
|
3107
|
+
code: "es-ht",
|
|
3108
|
+
english: "Spanish (Haiti)",
|
|
3109
|
+
native: "espa\xF1ol (Hait\xED)",
|
|
3110
|
+
direction: "ltr"
|
|
3111
|
+
},
|
|
3112
|
+
{
|
|
3113
|
+
code: "es-mx",
|
|
3114
|
+
english: "Mexican Spanish",
|
|
3115
|
+
native: "espa\xF1ol de M\xE9xico",
|
|
3116
|
+
direction: "ltr"
|
|
3117
|
+
},
|
|
3118
|
+
{
|
|
3119
|
+
code: "es-ni",
|
|
3120
|
+
english: "Spanish (Nicaragua)",
|
|
3121
|
+
native: "espa\xF1ol (Nicaragua)",
|
|
3122
|
+
direction: "ltr"
|
|
3123
|
+
},
|
|
3124
|
+
{
|
|
3125
|
+
code: "es-pa",
|
|
3126
|
+
english: "Spanish (Panama)",
|
|
3127
|
+
native: "espa\xF1ol (Panam\xE1)",
|
|
3128
|
+
direction: "ltr"
|
|
3129
|
+
},
|
|
3130
|
+
{
|
|
3131
|
+
code: "es-pe",
|
|
3132
|
+
english: "Spanish (Peru)",
|
|
3133
|
+
native: "espa\xF1ol (Per\xFA)",
|
|
3134
|
+
direction: "ltr"
|
|
3135
|
+
},
|
|
3136
|
+
{
|
|
3137
|
+
code: "es-pr",
|
|
3138
|
+
english: "Spanish (Puerto Rico)",
|
|
3139
|
+
native: "espa\xF1ol (Puerto Rico)",
|
|
3140
|
+
direction: "ltr"
|
|
3141
|
+
},
|
|
3142
|
+
{
|
|
3143
|
+
code: "es-py",
|
|
3144
|
+
english: "Spanish (Paraguay)",
|
|
3145
|
+
native: "espa\xF1ol (Paraguay)",
|
|
3146
|
+
direction: "ltr"
|
|
3147
|
+
},
|
|
3148
|
+
{
|
|
3149
|
+
code: "es-sv",
|
|
3150
|
+
english: "Spanish (El Salvador)",
|
|
3151
|
+
native: "espa\xF1ol (El Salvador)",
|
|
3152
|
+
direction: "ltr"
|
|
3153
|
+
},
|
|
3154
|
+
{
|
|
3155
|
+
code: "es-us",
|
|
3156
|
+
english: "Spanish (United States)",
|
|
3157
|
+
native: "espa\xF1ol (Estados Unidos)",
|
|
3158
|
+
direction: "ltr"
|
|
3159
|
+
},
|
|
3160
|
+
{
|
|
3161
|
+
code: "es-uy",
|
|
3162
|
+
english: "Spanish (Uruguay)",
|
|
3163
|
+
native: "espa\xF1ol (Uruguay)",
|
|
3164
|
+
direction: "ltr"
|
|
3165
|
+
},
|
|
3166
|
+
{
|
|
3167
|
+
code: "es-ve",
|
|
3168
|
+
english: "Spanish (Venezuela)",
|
|
3169
|
+
native: "espa\xF1ol (Venezuela)",
|
|
3170
|
+
direction: "ltr"
|
|
3171
|
+
},
|
|
3172
|
+
{
|
|
3173
|
+
code: "et",
|
|
3174
|
+
english: "Estonian",
|
|
3175
|
+
native: "eesti",
|
|
3176
|
+
direction: "ltr"
|
|
3177
|
+
},
|
|
3178
|
+
{
|
|
3179
|
+
code: "eu",
|
|
3180
|
+
english: "Basque",
|
|
3181
|
+
native: "euskara",
|
|
3182
|
+
direction: "ltr"
|
|
3183
|
+
},
|
|
3184
|
+
{
|
|
3185
|
+
code: "fa",
|
|
3186
|
+
english: "Persian",
|
|
3187
|
+
native: "\u0641\u0627\u0631\u0633\u06CC",
|
|
3188
|
+
direction: "rtl"
|
|
3189
|
+
},
|
|
3190
|
+
{
|
|
3191
|
+
code: "ff",
|
|
3192
|
+
english: "Fula",
|
|
3193
|
+
native: "Pulaar",
|
|
3194
|
+
direction: "rtl"
|
|
3195
|
+
},
|
|
3196
|
+
{
|
|
3197
|
+
code: "fi",
|
|
3198
|
+
english: "Finnish",
|
|
3199
|
+
native: "suomi",
|
|
3200
|
+
direction: "ltr"
|
|
3201
|
+
},
|
|
3202
|
+
{
|
|
3203
|
+
code: "fil",
|
|
3204
|
+
english: "Filipino",
|
|
3205
|
+
native: "Filipino",
|
|
3206
|
+
direction: "ltr"
|
|
3207
|
+
},
|
|
3208
|
+
{
|
|
3209
|
+
code: "fj",
|
|
3210
|
+
english: "Fijian",
|
|
3211
|
+
native: "Fijian",
|
|
3212
|
+
direction: "ltr"
|
|
3213
|
+
},
|
|
3214
|
+
{
|
|
3215
|
+
code: "fr",
|
|
3216
|
+
english: "French",
|
|
3217
|
+
native: "fran\xE7ais",
|
|
3218
|
+
direction: "ltr"
|
|
3219
|
+
},
|
|
3220
|
+
{
|
|
3221
|
+
code: "fr-ca",
|
|
3222
|
+
english: "Canadian French",
|
|
3223
|
+
native: "fran\xE7ais canadien",
|
|
3224
|
+
direction: "ltr"
|
|
3225
|
+
},
|
|
3226
|
+
{
|
|
3227
|
+
code: "fr-ch",
|
|
3228
|
+
english: "Swiss French",
|
|
3229
|
+
native: "fran\xE7ais suisse",
|
|
3230
|
+
direction: "ltr"
|
|
3231
|
+
},
|
|
3232
|
+
{
|
|
3233
|
+
code: "fr-fr",
|
|
3234
|
+
english: "French (France)",
|
|
3235
|
+
native: "fran\xE7ais (France)",
|
|
3236
|
+
direction: "ltr"
|
|
3237
|
+
},
|
|
3238
|
+
{
|
|
3239
|
+
code: "fy",
|
|
3240
|
+
english: "Western Frisian",
|
|
3241
|
+
native: "Frysk",
|
|
3242
|
+
direction: "ltr"
|
|
3243
|
+
},
|
|
3244
|
+
{
|
|
3245
|
+
code: "ga",
|
|
3246
|
+
english: "Irish",
|
|
3247
|
+
native: "Gaeilge",
|
|
3248
|
+
direction: "ltr"
|
|
3249
|
+
},
|
|
3250
|
+
{
|
|
3251
|
+
code: "gaa",
|
|
3252
|
+
english: "Ga",
|
|
3253
|
+
native: "Ga",
|
|
3254
|
+
direction: "ltr"
|
|
3255
|
+
},
|
|
3256
|
+
{
|
|
3257
|
+
code: "gd",
|
|
3258
|
+
english: "Scottish Gaelic",
|
|
3259
|
+
native: "G\xE0idhlig",
|
|
3260
|
+
direction: "ltr"
|
|
3261
|
+
},
|
|
3262
|
+
{
|
|
3263
|
+
code: "gl",
|
|
3264
|
+
english: "Galician",
|
|
3265
|
+
native: "galego",
|
|
3266
|
+
direction: "ltr"
|
|
3267
|
+
},
|
|
3268
|
+
{
|
|
3269
|
+
code: "gn",
|
|
3270
|
+
english: "Guarani",
|
|
3271
|
+
native: "Guarani",
|
|
3272
|
+
direction: "ltr"
|
|
3273
|
+
},
|
|
3274
|
+
{
|
|
3275
|
+
code: "gom",
|
|
3276
|
+
english: "Goan Konkani",
|
|
3277
|
+
native: "Goan Konkani",
|
|
3278
|
+
direction: "ltr"
|
|
3279
|
+
},
|
|
3280
|
+
{
|
|
3281
|
+
code: "gu",
|
|
3282
|
+
english: "Gujarati",
|
|
3283
|
+
native: "\u0A97\u0AC1\u0A9C\u0AB0\u0ABE\u0AA4\u0AC0",
|
|
3284
|
+
direction: "ltr"
|
|
3285
|
+
},
|
|
3286
|
+
{
|
|
3287
|
+
code: "ha",
|
|
3288
|
+
english: "Hausa",
|
|
3289
|
+
native: "Hausa",
|
|
3290
|
+
direction: "rtl"
|
|
3291
|
+
},
|
|
3292
|
+
{
|
|
3293
|
+
code: "haw",
|
|
3294
|
+
english: "Hawaiian",
|
|
3295
|
+
native: "\u02BB\u014Clelo Hawai\u02BBi",
|
|
3296
|
+
direction: "ltr"
|
|
3297
|
+
},
|
|
3298
|
+
{
|
|
3299
|
+
code: "he",
|
|
3300
|
+
english: "Hebrew",
|
|
3301
|
+
native: "\u05E2\u05D1\u05E8\u05D9\u05EA",
|
|
3302
|
+
direction: "rtl"
|
|
3303
|
+
},
|
|
3304
|
+
{
|
|
3305
|
+
code: "hi",
|
|
3306
|
+
english: "Hindi",
|
|
3307
|
+
native: "\u0939\u093F\u0928\u094D\u0926\u0940",
|
|
3308
|
+
direction: "ltr"
|
|
3309
|
+
},
|
|
3310
|
+
{
|
|
3311
|
+
code: "hil",
|
|
3312
|
+
english: "Hiligaynon",
|
|
3313
|
+
native: "Hiligaynon",
|
|
3314
|
+
direction: "ltr"
|
|
3315
|
+
},
|
|
3316
|
+
{
|
|
3317
|
+
code: "hmn",
|
|
3318
|
+
english: "Hmong",
|
|
3319
|
+
native: "Hmong",
|
|
3320
|
+
direction: "ltr"
|
|
3321
|
+
},
|
|
3322
|
+
{
|
|
3323
|
+
code: "hr",
|
|
3324
|
+
english: "Croatian",
|
|
3325
|
+
native: "hrvatski",
|
|
3326
|
+
direction: "ltr"
|
|
3327
|
+
},
|
|
3328
|
+
{
|
|
3329
|
+
code: "hrx",
|
|
3330
|
+
english: "hrx",
|
|
3331
|
+
native: "hrx",
|
|
3332
|
+
direction: "ltr"
|
|
3333
|
+
},
|
|
3334
|
+
{
|
|
3335
|
+
code: "ht",
|
|
3336
|
+
english: "Haitian Creole",
|
|
3337
|
+
native: "Haitian Creole",
|
|
3338
|
+
direction: "ltr"
|
|
3339
|
+
},
|
|
3340
|
+
{
|
|
3341
|
+
code: "hu",
|
|
3342
|
+
english: "Hungarian",
|
|
3343
|
+
native: "magyar",
|
|
3344
|
+
direction: "ltr"
|
|
3345
|
+
},
|
|
3346
|
+
{
|
|
3347
|
+
code: "hy",
|
|
3348
|
+
english: "Armenian",
|
|
3349
|
+
native: "\u0570\u0561\u0575\u0565\u0580\u0565\u0576",
|
|
3350
|
+
direction: "ltr"
|
|
3351
|
+
},
|
|
3352
|
+
{
|
|
3353
|
+
code: "id",
|
|
3354
|
+
english: "Indonesian",
|
|
3355
|
+
native: "Indonesia",
|
|
3356
|
+
direction: "ltr"
|
|
3357
|
+
},
|
|
3358
|
+
{
|
|
3359
|
+
code: "ig",
|
|
3360
|
+
english: "Igbo",
|
|
3361
|
+
native: "Igbo",
|
|
3362
|
+
direction: "ltr"
|
|
3363
|
+
},
|
|
3364
|
+
{
|
|
3365
|
+
code: "ilo",
|
|
3366
|
+
english: "Iloko",
|
|
3367
|
+
native: "Iloko",
|
|
3368
|
+
direction: "ltr"
|
|
3369
|
+
},
|
|
3370
|
+
{
|
|
3371
|
+
code: "is",
|
|
3372
|
+
english: "Icelandic",
|
|
3373
|
+
native: "\xEDslenska",
|
|
3374
|
+
direction: "ltr"
|
|
3375
|
+
},
|
|
3376
|
+
{
|
|
3377
|
+
code: "it",
|
|
3378
|
+
english: "Italian",
|
|
3379
|
+
native: "italiano",
|
|
3380
|
+
direction: "ltr"
|
|
3381
|
+
},
|
|
3382
|
+
{
|
|
3383
|
+
code: "iw",
|
|
3384
|
+
english: "Hebrew",
|
|
3385
|
+
native: "\u05E2\u05D1\u05E8\u05D9\u05EA",
|
|
3386
|
+
direction: "rtl"
|
|
3387
|
+
},
|
|
3388
|
+
{
|
|
3389
|
+
code: "ja",
|
|
3390
|
+
english: "Japanese",
|
|
3391
|
+
native: "\u65E5\u672C\u8A9E",
|
|
3392
|
+
direction: "ltr"
|
|
3393
|
+
},
|
|
3394
|
+
{
|
|
3395
|
+
code: "jv",
|
|
3396
|
+
english: "Javanese",
|
|
3397
|
+
native: "Jawa",
|
|
3398
|
+
direction: "ltr"
|
|
3399
|
+
},
|
|
3400
|
+
{
|
|
3401
|
+
code: "jw",
|
|
3402
|
+
english: "Javanese",
|
|
3403
|
+
native: "Jawa",
|
|
3404
|
+
direction: "ltr"
|
|
3405
|
+
},
|
|
3406
|
+
{
|
|
3407
|
+
code: "ka",
|
|
3408
|
+
english: "Georgian",
|
|
3409
|
+
native: "\u10E5\u10D0\u10E0\u10D7\u10E3\u10DA\u10D8",
|
|
3410
|
+
direction: "ltr"
|
|
3411
|
+
},
|
|
3412
|
+
{
|
|
3413
|
+
code: "kk",
|
|
3414
|
+
english: "Kazakh",
|
|
3415
|
+
native: "\u049B\u0430\u0437\u0430\u049B \u0442\u0456\u043B\u0456",
|
|
3416
|
+
direction: "ltr"
|
|
3417
|
+
},
|
|
3418
|
+
{
|
|
3419
|
+
code: "km",
|
|
3420
|
+
english: "Khmer",
|
|
3421
|
+
native: "\u1781\u17D2\u1798\u17C2\u179A",
|
|
3422
|
+
direction: "ltr"
|
|
3423
|
+
},
|
|
3424
|
+
{
|
|
3425
|
+
code: "kn",
|
|
3426
|
+
english: "Kannada",
|
|
3427
|
+
native: "\u0C95\u0CA8\u0CCD\u0CA8\u0CA1",
|
|
3428
|
+
direction: "ltr"
|
|
3429
|
+
},
|
|
3430
|
+
{
|
|
3431
|
+
code: "ko",
|
|
3432
|
+
english: "Korean",
|
|
3433
|
+
native: "\uD55C\uAD6D\uC5B4",
|
|
3434
|
+
direction: "ltr"
|
|
3435
|
+
},
|
|
3436
|
+
{
|
|
3437
|
+
code: "kri",
|
|
3438
|
+
english: "Krio",
|
|
3439
|
+
native: "Krio",
|
|
3440
|
+
direction: "ltr"
|
|
3441
|
+
},
|
|
3442
|
+
{
|
|
3443
|
+
code: "ktu",
|
|
3444
|
+
english: "ktu",
|
|
3445
|
+
native: "ktu",
|
|
3446
|
+
direction: "ltr"
|
|
3447
|
+
},
|
|
3448
|
+
{
|
|
3449
|
+
code: "ku",
|
|
3450
|
+
english: "Kurdish",
|
|
3451
|
+
native: "kurd\xEE (kurmanc\xEE)",
|
|
3452
|
+
direction: "ltr"
|
|
3453
|
+
},
|
|
3454
|
+
{
|
|
3455
|
+
code: "ky",
|
|
3456
|
+
english: "Kyrgyz",
|
|
3457
|
+
native: "\u043A\u044B\u0440\u0433\u044B\u0437\u0447\u0430",
|
|
3458
|
+
direction: "ltr"
|
|
3459
|
+
},
|
|
3460
|
+
{
|
|
3461
|
+
code: "la",
|
|
3462
|
+
english: "Latin",
|
|
3463
|
+
native: "Latin",
|
|
3464
|
+
direction: "ltr"
|
|
3465
|
+
},
|
|
3466
|
+
{
|
|
3467
|
+
code: "lb",
|
|
3468
|
+
english: "Luxembourgish",
|
|
3469
|
+
native: "L\xEBtzebuergesch",
|
|
3470
|
+
direction: "ltr"
|
|
3471
|
+
},
|
|
3472
|
+
{
|
|
3473
|
+
code: "lg",
|
|
3474
|
+
english: "Ganda",
|
|
3475
|
+
native: "Luganda",
|
|
3476
|
+
direction: "ltr"
|
|
3477
|
+
},
|
|
3478
|
+
{
|
|
3479
|
+
code: "li",
|
|
3480
|
+
english: "Limburgish",
|
|
3481
|
+
native: "Limburgish",
|
|
3482
|
+
direction: "ltr"
|
|
3483
|
+
},
|
|
3484
|
+
{
|
|
3485
|
+
code: "lij",
|
|
3486
|
+
english: "Ligurian",
|
|
3487
|
+
native: "ligure",
|
|
3488
|
+
direction: "ltr"
|
|
3489
|
+
},
|
|
3490
|
+
{
|
|
3491
|
+
code: "lmo",
|
|
3492
|
+
english: "Lombard",
|
|
3493
|
+
native: "Lombard",
|
|
3494
|
+
direction: "ltr"
|
|
3495
|
+
},
|
|
3496
|
+
{
|
|
3497
|
+
code: "ln",
|
|
3498
|
+
english: "Lingala",
|
|
3499
|
+
native: "ling\xE1la",
|
|
3500
|
+
direction: "ltr"
|
|
3501
|
+
},
|
|
3502
|
+
{
|
|
3503
|
+
code: "lo",
|
|
3504
|
+
english: "Lao",
|
|
3505
|
+
native: "\u0EA5\u0EB2\u0EA7",
|
|
3506
|
+
direction: "ltr"
|
|
3507
|
+
},
|
|
3508
|
+
{
|
|
3509
|
+
code: "lt",
|
|
3510
|
+
english: "Lithuanian",
|
|
3511
|
+
native: "lietuvi\u0173",
|
|
3512
|
+
direction: "ltr"
|
|
3513
|
+
},
|
|
3514
|
+
{
|
|
3515
|
+
code: "ltg",
|
|
3516
|
+
english: "Latgalian",
|
|
3517
|
+
native: "Latgalian",
|
|
3518
|
+
direction: "ltr"
|
|
3519
|
+
},
|
|
3520
|
+
{
|
|
3521
|
+
code: "luo",
|
|
3522
|
+
english: "Luo",
|
|
3523
|
+
native: "Dholuo",
|
|
3524
|
+
direction: "ltr"
|
|
3525
|
+
},
|
|
3526
|
+
{
|
|
3527
|
+
code: "lus",
|
|
3528
|
+
english: "Mizo",
|
|
3529
|
+
native: "Mizo",
|
|
3530
|
+
direction: "ltr"
|
|
3531
|
+
},
|
|
3532
|
+
{
|
|
3533
|
+
code: "lv",
|
|
3534
|
+
english: "Latvian",
|
|
3535
|
+
native: "latvie\u0161u",
|
|
3536
|
+
direction: "ltr"
|
|
3537
|
+
},
|
|
3538
|
+
{
|
|
3539
|
+
code: "mai",
|
|
3540
|
+
english: "Maithili",
|
|
3541
|
+
native: "\u092E\u0948\u0925\u093F\u0932\u0940",
|
|
3542
|
+
direction: "ltr"
|
|
3543
|
+
},
|
|
3544
|
+
{
|
|
3545
|
+
code: "mak",
|
|
3546
|
+
english: "Makasar",
|
|
3547
|
+
native: "Makasar",
|
|
3548
|
+
direction: "ltr"
|
|
3549
|
+
},
|
|
3550
|
+
{
|
|
3551
|
+
code: "mg",
|
|
3552
|
+
english: "Malagasy",
|
|
3553
|
+
native: "Malagasy",
|
|
3554
|
+
direction: "ltr"
|
|
3555
|
+
},
|
|
3556
|
+
{
|
|
3557
|
+
code: "mi",
|
|
3558
|
+
english: "M\u0101ori",
|
|
3559
|
+
native: "M\u0101ori",
|
|
3560
|
+
direction: "ltr"
|
|
3561
|
+
},
|
|
3562
|
+
{
|
|
3563
|
+
code: "min",
|
|
3564
|
+
english: "Minangkabau",
|
|
3565
|
+
native: "Minangkabau",
|
|
3566
|
+
direction: "ltr"
|
|
3567
|
+
},
|
|
3568
|
+
{
|
|
3569
|
+
code: "mk",
|
|
3570
|
+
english: "Macedonian",
|
|
3571
|
+
native: "\u043C\u0430\u043A\u0435\u0434\u043E\u043D\u0441\u043A\u0438",
|
|
3572
|
+
direction: "ltr"
|
|
3573
|
+
},
|
|
3574
|
+
{
|
|
3575
|
+
code: "ml",
|
|
3576
|
+
english: "Malayalam",
|
|
3577
|
+
native: "\u0D2E\u0D32\u0D2F\u0D3E\u0D33\u0D02",
|
|
3578
|
+
direction: "ltr"
|
|
3579
|
+
},
|
|
3580
|
+
{
|
|
3581
|
+
code: "mn",
|
|
3582
|
+
english: "Mongolian",
|
|
3583
|
+
native: "\u043C\u043E\u043D\u0433\u043E\u043B",
|
|
3584
|
+
direction: "ltr"
|
|
3585
|
+
},
|
|
3586
|
+
{
|
|
3587
|
+
code: "mni-mtei",
|
|
3588
|
+
english: "Manipuri (Meitei Mayek)",
|
|
3589
|
+
native: "\u09AE\u09C8\u09A4\u09C8\u09B2\u09CB\u09A8\u09CD (\u09AE\u09C0\u09A4\u09C8 \u09AE\u09AF\u09BC\u09C7\u0995)",
|
|
3590
|
+
direction: "ltr"
|
|
3591
|
+
},
|
|
3592
|
+
{
|
|
3593
|
+
code: "mr",
|
|
3594
|
+
english: "Marathi",
|
|
3595
|
+
native: "\u092E\u0930\u093E\u0920\u0940",
|
|
3596
|
+
direction: "ltr"
|
|
3597
|
+
},
|
|
3598
|
+
{
|
|
3599
|
+
code: "ms",
|
|
3600
|
+
english: "Malay",
|
|
3601
|
+
native: "Melayu",
|
|
3602
|
+
direction: "ltr"
|
|
3603
|
+
},
|
|
3604
|
+
{
|
|
3605
|
+
code: "ms-arab",
|
|
3606
|
+
english: "Malay (Arabic)",
|
|
3607
|
+
native: "Melayu (Arab)",
|
|
3608
|
+
direction: "ltr"
|
|
3609
|
+
},
|
|
3610
|
+
{
|
|
3611
|
+
code: "mt",
|
|
3612
|
+
english: "Maltese",
|
|
3613
|
+
native: "Malti",
|
|
3614
|
+
direction: "ltr"
|
|
3615
|
+
},
|
|
3616
|
+
{
|
|
3617
|
+
code: "my",
|
|
3618
|
+
english: "Burmese",
|
|
3619
|
+
native: "\u1019\u103C\u1014\u103A\u1019\u102C",
|
|
3620
|
+
direction: "ltr"
|
|
3621
|
+
},
|
|
3622
|
+
{
|
|
3623
|
+
code: "nb",
|
|
3624
|
+
english: "Norwegian Bokm\xE5l",
|
|
3625
|
+
native: "norsk bokm\xE5l",
|
|
3626
|
+
direction: "ltr"
|
|
3627
|
+
},
|
|
3628
|
+
{
|
|
3629
|
+
code: "ne",
|
|
3630
|
+
english: "Nepali",
|
|
3631
|
+
native: "\u0928\u0947\u092A\u093E\u0932\u0940",
|
|
3632
|
+
direction: "ltr"
|
|
3633
|
+
},
|
|
3634
|
+
{
|
|
3635
|
+
code: "new",
|
|
3636
|
+
english: "Newari",
|
|
3637
|
+
native: "Newari",
|
|
3638
|
+
direction: "ltr"
|
|
3639
|
+
},
|
|
3640
|
+
{
|
|
3641
|
+
code: "nl",
|
|
3642
|
+
english: "Dutch",
|
|
3643
|
+
native: "Nederlands",
|
|
3644
|
+
direction: "ltr"
|
|
3645
|
+
},
|
|
3646
|
+
{
|
|
3647
|
+
code: "nl-be",
|
|
3648
|
+
english: "Flemish",
|
|
3649
|
+
native: "Vlaams",
|
|
3650
|
+
direction: "ltr"
|
|
3651
|
+
},
|
|
3652
|
+
{
|
|
3653
|
+
code: "no",
|
|
3654
|
+
english: "Norwegian",
|
|
3655
|
+
native: "norsk",
|
|
3656
|
+
direction: "ltr"
|
|
3657
|
+
},
|
|
3658
|
+
{
|
|
3659
|
+
code: "nr",
|
|
3660
|
+
english: "South Ndebele",
|
|
3661
|
+
native: "South Ndebele",
|
|
3662
|
+
direction: "ltr"
|
|
3663
|
+
},
|
|
3664
|
+
{
|
|
3665
|
+
code: "nso",
|
|
3666
|
+
english: "Northern Sotho",
|
|
3667
|
+
native: "Northern Sotho",
|
|
3668
|
+
direction: "ltr"
|
|
3669
|
+
},
|
|
3670
|
+
{
|
|
3671
|
+
code: "nus",
|
|
3672
|
+
english: "Nuer",
|
|
3673
|
+
native: "Thok Nath",
|
|
3674
|
+
direction: "ltr"
|
|
3675
|
+
},
|
|
3676
|
+
{
|
|
3677
|
+
code: "ny",
|
|
3678
|
+
english: "Nyanja",
|
|
3679
|
+
native: "Nyanja",
|
|
3680
|
+
direction: "ltr"
|
|
3681
|
+
},
|
|
3682
|
+
{
|
|
3683
|
+
code: "oc",
|
|
3684
|
+
english: "Occitan",
|
|
3685
|
+
native: "occitan",
|
|
3686
|
+
direction: "ltr"
|
|
3687
|
+
},
|
|
3688
|
+
{
|
|
3689
|
+
code: "om",
|
|
3690
|
+
english: "Oromo",
|
|
3691
|
+
native: "Oromoo",
|
|
3692
|
+
direction: "ltr"
|
|
3693
|
+
},
|
|
3694
|
+
{
|
|
3695
|
+
code: "or",
|
|
3696
|
+
english: "Odia",
|
|
3697
|
+
native: "\u0B13\u0B21\u0B3C\u0B3F\u0B06",
|
|
3698
|
+
direction: "ltr"
|
|
3699
|
+
},
|
|
3700
|
+
{
|
|
3701
|
+
code: "pa",
|
|
3702
|
+
english: "Punjabi",
|
|
3703
|
+
native: "\u0A2A\u0A70\u0A1C\u0A3E\u0A2C\u0A40",
|
|
3704
|
+
direction: "ltr"
|
|
3705
|
+
},
|
|
3706
|
+
{
|
|
3707
|
+
code: "pa-arab",
|
|
3708
|
+
english: "Punjabi (Arabic)",
|
|
3709
|
+
native: "\u067E\u0646\u062C\u0627\u0628\u06CC (\u0639\u0631\u0628\u06CC)",
|
|
3710
|
+
direction: "ltr"
|
|
3711
|
+
},
|
|
3712
|
+
{
|
|
3713
|
+
code: "pa-pk",
|
|
3714
|
+
english: "Punjabi (Pakistan)",
|
|
3715
|
+
native: "\u067E\u0646\u062C\u0627\u0628\u06CC (\u067E\u0627\u06A9\u0633\u062A\u0627\u0646)",
|
|
3716
|
+
direction: "ltr"
|
|
3717
|
+
},
|
|
3718
|
+
{
|
|
3719
|
+
code: "pag",
|
|
3720
|
+
english: "Pangasinan",
|
|
3721
|
+
native: "Pangasinan",
|
|
3722
|
+
direction: "ltr"
|
|
3723
|
+
},
|
|
3724
|
+
{
|
|
3725
|
+
code: "pam",
|
|
3726
|
+
english: "Pampanga",
|
|
3727
|
+
native: "Pampanga",
|
|
3728
|
+
direction: "ltr"
|
|
3729
|
+
},
|
|
3730
|
+
{
|
|
3731
|
+
code: "pap",
|
|
3732
|
+
english: "Papiamento",
|
|
3733
|
+
native: "Papiamento",
|
|
3734
|
+
direction: "ltr"
|
|
3735
|
+
},
|
|
3736
|
+
{
|
|
3737
|
+
code: "pl",
|
|
3738
|
+
english: "Polish",
|
|
3739
|
+
native: "polski",
|
|
3740
|
+
direction: "ltr"
|
|
3741
|
+
},
|
|
3742
|
+
{
|
|
3743
|
+
code: "ps",
|
|
3744
|
+
english: "Pashto",
|
|
3745
|
+
native: "\u067E\u069A\u062A\u0648",
|
|
3746
|
+
direction: "rtl"
|
|
3747
|
+
},
|
|
3748
|
+
{
|
|
3749
|
+
code: "pt",
|
|
3750
|
+
english: "Portuguese",
|
|
3751
|
+
native: "portugu\xEAs",
|
|
3752
|
+
direction: "ltr"
|
|
3753
|
+
},
|
|
3754
|
+
{
|
|
3755
|
+
code: "pt-br",
|
|
3756
|
+
english: "Brazilian Portuguese",
|
|
3757
|
+
native: "portugu\xEAs (Brasil)",
|
|
3758
|
+
direction: "ltr"
|
|
3759
|
+
},
|
|
3760
|
+
{
|
|
3761
|
+
code: "pt-pt",
|
|
3762
|
+
english: "European Portuguese",
|
|
3763
|
+
native: "portugu\xEAs europeu",
|
|
3764
|
+
direction: "ltr"
|
|
3765
|
+
},
|
|
3766
|
+
{
|
|
3767
|
+
code: "qu",
|
|
3768
|
+
english: "Quechua",
|
|
3769
|
+
native: "Runasimi",
|
|
3770
|
+
direction: "ltr"
|
|
3771
|
+
},
|
|
3772
|
+
{
|
|
3773
|
+
code: "rn",
|
|
3774
|
+
english: "Rundi",
|
|
3775
|
+
native: "Ikirundi",
|
|
3776
|
+
direction: "ltr"
|
|
3777
|
+
},
|
|
3778
|
+
{
|
|
3779
|
+
code: "ro",
|
|
3780
|
+
english: "Romanian",
|
|
3781
|
+
native: "rom\xE2n\u0103",
|
|
3782
|
+
direction: "ltr"
|
|
3783
|
+
},
|
|
3784
|
+
{
|
|
3785
|
+
code: "rom",
|
|
3786
|
+
english: "Romany",
|
|
3787
|
+
native: "Romany",
|
|
3788
|
+
direction: "ltr"
|
|
3789
|
+
},
|
|
3790
|
+
{
|
|
3791
|
+
code: "ru",
|
|
3792
|
+
english: "Russian",
|
|
3793
|
+
native: "\u0440\u0443\u0441\u0441\u043A\u0438\u0439",
|
|
3794
|
+
direction: "ltr"
|
|
3795
|
+
},
|
|
3796
|
+
{
|
|
3797
|
+
code: "rw",
|
|
3798
|
+
english: "Kinyarwanda",
|
|
3799
|
+
native: "Kinyarwanda",
|
|
3800
|
+
direction: "ltr"
|
|
3801
|
+
},
|
|
3802
|
+
{
|
|
3803
|
+
code: "sa",
|
|
3804
|
+
english: "Sanskrit",
|
|
3805
|
+
native: "\u0938\u0902\u0938\u094D\u0915\u0943\u0924 \u092D\u093E\u0937\u093E",
|
|
3806
|
+
direction: "ltr"
|
|
3807
|
+
},
|
|
3808
|
+
{
|
|
3809
|
+
code: "scn",
|
|
3810
|
+
english: "Sicilian",
|
|
3811
|
+
native: "Sicilian",
|
|
3812
|
+
direction: "ltr"
|
|
3813
|
+
},
|
|
3814
|
+
{
|
|
3815
|
+
code: "sd",
|
|
3816
|
+
english: "Sindhi",
|
|
3817
|
+
native: "\u0633\u0646\u068C\u064A",
|
|
3818
|
+
direction: "rtl"
|
|
3819
|
+
},
|
|
3820
|
+
{
|
|
3821
|
+
code: "sg",
|
|
3822
|
+
english: "Sango",
|
|
3823
|
+
native: "S\xE4ng\xF6",
|
|
3824
|
+
direction: "ltr"
|
|
3825
|
+
},
|
|
3826
|
+
{
|
|
3827
|
+
code: "shn",
|
|
3828
|
+
english: "Shan",
|
|
3829
|
+
native: "Shan",
|
|
3830
|
+
direction: "ltr"
|
|
3831
|
+
},
|
|
3832
|
+
{
|
|
3833
|
+
code: "si",
|
|
3834
|
+
english: "Sinhala",
|
|
3835
|
+
native: "\u0DC3\u0DD2\u0D82\u0DC4\u0DBD",
|
|
3836
|
+
direction: "ltr"
|
|
3837
|
+
},
|
|
3838
|
+
{
|
|
3839
|
+
code: "sk",
|
|
3840
|
+
english: "Slovak",
|
|
3841
|
+
native: "sloven\u010Dina",
|
|
3842
|
+
direction: "ltr"
|
|
3843
|
+
},
|
|
3844
|
+
{
|
|
3845
|
+
code: "sl",
|
|
3846
|
+
english: "Slovenian",
|
|
3847
|
+
native: "sloven\u0161\u010Dina",
|
|
3848
|
+
direction: "ltr"
|
|
3849
|
+
},
|
|
3850
|
+
{
|
|
3851
|
+
code: "sm",
|
|
3852
|
+
english: "Samoan",
|
|
3853
|
+
native: "Samoan",
|
|
3854
|
+
direction: "ltr"
|
|
3855
|
+
},
|
|
3856
|
+
{
|
|
3857
|
+
code: "sn",
|
|
3858
|
+
english: "Shona",
|
|
3859
|
+
native: "chiShona",
|
|
3860
|
+
direction: "ltr"
|
|
3861
|
+
},
|
|
3862
|
+
{
|
|
3863
|
+
code: "so",
|
|
3864
|
+
english: "Somali",
|
|
3865
|
+
native: "Soomaali",
|
|
3866
|
+
direction: "ltr"
|
|
3867
|
+
},
|
|
3868
|
+
{
|
|
3869
|
+
code: "sq",
|
|
3870
|
+
english: "Albanian",
|
|
3871
|
+
native: "shqip",
|
|
3872
|
+
direction: "ltr"
|
|
3873
|
+
},
|
|
3874
|
+
{
|
|
3875
|
+
code: "sr",
|
|
3876
|
+
english: "Serbian",
|
|
3877
|
+
native: "\u0441\u0440\u043F\u0441\u043A\u0438",
|
|
3878
|
+
direction: "ltr"
|
|
3879
|
+
},
|
|
3880
|
+
{
|
|
3881
|
+
code: "ss",
|
|
3882
|
+
english: "Swati",
|
|
3883
|
+
native: "Swati",
|
|
3884
|
+
direction: "ltr"
|
|
3885
|
+
},
|
|
3886
|
+
{
|
|
3887
|
+
code: "st",
|
|
3888
|
+
english: "Southern Sotho",
|
|
3889
|
+
native: "Southern Sotho",
|
|
3890
|
+
direction: "ltr"
|
|
3891
|
+
},
|
|
3892
|
+
{
|
|
3893
|
+
code: "su",
|
|
3894
|
+
english: "Sundanese",
|
|
3895
|
+
native: "Basa Sunda",
|
|
3896
|
+
direction: "ltr"
|
|
3897
|
+
},
|
|
3898
|
+
{
|
|
3899
|
+
code: "sv",
|
|
3900
|
+
english: "Swedish",
|
|
3901
|
+
native: "svenska",
|
|
3902
|
+
direction: "ltr"
|
|
3903
|
+
},
|
|
3904
|
+
{
|
|
3905
|
+
code: "sw",
|
|
3906
|
+
english: "Swahili",
|
|
3907
|
+
native: "Kiswahili",
|
|
3908
|
+
direction: "ltr"
|
|
3909
|
+
},
|
|
3910
|
+
{
|
|
3911
|
+
code: "szl",
|
|
3912
|
+
english: "Silesian",
|
|
3913
|
+
native: "\u015Bl\u014Dnski",
|
|
3914
|
+
direction: "ltr"
|
|
3915
|
+
},
|
|
3916
|
+
{
|
|
3917
|
+
code: "ta",
|
|
3918
|
+
english: "Tamil",
|
|
3919
|
+
native: "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD",
|
|
3920
|
+
direction: "ltr"
|
|
3921
|
+
},
|
|
3922
|
+
{
|
|
3923
|
+
code: "te",
|
|
3924
|
+
english: "Telugu",
|
|
3925
|
+
native: "\u0C24\u0C46\u0C32\u0C41\u0C17\u0C41",
|
|
3926
|
+
direction: "ltr"
|
|
3927
|
+
},
|
|
3928
|
+
{
|
|
3929
|
+
code: "tet",
|
|
3930
|
+
english: "Tetum",
|
|
3931
|
+
native: "Tetum",
|
|
3932
|
+
direction: "ltr"
|
|
3933
|
+
},
|
|
3934
|
+
{
|
|
3935
|
+
code: "tg",
|
|
3936
|
+
english: "Tajik",
|
|
3937
|
+
native: "\u0442\u043E\u04B7\u0438\u043A\u04E3",
|
|
3938
|
+
direction: "ltr"
|
|
3939
|
+
},
|
|
3940
|
+
{
|
|
3941
|
+
code: "th",
|
|
3942
|
+
english: "Thai",
|
|
3943
|
+
native: "\u0E44\u0E17\u0E22",
|
|
3944
|
+
direction: "ltr"
|
|
3945
|
+
},
|
|
3946
|
+
{
|
|
3947
|
+
code: "ti",
|
|
3948
|
+
english: "Tigrinya",
|
|
3949
|
+
native: "\u1275\u130D\u122D\u129B",
|
|
3950
|
+
direction: "ltr"
|
|
3951
|
+
},
|
|
3952
|
+
{
|
|
3953
|
+
code: "tk",
|
|
3954
|
+
english: "Turkmen",
|
|
3955
|
+
native: "t\xFCrkmen dili",
|
|
3956
|
+
direction: "ltr"
|
|
3957
|
+
},
|
|
3958
|
+
{
|
|
3959
|
+
code: "tl",
|
|
3960
|
+
english: "Filipino",
|
|
3961
|
+
native: "Filipino",
|
|
3962
|
+
direction: "ltr"
|
|
3963
|
+
},
|
|
3964
|
+
{
|
|
3965
|
+
code: "tn",
|
|
3966
|
+
english: "Tswana",
|
|
3967
|
+
native: "Tswana",
|
|
3968
|
+
direction: "ltr"
|
|
3969
|
+
},
|
|
3970
|
+
{
|
|
3971
|
+
code: "tr",
|
|
3972
|
+
english: "Turkish",
|
|
3973
|
+
native: "T\xFCrk\xE7e",
|
|
3974
|
+
direction: "ltr"
|
|
3975
|
+
},
|
|
3976
|
+
{
|
|
3977
|
+
code: "ts",
|
|
3978
|
+
english: "Tsonga",
|
|
3979
|
+
native: "Tsonga",
|
|
3980
|
+
direction: "ltr"
|
|
3981
|
+
},
|
|
3982
|
+
{
|
|
3983
|
+
code: "tt",
|
|
3984
|
+
english: "Tatar",
|
|
3985
|
+
native: "\u0442\u0430\u0442\u0430\u0440",
|
|
3986
|
+
direction: "ltr"
|
|
3987
|
+
},
|
|
3988
|
+
{
|
|
3989
|
+
code: "ug",
|
|
3990
|
+
english: "Uyghur",
|
|
3991
|
+
native: "\u0626\u06C7\u064A\u063A\u06C7\u0631\u0686\u06D5",
|
|
3992
|
+
direction: "rtl"
|
|
3993
|
+
},
|
|
3994
|
+
{
|
|
3995
|
+
code: "uk",
|
|
3996
|
+
english: "Ukrainian",
|
|
3997
|
+
native: "\u0443\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430",
|
|
3998
|
+
direction: "ltr"
|
|
3999
|
+
},
|
|
4000
|
+
{
|
|
4001
|
+
code: "ur",
|
|
4002
|
+
english: "Urdu",
|
|
4003
|
+
native: "\u0627\u0631\u062F\u0648",
|
|
4004
|
+
direction: "rtl"
|
|
4005
|
+
},
|
|
4006
|
+
{
|
|
4007
|
+
code: "uz",
|
|
4008
|
+
english: "Uzbek",
|
|
4009
|
+
native: "o\u2018zbek",
|
|
4010
|
+
direction: "ltr"
|
|
4011
|
+
},
|
|
4012
|
+
{
|
|
4013
|
+
code: "vi",
|
|
4014
|
+
english: "Vietnamese",
|
|
4015
|
+
native: "Ti\u1EBFng Vi\u1EC7t",
|
|
4016
|
+
direction: "ltr"
|
|
4017
|
+
},
|
|
4018
|
+
{
|
|
4019
|
+
code: "xh",
|
|
4020
|
+
english: "Xhosa",
|
|
4021
|
+
native: "IsiXhosa",
|
|
4022
|
+
direction: "ltr"
|
|
4023
|
+
},
|
|
4024
|
+
{
|
|
4025
|
+
code: "yi",
|
|
4026
|
+
english: "Yiddish",
|
|
4027
|
+
native: "\u05D9\u05D9\u05B4\u05D3\u05D9\u05E9",
|
|
4028
|
+
direction: "rtl"
|
|
4029
|
+
},
|
|
4030
|
+
{
|
|
4031
|
+
code: "yo",
|
|
4032
|
+
english: "Yoruba",
|
|
4033
|
+
native: "\xC8d\xE8 Yor\xF9b\xE1",
|
|
4034
|
+
direction: "ltr"
|
|
4035
|
+
},
|
|
4036
|
+
{
|
|
4037
|
+
code: "yua",
|
|
4038
|
+
english: "yua",
|
|
4039
|
+
native: "yua",
|
|
4040
|
+
direction: "ltr"
|
|
4041
|
+
},
|
|
4042
|
+
{
|
|
4043
|
+
code: "yue",
|
|
4044
|
+
english: "Cantonese",
|
|
4045
|
+
native: "\u7CB5\u8A9E",
|
|
4046
|
+
direction: "ltr"
|
|
4047
|
+
},
|
|
4048
|
+
{
|
|
4049
|
+
code: "zh",
|
|
4050
|
+
english: "Chinese",
|
|
4051
|
+
native: "\u4E2D\u6587",
|
|
4052
|
+
direction: "ltr"
|
|
4053
|
+
},
|
|
4054
|
+
{
|
|
4055
|
+
code: "zh-cn",
|
|
4056
|
+
english: "Chinese (China)",
|
|
4057
|
+
native: "\u4E2D\u6587\uFF08\u4E2D\u56FD\uFF09",
|
|
4058
|
+
direction: "ltr"
|
|
4059
|
+
},
|
|
4060
|
+
{
|
|
4061
|
+
code: "zh-hans",
|
|
4062
|
+
english: "Simplified Chinese",
|
|
4063
|
+
native: "\u7B80\u4F53\u4E2D\u6587",
|
|
4064
|
+
direction: "ltr"
|
|
4065
|
+
},
|
|
4066
|
+
{
|
|
4067
|
+
code: "zh-hant",
|
|
4068
|
+
english: "Traditional Chinese",
|
|
4069
|
+
native: "\u7E41\u9AD4\u4E2D\u6587",
|
|
4070
|
+
direction: "ltr"
|
|
4071
|
+
},
|
|
4072
|
+
{
|
|
4073
|
+
code: "zh-hk",
|
|
4074
|
+
english: "Chinese (Hong Kong SAR China)",
|
|
4075
|
+
native: "\u4E2D\u6587\uFF08\u4E2D\u570B\u9999\u6E2F\u7279\u5225\u884C\u653F\u5340\uFF09",
|
|
4076
|
+
direction: "ltr"
|
|
4077
|
+
},
|
|
4078
|
+
{
|
|
4079
|
+
code: "zh-tw",
|
|
4080
|
+
english: "Chinese (Taiwan)",
|
|
4081
|
+
native: "\u4E2D\u6587\uFF08\u53F0\u7063\uFF09",
|
|
4082
|
+
direction: "ltr"
|
|
4083
|
+
},
|
|
4084
|
+
{
|
|
4085
|
+
code: "zu",
|
|
4086
|
+
english: "Zulu",
|
|
4087
|
+
native: "isiZulu",
|
|
4088
|
+
direction: "ltr"
|
|
4089
|
+
}
|
|
4090
|
+
];
|
|
4091
|
+
|
|
4092
|
+
// src/shared/languages/catalog/index.ts
|
|
4093
|
+
var generatedLanguageCatalog = languages_default;
|
|
4094
|
+
function buildLanguageCatalog(raw) {
|
|
4095
|
+
return Object.freeze(raw.map((r) => ({ ...r, code: normalizeLanguageCode(r.code) })));
|
|
4096
|
+
}
|
|
4097
|
+
function filterLanguageCatalog(catalog, filter) {
|
|
4098
|
+
const all = [...catalog];
|
|
4099
|
+
const q = filter?.trim().toLowerCase();
|
|
4100
|
+
if (!q) return all.sort((a, b) => a.code.localeCompare(b.code));
|
|
4101
|
+
return all.filter(
|
|
4102
|
+
(r) => r.code.includes(q) || r.english.toLowerCase().includes(q) || r.native.toLowerCase().includes(q)
|
|
4103
|
+
).sort((a, b) => a.code.localeCompare(b.code));
|
|
4104
|
+
}
|
|
4105
|
+
function getLanguageByCodeFromCatalog(catalog, code) {
|
|
4106
|
+
const n = normalizeLanguageCode(code);
|
|
4107
|
+
return catalog.find((r) => r.code === n);
|
|
4108
|
+
}
|
|
4109
|
+
function suggestCatalogCodesForInvalidInputFromCatalog(catalog, code, maxCodesInCatalogHint = 5) {
|
|
4110
|
+
const n = normalizeLanguageCode(code);
|
|
4111
|
+
const all = [...catalog].sort((a, b) => a.code.localeCompare(b.code));
|
|
4112
|
+
const out = [];
|
|
4113
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4114
|
+
const push = (c) => {
|
|
4115
|
+
if (!seen.has(c)) {
|
|
4116
|
+
seen.add(c);
|
|
4117
|
+
out.push(c);
|
|
4118
|
+
}
|
|
4119
|
+
};
|
|
4120
|
+
for (const r of filterLanguageCatalog(catalog, n)) {
|
|
4121
|
+
push(r.code);
|
|
4122
|
+
if (out.length >= maxCodesInCatalogHint) return out;
|
|
4123
|
+
}
|
|
4124
|
+
if (n.length >= 2) {
|
|
4125
|
+
const prefix = n.slice(0, 2);
|
|
4126
|
+
for (const r of all) {
|
|
4127
|
+
if (r.code.startsWith(prefix)) push(r.code);
|
|
4128
|
+
if (out.length >= maxCodesInCatalogHint) return out;
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
for (const r of all) {
|
|
4132
|
+
push(r.code);
|
|
4133
|
+
if (out.length >= maxCodesInCatalogHint) return out;
|
|
4134
|
+
}
|
|
4135
|
+
return out;
|
|
4136
|
+
}
|
|
4137
|
+
|
|
4138
|
+
// src/shared/constants/index.ts
|
|
4139
|
+
var constants_exports = {};
|
|
4140
|
+
__export(constants_exports, {
|
|
4141
|
+
ANALYSIS_BASENAME: () => ANALYSIS_BASENAME,
|
|
4142
|
+
CACHE_PROFILE_DEFAULTS: () => CACHE_PROFILE_DEFAULTS,
|
|
4143
|
+
CACHE_SCHEMA_VERSION: () => CACHE_SCHEMA_VERSION,
|
|
4144
|
+
DEFAULT_CACHE_PROFILE_ID: () => DEFAULT_CACHE_PROFILE_ID,
|
|
4145
|
+
DEFAULT_HEAL_EVERY_RUNS: () => DEFAULT_HEAL_EVERY_RUNS,
|
|
4146
|
+
DEFAULT_LIST_TOP: () => DEFAULT_LIST_TOP,
|
|
4147
|
+
DEFAULT_MAX_SHARE_JSON_BYTES: () => DEFAULT_MAX_SHARE_JSON_BYTES,
|
|
4148
|
+
DEFAULT_MISSING_LEAF_PLACEHOLDER: () => DEFAULT_MISSING_LEAF_PLACEHOLDER,
|
|
4149
|
+
DEFAULT_WORKER_API_URL: () => DEFAULT_WORKER_API_URL,
|
|
4150
|
+
DEMO_REPORT_URL: () => DEMO_REPORT_URL,
|
|
4151
|
+
DEMO_WEB_APP_BASE: () => DEMO_WEB_APP_BASE,
|
|
4152
|
+
DOCS_ISSUES_PAGE_PATH: () => DOCS_ISSUES_PAGE_PATH,
|
|
4153
|
+
DOCS_SITE_BASE: () => DOCS_SITE_BASE,
|
|
4154
|
+
DOCS_SITE_ORIGIN: () => DOCS_SITE_ORIGIN,
|
|
4155
|
+
ENV_TRANSLATE_DEEPL_API_KEY: () => ENV_TRANSLATE_DEEPL_API_KEY,
|
|
4156
|
+
ENV_TRANSLATE_LIBRE_URL: () => ENV_TRANSLATE_LIBRE_URL,
|
|
4157
|
+
ENV_TRANSLATE_LLM_API_KEY: () => ENV_TRANSLATE_LLM_API_KEY,
|
|
4158
|
+
ENV_TRANSLATE_LLM_BASE_URL: () => ENV_TRANSLATE_LLM_BASE_URL,
|
|
4159
|
+
ENV_TRANSLATE_LLM_MODEL: () => ENV_TRANSLATE_LLM_MODEL,
|
|
4160
|
+
ENV_TRANSLATE_MAX_WORKERS: () => ENV_TRANSLATE_MAX_WORKERS,
|
|
4161
|
+
ENV_TRANSLATE_PROVIDER: () => ENV_TRANSLATE_PROVIDER,
|
|
4162
|
+
GITHUB_BASE: () => GITHUB_BASE,
|
|
4163
|
+
GITHUB_DOCS_BASE: () => GITHUB_DOCS_BASE,
|
|
4164
|
+
GITHUB_DOCS_TREE_BASE: () => GITHUB_DOCS_TREE_BASE,
|
|
4165
|
+
GITHUB_OWNER: () => GITHUB_OWNER,
|
|
4166
|
+
GITHUB_REPO: () => GITHUB_REPO,
|
|
4167
|
+
GITHUB_REPO_URL: () => GITHUB_REPO_URL,
|
|
4168
|
+
HOSTED_PROJECT_SNAPSHOT_SCHEMA_VERSION: () => HOSTED_PROJECT_SNAPSHOT_SCHEMA_VERSION,
|
|
4169
|
+
I18NPRUNE_CONFIG_BASENAME: () => I18NPRUNE_CONFIG_BASENAME,
|
|
4170
|
+
I18NPRUNE_CONFIG_JSON_FILE_NAME: () => I18NPRUNE_CONFIG_JSON_FILE_NAME,
|
|
4171
|
+
I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES: () => I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES,
|
|
4172
|
+
I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES_SET: () => I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES_SET,
|
|
4173
|
+
I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES: () => I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES,
|
|
4174
|
+
I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES_SET: () => I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES_SET,
|
|
4175
|
+
ISSUE_CLEANUP_RIPGREP_UNAVAILABLE: () => ISSUE_CLEANUP_RIPGREP_UNAVAILABLE,
|
|
4176
|
+
ISSUE_CLEANUP_UNCERTAIN_PATHS_EXCLUDED: () => ISSUE_CLEANUP_UNCERTAIN_PATHS_EXCLUDED,
|
|
4177
|
+
ISSUE_CLI_INVALID_JSON_PRETTY: () => ISSUE_CLI_INVALID_JSON_PRETTY,
|
|
4178
|
+
ISSUE_CONFIG_INVALID: () => ISSUE_CONFIG_INVALID,
|
|
4179
|
+
ISSUE_CONFIG_LOAD_FAILED: () => ISSUE_CONFIG_LOAD_FAILED,
|
|
4180
|
+
ISSUE_CONFIG_MISSING: () => ISSUE_CONFIG_MISSING,
|
|
4181
|
+
ISSUE_CONTEXT_DISCOVERY_WARNING: () => ISSUE_CONTEXT_DISCOVERY_WARNING,
|
|
4182
|
+
ISSUE_CONTEXT_RESOLUTION_FAILED: () => ISSUE_CONTEXT_RESOLUTION_FAILED,
|
|
4183
|
+
ISSUE_DOCTOR_CONFIG_MISSING_FILE: () => ISSUE_DOCTOR_CONFIG_MISSING_FILE,
|
|
4184
|
+
ISSUE_DOCTOR_PATHS_DIRECTORIES_MISSING: () => ISSUE_DOCTOR_PATHS_DIRECTORIES_MISSING,
|
|
4185
|
+
ISSUE_DOCTOR_PATHS_SOURCE_LOCALE_MISSING: () => ISSUE_DOCTOR_PATHS_SOURCE_LOCALE_MISSING,
|
|
4186
|
+
ISSUE_DOCTOR_RUNTIME_UNSUPPORTED_NODE: () => ISSUE_DOCTOR_RUNTIME_UNSUPPORTED_NODE,
|
|
4187
|
+
ISSUE_DOCTOR_TOOLS_RG_NOT_ON_PATH: () => ISSUE_DOCTOR_TOOLS_RG_NOT_ON_PATH,
|
|
4188
|
+
ISSUE_GENERATE_SOURCE_EMPTY_STRING_LEAVES: () => ISSUE_GENERATE_SOURCE_EMPTY_STRING_LEAVES,
|
|
4189
|
+
ISSUE_GENERATE_TRANSLATE_NETWORK_ERROR: () => ISSUE_GENERATE_TRANSLATE_NETWORK_ERROR,
|
|
4190
|
+
ISSUE_GENERATE_TRANSLATE_RATE_LIMITED: () => ISSUE_GENERATE_TRANSLATE_RATE_LIMITED,
|
|
4191
|
+
ISSUE_GENERATE_USAGE: () => ISSUE_GENERATE_USAGE,
|
|
4192
|
+
ISSUE_IO_READ_FAILED: () => ISSUE_IO_READ_FAILED,
|
|
4193
|
+
ISSUE_LANGUAGES_EMPTY_FILTER: () => ISSUE_LANGUAGES_EMPTY_FILTER,
|
|
4194
|
+
ISSUE_LANGUAGES_UNSUPPORTED_LANGUAGE_CODE: () => ISSUE_LANGUAGES_UNSUPPORTED_LANGUAGE_CODE,
|
|
4195
|
+
ISSUE_LOCALES_USAGE: () => ISSUE_LOCALES_USAGE,
|
|
4196
|
+
ISSUE_LOCALE_SOURCE_PLACEHOLDER_LEAVES: () => ISSUE_LOCALE_SOURCE_PLACEHOLDER_LEAVES,
|
|
4197
|
+
ISSUE_LOCALE_TARGET_NOT_FOUND: () => ISSUE_LOCALE_TARGET_NOT_FOUND,
|
|
4198
|
+
ISSUE_LOCALE_TARGET_PLACEHOLDER_LEAVES: () => ISSUE_LOCALE_TARGET_PLACEHOLDER_LEAVES,
|
|
4199
|
+
ISSUE_MISSING_PATHS_NOT_IN_SCAN: () => ISSUE_MISSING_PATHS_NOT_IN_SCAN,
|
|
4200
|
+
ISSUE_PATCHING_CATALOG_MISMATCH_DIRECTION: () => ISSUE_PATCHING_CATALOG_MISMATCH_DIRECTION,
|
|
4201
|
+
ISSUE_PATCHING_CATALOG_MISMATCH_ENGLISH: () => ISSUE_PATCHING_CATALOG_MISMATCH_ENGLISH,
|
|
4202
|
+
ISSUE_PATCHING_CATALOG_MISMATCH_NATIVE: () => ISSUE_PATCHING_CATALOG_MISMATCH_NATIVE,
|
|
4203
|
+
ISSUE_PATCHING_CONFIG_INVALID_SCHEMA: () => ISSUE_PATCHING_CONFIG_INVALID_SCHEMA,
|
|
4204
|
+
ISSUE_PATCHING_CONFIG_LOCALE_MISSING_FILE: () => ISSUE_PATCHING_CONFIG_LOCALE_MISSING_FILE,
|
|
4205
|
+
ISSUE_PATCHING_CONFIG_PARSE_FAILED: () => ISSUE_PATCHING_CONFIG_PARSE_FAILED,
|
|
4206
|
+
ISSUE_PATCHING_CONFIG_SECTION_INCOMPLETE: () => ISSUE_PATCHING_CONFIG_SECTION_INCOMPLETE,
|
|
4207
|
+
ISSUE_PATCHING_CONFIG_SIZE_ANOMALY: () => ISSUE_PATCHING_CONFIG_SIZE_ANOMALY,
|
|
4208
|
+
ISSUE_PATCHING_CONFIG_TOO_LARGE: () => ISSUE_PATCHING_CONFIG_TOO_LARGE,
|
|
4209
|
+
ISSUE_PATCHING_FILE_LOCALE_MISSING_CONFIG: () => ISSUE_PATCHING_FILE_LOCALE_MISSING_CONFIG,
|
|
4210
|
+
ISSUE_PATHS_NETWORK_DRIVE: () => ISSUE_PATHS_NETWORK_DRIVE,
|
|
4211
|
+
ISSUE_PATHS_WINDOWS_LONG_PATH: () => ISSUE_PATHS_WINDOWS_LONG_PATH,
|
|
4212
|
+
ISSUE_PATHS_WINDOWS_RESERVED_NAME: () => ISSUE_PATHS_WINDOWS_RESERVED_NAME,
|
|
4213
|
+
ISSUE_PROJECT_CONFIG_FILE_MISSING: () => ISSUE_PROJECT_CONFIG_FILE_MISSING,
|
|
4214
|
+
ISSUE_PROJECT_HOSTED_SNAPSHOT_INVALID: () => ISSUE_PROJECT_HOSTED_SNAPSHOT_INVALID,
|
|
4215
|
+
ISSUE_PROJECT_HOSTED_SNAPSHOT_SCHEMA_VERSION: () => ISSUE_PROJECT_HOSTED_SNAPSHOT_SCHEMA_VERSION,
|
|
4216
|
+
ISSUE_PROJECT_LOCALES_DIR_UNAVAILABLE: () => ISSUE_PROJECT_LOCALES_DIR_UNAVAILABLE,
|
|
4217
|
+
ISSUE_PROJECT_LOCALES_SOURCE_NOT_IN_BUNDLE: () => ISSUE_PROJECT_LOCALES_SOURCE_NOT_IN_BUNDLE,
|
|
4218
|
+
ISSUE_PROJECT_LOCALES_SOURCE_NOT_LANGUAGE_CODE: () => ISSUE_PROJECT_LOCALES_SOURCE_NOT_LANGUAGE_CODE,
|
|
4219
|
+
ISSUE_PROJECT_LOCALES_STRUCTURE_REQUIRED: () => ISSUE_PROJECT_LOCALES_STRUCTURE_REQUIRED,
|
|
4220
|
+
ISSUE_PROJECT_SOURCE_LOCALE_INVALID_JSON: () => ISSUE_PROJECT_SOURCE_LOCALE_INVALID_JSON,
|
|
4221
|
+
ISSUE_PROJECT_SOURCE_LOCALE_INVALID_SHAPE: () => ISSUE_PROJECT_SOURCE_LOCALE_INVALID_SHAPE,
|
|
4222
|
+
ISSUE_PROJECT_SOURCE_LOCALE_MISSING_SEGMENTS: () => ISSUE_PROJECT_SOURCE_LOCALE_MISSING_SEGMENTS,
|
|
4223
|
+
ISSUE_PROJECT_SOURCE_LOCALE_NOT_FOUND: () => ISSUE_PROJECT_SOURCE_LOCALE_NOT_FOUND,
|
|
4224
|
+
ISSUE_PROJECT_SOURCE_LOCALE_UNAVAILABLE: () => ISSUE_PROJECT_SOURCE_LOCALE_UNAVAILABLE,
|
|
4225
|
+
ISSUE_PROJECT_SRC_ROOT_UNAVAILABLE: () => ISSUE_PROJECT_SRC_ROOT_UNAVAILABLE,
|
|
4226
|
+
ISSUE_PROJECT_UPLOAD_CONFIG_JSON_INVALID: () => ISSUE_PROJECT_UPLOAD_CONFIG_JSON_INVALID,
|
|
4227
|
+
ISSUE_PROJECT_UPLOAD_CONFIG_REQUIRED: () => ISSUE_PROJECT_UPLOAD_CONFIG_REQUIRED,
|
|
4228
|
+
ISSUE_QUALITY_ENGLISH_IDENTICAL_LEAVES: () => ISSUE_QUALITY_ENGLISH_IDENTICAL_LEAVES,
|
|
4229
|
+
ISSUE_REPORT_HOSTED_REPORT_INVALID: () => ISSUE_REPORT_HOSTED_REPORT_INVALID,
|
|
4230
|
+
ISSUE_REPORT_INVALID_FORMAT: () => ISSUE_REPORT_INVALID_FORMAT,
|
|
4231
|
+
ISSUE_SCAN_DYNAMIC_KEY_SITES: () => ISSUE_SCAN_DYNAMIC_KEY_SITES,
|
|
4232
|
+
ISSUE_SHARE_CACHE_EMPTY: () => ISSUE_SHARE_CACHE_EMPTY,
|
|
4233
|
+
ISSUE_SHARE_CACHE_ENTRY_NOT_FOUND: () => ISSUE_SHARE_CACHE_ENTRY_NOT_FOUND,
|
|
4234
|
+
ISSUE_SHARE_JSON_REPAIRED: () => ISSUE_SHARE_JSON_REPAIRED,
|
|
4235
|
+
ISSUE_SHARE_JSON_WRITE_FAILED: () => ISSUE_SHARE_JSON_WRITE_FAILED,
|
|
4236
|
+
ISSUE_SHARE_PREPARE_ANALYSIS_FAILED: () => ISSUE_SHARE_PREPARE_ANALYSIS_FAILED,
|
|
4237
|
+
ISSUE_SHARE_PREPARE_NOTHING_REQUESTED: () => ISSUE_SHARE_PREPARE_NOTHING_REQUESTED,
|
|
4238
|
+
ISSUE_SHARE_PREPARE_REPORT_FROM_ARCHIVE_FAILED: () => ISSUE_SHARE_PREPARE_REPORT_FROM_ARCHIVE_FAILED,
|
|
4239
|
+
ISSUE_SHARE_PREPARE_REPORT_HOST_REQUIRED: () => ISSUE_SHARE_PREPARE_REPORT_HOST_REQUIRED,
|
|
4240
|
+
ISSUE_SHARE_REMOTE_ERROR: () => ISSUE_SHARE_REMOTE_ERROR,
|
|
4241
|
+
ISSUE_SHARE_REMOTE_PAYLOAD_TOO_LARGE: () => ISSUE_SHARE_REMOTE_PAYLOAD_TOO_LARGE,
|
|
4242
|
+
ISSUE_SHARE_REMOTE_PROJECT_NOT_FOUND: () => ISSUE_SHARE_REMOTE_PROJECT_NOT_FOUND,
|
|
4243
|
+
ISSUE_SHARE_REMOTE_REPORT_NOT_FOUND: () => ISSUE_SHARE_REMOTE_REPORT_NOT_FOUND,
|
|
4244
|
+
ISSUE_SHARE_REMOTE_REPORT_REJECTED: () => ISSUE_SHARE_REMOTE_REPORT_REJECTED,
|
|
4245
|
+
ISSUE_SHARE_REMOTE_UNAVAILABLE: () => ISSUE_SHARE_REMOTE_UNAVAILABLE,
|
|
4246
|
+
ISSUE_SHARE_REMOTE_UPLOAD_REJECTED: () => ISSUE_SHARE_REMOTE_UPLOAD_REJECTED,
|
|
4247
|
+
ISSUE_SHARE_SNAPSHOT_EMPTY: () => ISSUE_SHARE_SNAPSHOT_EMPTY,
|
|
4248
|
+
ISSUE_SHARE_STALE_CACHE_ROW_REMOVED: () => ISSUE_SHARE_STALE_CACHE_ROW_REMOVED,
|
|
4249
|
+
ISSUE_SHARE_ZIP_FAILED: () => ISSUE_SHARE_ZIP_FAILED,
|
|
4250
|
+
ISSUE_SYNC_LOCALE_FILE_NOT_FOUND: () => ISSUE_SYNC_LOCALE_FILE_NOT_FOUND,
|
|
4251
|
+
ISSUE_SYNC_METADATA_FLAG_CONFLICT: () => ISSUE_SYNC_METADATA_FLAG_CONFLICT,
|
|
4252
|
+
ISSUE_TRANSLATE_CONFIG_DEFAULT_APPLIED: () => ISSUE_TRANSLATE_CONFIG_DEFAULT_APPLIED,
|
|
4253
|
+
ISSUE_TRANSLATE_HANDOFF_NO_ELIGIBLE_PROVIDER: () => ISSUE_TRANSLATE_HANDOFF_NO_ELIGIBLE_PROVIDER,
|
|
4254
|
+
ISSUE_TRANSLATE_IDENTITY_STREAK_ABORT: () => ISSUE_TRANSLATE_IDENTITY_STREAK_ABORT,
|
|
4255
|
+
ISSUE_TRANSLATE_IDENTITY_STREAK_WARNING: () => ISSUE_TRANSLATE_IDENTITY_STREAK_WARNING,
|
|
4256
|
+
ISSUE_TRANSLATE_MISSING_CREDENTIALS: () => ISSUE_TRANSLATE_MISSING_CREDENTIALS,
|
|
4257
|
+
ISSUE_TRANSLATE_PROVIDER_NOT_IMPLEMENTED_YET: () => ISSUE_TRANSLATE_PROVIDER_NOT_IMPLEMENTED_YET,
|
|
4258
|
+
ISSUE_TRANSLATE_UNKNOWN_TRANSLATION_PROVIDER: () => ISSUE_TRANSLATE_UNKNOWN_TRANSLATION_PROVIDER,
|
|
4259
|
+
ISSUE_VALIDATE_DYNAMIC_KEY_SITES: () => ISSUE_VALIDATE_DYNAMIC_KEY_SITES,
|
|
4260
|
+
ISSUE_VALIDATE_MISSING_LITERAL_KEYS: () => ISSUE_VALIDATE_MISSING_LITERAL_KEYS,
|
|
4261
|
+
ISSUE_VALIDATE_SOURCE_LOCALE_READ_FAILED: () => ISSUE_VALIDATE_SOURCE_LOCALE_READ_FAILED,
|
|
4262
|
+
LICENSE_URL: () => LICENSE_URL,
|
|
4263
|
+
LIST_MORE_HINT: () => LIST_MORE_HINT,
|
|
4264
|
+
MAX_ANALYSIS_BYTES: () => MAX_ANALYSIS_BYTES,
|
|
4265
|
+
MAX_MISSING_TARGET_SUGGESTIONS: () => MAX_MISSING_TARGET_SUGGESTIONS,
|
|
4266
|
+
MAX_PROJECTS_INDEX_BYTES: () => MAX_PROJECTS_INDEX_BYTES,
|
|
4267
|
+
MAX_PROJECT_FILES_BYTES: () => MAX_PROJECT_FILES_BYTES,
|
|
4268
|
+
MAX_TRANSLATIONS_CACHE_BYTES: () => MAX_TRANSLATIONS_CACHE_BYTES,
|
|
4269
|
+
META_WORKER_URL: () => META_WORKER_URL,
|
|
4270
|
+
NPM_PACKAGE_NAME: () => NPM_PACKAGE_NAME,
|
|
4271
|
+
NPM_PACKAGE_URL: () => NPM_PACKAGE_URL,
|
|
4272
|
+
PROJECT_REPORT_KIND: () => PROJECT_REPORT_KIND,
|
|
4273
|
+
PROJECT_REPORT_SCHEMA_VERSION: () => PROJECT_REPORT_SCHEMA_VERSION,
|
|
4274
|
+
PROJECT_SHARE_PREPARED_MAX_BYTES: () => PROJECT_SHARE_PREPARED_MAX_BYTES,
|
|
4275
|
+
PROJECT_UPLOAD_MAX_FILES: () => PROJECT_UPLOAD_MAX_FILES,
|
|
4276
|
+
PROJECT_UPLOAD_MAX_TEXT_BYTES: () => PROJECT_UPLOAD_MAX_TEXT_BYTES,
|
|
4277
|
+
PROJECT_UPLOAD_MAX_ZIP_BYTES: () => PROJECT_UPLOAD_MAX_ZIP_BYTES,
|
|
4278
|
+
PROJECT_UPLOAD_ZIP_LIMITS: () => PROJECT_UPLOAD_ZIP_LIMITS,
|
|
4279
|
+
REPORT_INLINE_PAYLOAD_PLACEHOLDER: () => REPORT_INLINE_PAYLOAD_PLACEHOLDER,
|
|
4280
|
+
REPORT_SHARE_MAX_BYTES: () => REPORT_SHARE_MAX_BYTES,
|
|
4281
|
+
RESULT_API_VERSION: () => RESULT_API_VERSION,
|
|
4282
|
+
SDK_PACKAGE_NAME: () => SDK_PACKAGE_NAME,
|
|
4283
|
+
SDK_VERSION: () => SDK_VERSION,
|
|
4284
|
+
SHARE_BAK_DIRNAME: () => SHARE_BAK_DIRNAME,
|
|
4285
|
+
SHARE_CACHE_REASON_MESSAGES: () => SHARE_CACHE_REASON_MESSAGES,
|
|
4286
|
+
SHARE_JSON_BASENAME: () => SHARE_JSON_BASENAME,
|
|
4287
|
+
TRANSLATE_WORKERS_CAP: () => TRANSLATE_WORKERS_CAP,
|
|
4288
|
+
TRANSLATIONS_DIR: () => TRANSLATIONS_DIR,
|
|
4289
|
+
WORKER_IDLE_RETENTION_MS: () => WORKER_IDLE_RETENTION_MS,
|
|
4290
|
+
WORKER_INGEST_FORCE_QUERY: () => WORKER_INGEST_FORCE_QUERY,
|
|
4291
|
+
formatListOmittedSuffix: () => formatListOmittedSuffix,
|
|
4292
|
+
formatListShownOmitted: () => formatListShownOmitted
|
|
4293
|
+
});
|
|
4294
|
+
|
|
4295
|
+
// src/shared/constants/config.ts
|
|
4296
|
+
var I18NPRUNE_CONFIG_BASENAME = "i18nprune.config";
|
|
4297
|
+
var I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES = [
|
|
4298
|
+
`${I18NPRUNE_CONFIG_BASENAME}.ts`,
|
|
4299
|
+
`${I18NPRUNE_CONFIG_BASENAME}.mts`,
|
|
4300
|
+
`${I18NPRUNE_CONFIG_BASENAME}.cts`,
|
|
4301
|
+
`${I18NPRUNE_CONFIG_BASENAME}.js`,
|
|
4302
|
+
`${I18NPRUNE_CONFIG_BASENAME}.mjs`,
|
|
4303
|
+
`${I18NPRUNE_CONFIG_BASENAME}.cjs`
|
|
4304
|
+
];
|
|
4305
|
+
var I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES_SET = new Set(I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES);
|
|
4306
|
+
var I18NPRUNE_CONFIG_JSON_FILE_NAME = `${I18NPRUNE_CONFIG_BASENAME}.json`;
|
|
4307
|
+
var I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES = [
|
|
4308
|
+
...I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES,
|
|
4309
|
+
I18NPRUNE_CONFIG_JSON_FILE_NAME
|
|
4310
|
+
];
|
|
4311
|
+
var I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES_SET = new Set(I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES);
|
|
4312
|
+
|
|
4313
|
+
// src/shared/constants/listDisplay.ts
|
|
4314
|
+
var DEFAULT_LIST_TOP = 3;
|
|
4315
|
+
var LIST_MORE_HINT = "(use --full or --top <n>)";
|
|
4316
|
+
function formatListOmittedSuffix(omitted) {
|
|
4317
|
+
return `\u2026 ${String(omitted)} more ${LIST_MORE_HINT}`;
|
|
4318
|
+
}
|
|
4319
|
+
function formatListShownOmitted(prefix, omitted) {
|
|
4320
|
+
if (omitted <= 0) return prefix;
|
|
4321
|
+
return `${prefix} + ${formatListOmittedSuffix(omitted)}`;
|
|
4322
|
+
}
|
|
4323
|
+
|
|
4324
|
+
// src/shared/constants/sdk.ts
|
|
4325
|
+
var SDK_PACKAGE_NAME = "@i18nprune/core";
|
|
4326
|
+
var SDK_VERSION = "0.1.0";
|
|
4327
|
+
|
|
4328
|
+
// src/shared/constants/cache.ts
|
|
4329
|
+
var CACHE_SCHEMA_VERSION = 1;
|
|
4330
|
+
var DEFAULT_CACHE_PROFILE_ID = "balanced";
|
|
4331
|
+
var CACHE_PROFILE_DEFAULTS = {
|
|
4332
|
+
safe: {
|
|
4333
|
+
rebuild: "full",
|
|
4334
|
+
fullRescanThresholdPercent: 10,
|
|
4335
|
+
mode: "readWrite"
|
|
4336
|
+
},
|
|
4337
|
+
balanced: {
|
|
4338
|
+
rebuild: "partial",
|
|
4339
|
+
fullRescanThresholdPercent: 40,
|
|
4340
|
+
mode: "readWrite"
|
|
4341
|
+
},
|
|
4342
|
+
fast: {
|
|
4343
|
+
rebuild: "partial",
|
|
4344
|
+
fullRescanThresholdPercent: 70,
|
|
4345
|
+
mode: "readWrite"
|
|
4346
|
+
}
|
|
4347
|
+
};
|
|
4348
|
+
var ANALYSIS_BASENAME = "analysis.json";
|
|
4349
|
+
var TRANSLATIONS_DIR = "translations";
|
|
4350
|
+
var MAX_PROJECTS_INDEX_BYTES = 2 * 1024 * 1024;
|
|
4351
|
+
var MAX_PROJECT_FILES_BYTES = 32 * 1024 * 1024;
|
|
4352
|
+
var MAX_ANALYSIS_BYTES = 16 * 1024 * 1024;
|
|
4353
|
+
var MAX_TRANSLATIONS_CACHE_BYTES = 32 * 1024 * 1024;
|
|
4354
|
+
var DEFAULT_HEAL_EVERY_RUNS = 20;
|
|
4355
|
+
|
|
4356
|
+
// src/shared/constants/project.ts
|
|
4357
|
+
var PROJECT_UPLOAD_ZIP_LIMITS = {
|
|
4358
|
+
maxZipBytes: 50 * 1024 * 1024,
|
|
4359
|
+
maxFiles: 15e3,
|
|
4360
|
+
maxTextBytes: 60 * 1024 * 1024
|
|
4361
|
+
};
|
|
4362
|
+
var PROJECT_UPLOAD_MAX_ZIP_BYTES = PROJECT_UPLOAD_ZIP_LIMITS.maxZipBytes;
|
|
4363
|
+
var PROJECT_UPLOAD_MAX_FILES = PROJECT_UPLOAD_ZIP_LIMITS.maxFiles;
|
|
4364
|
+
var PROJECT_UPLOAD_MAX_TEXT_BYTES = PROJECT_UPLOAD_ZIP_LIMITS.maxTextBytes;
|
|
4365
|
+
var HOSTED_PROJECT_SNAPSHOT_SCHEMA_VERSION = 1;
|
|
4366
|
+
|
|
4367
|
+
// src/shared/constants/report.ts
|
|
4368
|
+
var PROJECT_REPORT_KIND = "i18nprune.projectReport";
|
|
4369
|
+
var PROJECT_REPORT_SCHEMA_VERSION = 1;
|
|
4370
|
+
var REPORT_INLINE_PAYLOAD_PLACEHOLDER = "__I18NPRUNE_REPORT__";
|
|
4371
|
+
|
|
4372
|
+
// src/shared/constants/share.ts
|
|
4373
|
+
var SHARE_JSON_BASENAME = "share.json";
|
|
4374
|
+
var SHARE_BAK_DIRNAME = "share.bak";
|
|
4375
|
+
var DEFAULT_MAX_SHARE_JSON_BYTES = 512 * 1024;
|
|
4376
|
+
var REPORT_SHARE_MAX_BYTES = 8 * 1024 * 1024;
|
|
4377
|
+
var PROJECT_SHARE_PREPARED_MAX_BYTES = PROJECT_UPLOAD_MAX_ZIP_BYTES;
|
|
4378
|
+
var SHARE_CACHE_REASON_MESSAGES = {
|
|
4379
|
+
cache_hit: "analysis cache hit",
|
|
4380
|
+
no_cache: "project cache is disabled",
|
|
4381
|
+
cache_unavailable: "project cache is unavailable",
|
|
4382
|
+
run_missing: "cached analysis run is missing",
|
|
4383
|
+
files_changed: "tracked files changed since last analysis",
|
|
4384
|
+
files_index_recovered: "cache files index was recovered",
|
|
4385
|
+
run_binding_stale: "cached analysis binding is stale",
|
|
4386
|
+
producer_succeeded: "analysis recomputed and cache updated",
|
|
4387
|
+
run_invalid: "cached analysis run is invalid",
|
|
4388
|
+
archive_ingest_no_project_cache: "archive uploads do not use persistent project cache"
|
|
4389
|
+
};
|
|
4390
|
+
|
|
4391
|
+
// src/shared/constants/worker.ts
|
|
4392
|
+
var WORKER_INGEST_FORCE_QUERY = "force";
|
|
4393
|
+
var WORKER_IDLE_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
4394
|
+
|
|
4395
|
+
// src/shared/locales/targets/segmentWritePlan.ts
|
|
4396
|
+
function swapLocaleInSegmentRelativePath(input) {
|
|
4397
|
+
const target = normalizeLanguageCode(input.targetLocale);
|
|
4398
|
+
const rel = input.relativePath.replace(/\\/g, "/");
|
|
4399
|
+
if (input.structure === "locale_file") {
|
|
4400
|
+
if (rel.includes("/")) return null;
|
|
4401
|
+
return `${target}.json`;
|
|
4402
|
+
}
|
|
4403
|
+
if (input.structure === "locale_per_dir") {
|
|
4404
|
+
const slash = rel.indexOf("/");
|
|
4405
|
+
if (slash < 0) return null;
|
|
4406
|
+
const rest = rel.slice(slash + 1);
|
|
4407
|
+
if (!rest) return null;
|
|
4408
|
+
return `${target}/${rest}`;
|
|
4409
|
+
}
|
|
4410
|
+
if (input.structure === "feature_bundle") {
|
|
4411
|
+
const slash = rel.lastIndexOf("/");
|
|
4412
|
+
if (slash < 0) return null;
|
|
4413
|
+
const feature = rel.slice(0, slash);
|
|
4414
|
+
if (!feature) return null;
|
|
4415
|
+
return `${feature}/${target}.json`;
|
|
4416
|
+
}
|
|
4417
|
+
return null;
|
|
4418
|
+
}
|
|
4419
|
+
function segmentTargetFromRef(ref, role) {
|
|
4420
|
+
return {
|
|
4421
|
+
locale: normalizeLanguageCode(ref.locale),
|
|
4422
|
+
relativePath: ref.relativePath,
|
|
4423
|
+
absolutePath: ref.absolutePath,
|
|
4424
|
+
role
|
|
4425
|
+
};
|
|
4426
|
+
}
|
|
4427
|
+
function deriveTargetSegmentFromSource(ctx, layout, targetLocale) {
|
|
4428
|
+
const sourceRef = localeSegmentRefFromAbsolute({
|
|
4429
|
+
layout,
|
|
4430
|
+
path: ctx.adapters.path,
|
|
4431
|
+
absolutePath: ctx.adapters.path.resolve(ctx.paths.sourceLocale)
|
|
4432
|
+
});
|
|
4433
|
+
if (sourceRef === null) {
|
|
4434
|
+
throw new I18nPruneError(
|
|
4435
|
+
`generate: source locale path does not match layout mode=${layout.mode} structure=${layout.structure}: ${ctx.paths.sourceLocale}`,
|
|
4436
|
+
"USAGE"
|
|
4437
|
+
);
|
|
4438
|
+
}
|
|
4439
|
+
const nextRelative = swapLocaleInSegmentRelativePath({
|
|
4440
|
+
structure: layout.structure,
|
|
4441
|
+
relativePath: sourceRef.relativePath,
|
|
4442
|
+
targetLocale
|
|
4443
|
+
});
|
|
4444
|
+
if (nextRelative === null) {
|
|
4445
|
+
throw new I18nPruneError(
|
|
4446
|
+
`generate: cannot derive target segment from source ${sourceRef.relativePath} for structure=${layout.structure}`,
|
|
4447
|
+
"USAGE"
|
|
4448
|
+
);
|
|
4449
|
+
}
|
|
4450
|
+
const absolutePath = resolveLocaleSegmentAbsolutePath({
|
|
4451
|
+
layout,
|
|
4452
|
+
path: ctx.adapters.path,
|
|
4453
|
+
locale: targetLocale,
|
|
4454
|
+
segmentRelativePath: nextRelative
|
|
4455
|
+
});
|
|
4456
|
+
return {
|
|
4457
|
+
locale: normalizeLanguageCode(targetLocale),
|
|
4458
|
+
relativePath: nextRelative,
|
|
4459
|
+
absolutePath,
|
|
4460
|
+
role: "target"
|
|
4461
|
+
};
|
|
4462
|
+
}
|
|
4463
|
+
function listSourceLocaleWriteTargets(ctx) {
|
|
4464
|
+
const source = sourceLocaleCodeFromContext(ctx);
|
|
4465
|
+
return segmentsForLocaleCode(ctx, source).map((s) => segmentTargetFromRef(s, "source"));
|
|
4466
|
+
}
|
|
4467
|
+
function resolveTargetLocaleWritePlan(ctx, targetLocale) {
|
|
4468
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
4469
|
+
const target = normalizeLanguageCode(targetLocale);
|
|
4470
|
+
const { fs } = ctx.adapters;
|
|
4471
|
+
if (layout.mode === "flat_file") {
|
|
4472
|
+
const existing = segmentsForLocaleCode(ctx, target);
|
|
4473
|
+
if (existing.length > 0) {
|
|
4474
|
+
const primary = primarySegmentForLocale(ctx, target);
|
|
4475
|
+
const segments2 = [segmentTargetFromRef(primary, "existing_target")];
|
|
4476
|
+
return {
|
|
4477
|
+
targetLocale: target,
|
|
4478
|
+
layout,
|
|
4479
|
+
segments: segments2,
|
|
4480
|
+
missingSegments: existsRuntimeFsSync(primary.absolutePath, fs) ? [] : segments2
|
|
4481
|
+
};
|
|
4482
|
+
}
|
|
4483
|
+
const derived = deriveTargetSegmentFromSource(ctx, layout, target);
|
|
4484
|
+
const missingSegments2 = existsRuntimeFsSync(derived.absolutePath, fs) ? [] : [derived];
|
|
4485
|
+
return { targetLocale: target, layout, segments: [derived], missingSegments: missingSegments2 };
|
|
4486
|
+
}
|
|
4487
|
+
const sourceSegments = listSourceLocaleWriteTargets(ctx);
|
|
4488
|
+
const existingByRel = new Map(
|
|
4489
|
+
segmentsForLocaleCode(ctx, target).map((s) => [s.relativePath, s])
|
|
4490
|
+
);
|
|
4491
|
+
const segments = [];
|
|
4492
|
+
for (const src of sourceSegments) {
|
|
4493
|
+
const targetRel = swapLocaleInSegmentRelativePath({
|
|
4494
|
+
structure: layout.structure,
|
|
4495
|
+
relativePath: src.relativePath,
|
|
4496
|
+
targetLocale: target
|
|
4497
|
+
});
|
|
4498
|
+
if (targetRel === null) {
|
|
4499
|
+
throw new I18nPruneError(
|
|
4500
|
+
`generate: cannot derive target segment from source ${src.relativePath} for structure=${layout.structure}`,
|
|
4501
|
+
"USAGE"
|
|
4502
|
+
);
|
|
4503
|
+
}
|
|
4504
|
+
const onDisk = existingByRel.get(targetRel);
|
|
4505
|
+
if (onDisk) {
|
|
4506
|
+
segments.push(segmentTargetFromRef(onDisk, "existing_target"));
|
|
4507
|
+
continue;
|
|
4508
|
+
}
|
|
4509
|
+
const absolutePath = resolveLocaleSegmentAbsolutePath({
|
|
4510
|
+
layout,
|
|
4511
|
+
path: ctx.adapters.path,
|
|
4512
|
+
locale: target,
|
|
4513
|
+
segmentRelativePath: targetRel
|
|
4514
|
+
});
|
|
4515
|
+
segments.push({
|
|
4516
|
+
locale: target,
|
|
4517
|
+
relativePath: targetRel,
|
|
4518
|
+
absolutePath,
|
|
4519
|
+
role: "target"
|
|
4520
|
+
});
|
|
4521
|
+
}
|
|
4522
|
+
segments.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
4523
|
+
const missingSegments = segments.filter((s) => !existsRuntimeFsSync(s.absolutePath, fs));
|
|
4524
|
+
return { targetLocale: target, layout, segments, missingSegments };
|
|
4525
|
+
}
|
|
4526
|
+
function resolvePrimaryTargetWritePath(ctx, targetLocale) {
|
|
4527
|
+
const plan = resolveTargetLocaleWritePlan(ctx, targetLocale);
|
|
4528
|
+
const primary = plan.segments[0];
|
|
4529
|
+
if (!primary) {
|
|
4530
|
+
throw new I18nPruneError(`generate: no write path for target locale ${targetLocale}`, "USAGE");
|
|
4531
|
+
}
|
|
4532
|
+
return primary.absolutePath;
|
|
4533
|
+
}
|
|
4534
|
+
|
|
4535
|
+
// src/shared/locales/projection.ts
|
|
4536
|
+
function isPlainObject7(x) {
|
|
4537
|
+
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
4538
|
+
}
|
|
4539
|
+
function pushLeaf(out, leaf, winner) {
|
|
4540
|
+
const cur = out.get(leaf.path);
|
|
4541
|
+
if (!cur) {
|
|
4542
|
+
out.set(leaf.path, { leaf, winner });
|
|
4543
|
+
return { conflictsAdded: 0 };
|
|
4544
|
+
}
|
|
4545
|
+
if (cur.winner === "nested") {
|
|
4546
|
+
return { conflictsAdded: winner === "dotted" ? 1 : 0 };
|
|
4547
|
+
}
|
|
4548
|
+
if (winner === "nested") {
|
|
4549
|
+
out.set(leaf.path, { leaf, winner });
|
|
4550
|
+
return { conflictsAdded: 1 };
|
|
4551
|
+
}
|
|
4552
|
+
return { conflictsAdded: 0 };
|
|
4553
|
+
}
|
|
4554
|
+
function collectLeavesPreferNested(input) {
|
|
4555
|
+
let sawDottedKey = false;
|
|
4556
|
+
let conflicts = 0;
|
|
4557
|
+
const { root, prefix } = input;
|
|
4558
|
+
if (typeof root === "string") {
|
|
4559
|
+
if (prefix) {
|
|
4560
|
+
const { conflictsAdded } = pushLeaf(input.out, {
|
|
4561
|
+
path: prefix,
|
|
4562
|
+
value: root,
|
|
4563
|
+
shape: "legacy_string",
|
|
4564
|
+
confidence: null,
|
|
4565
|
+
needsReview: null
|
|
4566
|
+
}, input.winner);
|
|
4567
|
+
conflicts += conflictsAdded;
|
|
4568
|
+
}
|
|
4569
|
+
return { sawDottedKey, conflicts };
|
|
4570
|
+
}
|
|
4571
|
+
if (isStructuredLocaleLeafNode(root)) {
|
|
4572
|
+
if (prefix) {
|
|
4573
|
+
const { conflictsAdded } = pushLeaf(
|
|
4574
|
+
input.out,
|
|
4575
|
+
{
|
|
4576
|
+
path: prefix,
|
|
4577
|
+
value: root.value,
|
|
4578
|
+
shape: "legacy_string",
|
|
4579
|
+
confidence: null,
|
|
4580
|
+
needsReview: null
|
|
4581
|
+
},
|
|
4582
|
+
input.winner
|
|
4583
|
+
);
|
|
4584
|
+
conflicts += conflictsAdded;
|
|
4585
|
+
}
|
|
4586
|
+
return { sawDottedKey, conflicts };
|
|
4587
|
+
}
|
|
4588
|
+
if (Array.isArray(root)) {
|
|
4589
|
+
root.forEach((item, i) => {
|
|
4590
|
+
const p = prefix ? `${prefix}[${i}]` : `[${i}]`;
|
|
4591
|
+
const r = collectLeavesPreferNested({ root: item, prefix: p, out: input.out, winner: input.winner });
|
|
4592
|
+
if (r.sawDottedKey) sawDottedKey = true;
|
|
4593
|
+
conflicts += r.conflicts;
|
|
4594
|
+
});
|
|
4595
|
+
return { sawDottedKey, conflicts };
|
|
4596
|
+
}
|
|
4597
|
+
if (isPlainObject7(root)) {
|
|
4598
|
+
const keys = Object.keys(root);
|
|
4599
|
+
const nestedKeys = keys.filter((k) => !k.includes("."));
|
|
4600
|
+
const dottedKeys = keys.filter((k) => k.includes("."));
|
|
4601
|
+
for (const k of nestedKeys) {
|
|
4602
|
+
const p = prefix ? `${prefix}.${k}` : k;
|
|
4603
|
+
const r = collectLeavesPreferNested({ root: root[k], prefix: p, out: input.out, winner: input.winner });
|
|
4604
|
+
if (r.sawDottedKey) sawDottedKey = true;
|
|
4605
|
+
conflicts += r.conflicts;
|
|
4606
|
+
}
|
|
4607
|
+
for (const k of dottedKeys) {
|
|
4608
|
+
sawDottedKey = true;
|
|
4609
|
+
const p = prefix ? `${prefix}.${k}` : k;
|
|
4610
|
+
const r = collectLeavesPreferNested({ root: root[k], prefix: p, out: input.out, winner: "dotted" });
|
|
4611
|
+
if (r.sawDottedKey) sawDottedKey = true;
|
|
4612
|
+
conflicts += r.conflicts;
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
return { sawDottedKey, conflicts };
|
|
4616
|
+
}
|
|
4617
|
+
function projectLocaleLeaves(localeJson) {
|
|
4618
|
+
const tmp = /* @__PURE__ */ new Map();
|
|
4619
|
+
const r = collectLeavesPreferNested({ root: localeJson, prefix: "", out: tmp, winner: "nested" });
|
|
4620
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
4621
|
+
for (const [k, v] of tmp) byPath.set(k, v.leaf);
|
|
4622
|
+
return { byPath, sawDottedKey: r.sawDottedKey, conflicts: r.conflicts };
|
|
4623
|
+
}
|
|
4624
|
+
function getProjectedLeafString(proj, path) {
|
|
4625
|
+
const leaf = proj.byPath.get(path);
|
|
4626
|
+
if (!leaf) return void 0;
|
|
4627
|
+
return leaf.value;
|
|
4628
|
+
}
|
|
4629
|
+
|
|
4630
|
+
// src/shared/locales/targets/segmentMaterialize.ts
|
|
4631
|
+
function localeJsonFromTranslationSurfaceLeaves(leaves) {
|
|
4632
|
+
let out = {};
|
|
4633
|
+
for (const leaf of leaves) {
|
|
4634
|
+
out = setAtPath(out, leaf.path, leaf.value);
|
|
4635
|
+
}
|
|
4636
|
+
return out;
|
|
4637
|
+
}
|
|
4638
|
+
function pathsForSourceSegment(input) {
|
|
4639
|
+
const fromOrigin = input.sourceLeaves.filter((l) => l.fileOrigin?.relativePath === input.sourceRelativePath);
|
|
4640
|
+
if (fromOrigin.length > 0) {
|
|
4641
|
+
return new Set(fromOrigin.map((l) => l.path));
|
|
4642
|
+
}
|
|
4643
|
+
const absoluteFile = resolveLocaleSegmentAbsolutePath({
|
|
4644
|
+
layout: input.layout,
|
|
4645
|
+
path: input.path,
|
|
4646
|
+
locale: input.sourceLocaleCode,
|
|
4647
|
+
segmentRelativePath: input.sourceRelativePath
|
|
4648
|
+
});
|
|
4649
|
+
const read = readFlatLocaleJsonSurface({
|
|
4650
|
+
fs: input.fs,
|
|
4651
|
+
path: input.path,
|
|
4652
|
+
absoluteFile,
|
|
4653
|
+
localesDir: input.layout.directoryAbsolute,
|
|
4654
|
+
structure: input.layout.structure
|
|
4655
|
+
});
|
|
4656
|
+
if (read.ok) {
|
|
4657
|
+
const filePaths = new Set(read.leaves.map((l) => l.path));
|
|
4658
|
+
const intersected = input.sourceLeaves.filter((l) => filePaths.has(l.path)).map((l) => l.path);
|
|
4659
|
+
if (intersected.length > 0) {
|
|
4660
|
+
return new Set(intersected);
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
if (input.singleSegmentFallback) {
|
|
4664
|
+
return new Set(input.sourceLeaves.map((l) => l.path));
|
|
4665
|
+
}
|
|
4666
|
+
return /* @__PURE__ */ new Set();
|
|
4667
|
+
}
|
|
4668
|
+
function materializeGenerateWorkingBySegment(input) {
|
|
4669
|
+
const sourceLocale = input.sourceLocaleCode;
|
|
4670
|
+
const projected = projectLocaleLeaves(input.working);
|
|
4671
|
+
const singleSegmentFallback = input.segments.length === 1;
|
|
4672
|
+
return input.segments.map((segment) => {
|
|
4673
|
+
const sourceRel = swapLocaleInSegmentRelativePath({
|
|
4674
|
+
structure: input.structure,
|
|
4675
|
+
relativePath: segment.relativePath,
|
|
4676
|
+
targetLocale: sourceLocale
|
|
4677
|
+
}) ?? segment.relativePath;
|
|
4678
|
+
const pathsForSegment = pathsForSourceSegment({
|
|
4679
|
+
layout: input.layout,
|
|
4680
|
+
fs: input.fs,
|
|
4681
|
+
path: input.path,
|
|
4682
|
+
sourceLocaleCode: sourceLocale,
|
|
4683
|
+
sourceRelativePath: sourceRel,
|
|
4684
|
+
sourceLeaves: input.sourceLeaves,
|
|
4685
|
+
singleSegmentFallback
|
|
4686
|
+
});
|
|
4687
|
+
let document = {};
|
|
4688
|
+
for (const leafPath of pathsForSegment) {
|
|
4689
|
+
const workingValue = getLocaleLeafAtPath(input.working, leafPath);
|
|
4690
|
+
let value;
|
|
4691
|
+
if (isStructuredLocaleLeafNode(workingValue)) {
|
|
4692
|
+
value = workingValue;
|
|
4693
|
+
} else {
|
|
4694
|
+
const projectedValue = getProjectedLeafString(projected, leafPath);
|
|
4695
|
+
value = projectedValue !== void 0 ? projectedValue : workingValue;
|
|
4696
|
+
}
|
|
4697
|
+
if (value !== void 0) {
|
|
4698
|
+
document = setAtPath(document, leafPath, value);
|
|
4699
|
+
}
|
|
4700
|
+
}
|
|
4701
|
+
return { segment, document };
|
|
4702
|
+
});
|
|
4703
|
+
}
|
|
4704
|
+
|
|
4705
|
+
// src/shared/locales/archive/buildLocaleJsonByTag.ts
|
|
4706
|
+
function segmentRelUnderLocalesDir(localesDirAbsolute, absolutePath) {
|
|
4707
|
+
const root = localesDirAbsolute.replace(/\\/g, "/").replace(/\/$/, "");
|
|
4708
|
+
const abs = absolutePath.replace(/\\/g, "/");
|
|
4709
|
+
if (abs === root) return "";
|
|
4710
|
+
const prefix = `${root}/`;
|
|
4711
|
+
if (!abs.startsWith(prefix)) return null;
|
|
4712
|
+
return abs.slice(prefix.length);
|
|
4713
|
+
}
|
|
4714
|
+
function collectArchiveLocaleSegments(input) {
|
|
4715
|
+
const { path, localesDirAbsolute, archiveRelPaths, locales, resolveArchiveAbsolute } = input;
|
|
4716
|
+
const layout = resolveLocalesLayout(locales, localesDirAbsolute);
|
|
4717
|
+
const recursive = layout.structure !== "locale_file";
|
|
4718
|
+
const segments = [];
|
|
4719
|
+
for (const archiveRelPath of archiveRelPaths) {
|
|
4720
|
+
if (!archiveRelPath.endsWith(".json")) continue;
|
|
4721
|
+
const absolutePath = resolveArchiveAbsolute(archiveRelPath);
|
|
4722
|
+
const segmentRel = segmentRelUnderLocalesDir(localesDirAbsolute, absolutePath);
|
|
4723
|
+
if (segmentRel === null) continue;
|
|
4724
|
+
if (!recursive && segmentRel.includes("/")) continue;
|
|
4725
|
+
const locale = localeCodeForSegment(layout.structure, path, { absolutePath, relativePath: segmentRel });
|
|
4726
|
+
if (locale === null) continue;
|
|
4727
|
+
segments.push({ locale, relativePath: segmentRel, absolutePath, archiveRelPath });
|
|
4728
|
+
}
|
|
4729
|
+
segments.sort((a, b) => {
|
|
4730
|
+
const byLocale = a.locale.localeCompare(b.locale);
|
|
4731
|
+
if (byLocale !== 0) return byLocale;
|
|
4732
|
+
return a.relativePath.localeCompare(b.relativePath);
|
|
4733
|
+
});
|
|
4734
|
+
return segments;
|
|
4735
|
+
}
|
|
4736
|
+
function listLocaleCodesFromArchive(input) {
|
|
4737
|
+
const segments = collectArchiveLocaleSegments(input);
|
|
4738
|
+
return [...new Set(segments.map((s) => s.locale))].sort((a, b) => a.localeCompare(b));
|
|
4739
|
+
}
|
|
4740
|
+
function buildLocaleJsonByTagFromArchive(input) {
|
|
4741
|
+
const { readText, sourceLocaleAbsolute } = input;
|
|
4742
|
+
const segments = collectArchiveLocaleSegments(input);
|
|
4743
|
+
const byLocale = /* @__PURE__ */ new Map();
|
|
4744
|
+
for (const segment of segments) {
|
|
4745
|
+
const list = byLocale.get(segment.locale) ?? [];
|
|
4746
|
+
list.push(segment);
|
|
4747
|
+
byLocale.set(segment.locale, list);
|
|
4748
|
+
}
|
|
4749
|
+
const out = {};
|
|
4750
|
+
for (const [locale, localeSegments] of byLocale) {
|
|
4751
|
+
let primary = localeSegments[0];
|
|
4752
|
+
if (sourceLocaleAbsolute !== void 0) {
|
|
4753
|
+
const sourceMatch = localeSegments.find((s) => s.absolutePath === sourceLocaleAbsolute);
|
|
4754
|
+
if (sourceMatch) primary = sourceMatch;
|
|
4755
|
+
}
|
|
4756
|
+
const raw = readText(primary.archiveRelPath);
|
|
4757
|
+
if (raw === void 0) continue;
|
|
4758
|
+
try {
|
|
4759
|
+
const parsed = JSON.parse(raw);
|
|
4760
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
|
|
4761
|
+
out[locale] = parsed;
|
|
4762
|
+
} catch {
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
return out;
|
|
4766
|
+
}
|
|
4767
|
+
|
|
4768
|
+
// src/shared/locales/surface/localeSurface.ts
|
|
4769
|
+
function readLocaleLeavesForCode(ctx, localeCode) {
|
|
4770
|
+
const read = readLocaleCodeSurfaceFromContext(ctx, localeCode);
|
|
4771
|
+
if (!read.ok) return [];
|
|
4772
|
+
return read.leaves;
|
|
4773
|
+
}
|
|
4774
|
+
function readSourceLocaleLeaves(ctx) {
|
|
4775
|
+
return readLocaleLeavesForCode(ctx, sourceLocaleCodeFromContext(ctx));
|
|
4776
|
+
}
|
|
4777
|
+
|
|
4778
|
+
// src/shared/locales/surface/readJson.ts
|
|
4779
|
+
function readLocaleJsonOrEmpty(ctx, absolutePath) {
|
|
4780
|
+
if (!existsRuntimeFsSync(absolutePath, ctx.adapters.fs)) {
|
|
4781
|
+
return {};
|
|
4782
|
+
}
|
|
4783
|
+
const read = readLocaleSegmentFromContext(ctx, absolutePath);
|
|
4784
|
+
if (!read.ok) return {};
|
|
4785
|
+
return read.document;
|
|
4786
|
+
}
|
|
4787
|
+
|
|
4788
|
+
// src/shared/locales/surface/segmentPairing.ts
|
|
4789
|
+
function pairedSourceSegmentRelativePath(ctx, targetSegmentRelativePath, _targetLocaleCode) {
|
|
4790
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
4791
|
+
const sourceCode = sourceLocaleCodeFromContext(ctx);
|
|
4792
|
+
return swapLocaleInSegmentRelativePath({
|
|
4793
|
+
structure: layout.structure,
|
|
4794
|
+
relativePath: targetSegmentRelativePath,
|
|
4795
|
+
targetLocale: sourceCode
|
|
4796
|
+
});
|
|
4797
|
+
}
|
|
4798
|
+
function resolvePairedSourceSegmentAbsolutePath(ctx, targetSegmentRelativePath, targetLocaleCode) {
|
|
4799
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
4800
|
+
const sourceCode = sourceLocaleCodeFromContext(ctx);
|
|
4801
|
+
const sourceRel = pairedSourceSegmentRelativePath(ctx, targetSegmentRelativePath) ?? targetSegmentRelativePath;
|
|
4802
|
+
return resolveLocaleSegmentAbsolutePath({
|
|
4803
|
+
layout,
|
|
4804
|
+
path: ctx.adapters.path,
|
|
4805
|
+
locale: sourceCode,
|
|
4806
|
+
segmentRelativePath: sourceRel
|
|
4807
|
+
});
|
|
4808
|
+
}
|
|
4809
|
+
function inferSourceSegmentRelativePath(ctx, key) {
|
|
4810
|
+
const sourceCode = sourceLocaleCodeFromContext(ctx);
|
|
4811
|
+
const segments = segmentsForLocaleCode(ctx, sourceCode);
|
|
4812
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
4813
|
+
const primary = primarySegmentForLocale(ctx, sourceCode);
|
|
4814
|
+
const fallback = primary?.relativePath ?? segments[0]?.relativePath ?? `${sourceCode}.json`;
|
|
4815
|
+
if (layout.structure !== "feature_bundle" || segments.length <= 1) {
|
|
4816
|
+
return fallback;
|
|
4817
|
+
}
|
|
4818
|
+
const featureDirs = new Set(
|
|
4819
|
+
segments.map((s) => {
|
|
4820
|
+
const slash = s.relativePath.indexOf("/");
|
|
4821
|
+
return slash >= 0 ? s.relativePath.slice(0, slash) : null;
|
|
4822
|
+
}).filter((name) => name !== null && name.length > 0)
|
|
4823
|
+
);
|
|
4824
|
+
const top = key.includes(".") ? key.slice(0, key.indexOf(".")) : key;
|
|
4825
|
+
if (featureDirs.has(top)) {
|
|
4826
|
+
return `${top}/${sourceCode}.json`;
|
|
4827
|
+
}
|
|
4828
|
+
return fallback;
|
|
4829
|
+
}
|
|
4830
|
+
function sourceSegmentRelativePathForKey(ctx, key, sourceLeaves) {
|
|
4831
|
+
const existing = sourceLeaves.find((leaf) => leaf.path === key);
|
|
4832
|
+
if (existing?.fileOrigin?.relativePath) {
|
|
4833
|
+
return existing.fileOrigin.relativePath;
|
|
4834
|
+
}
|
|
4835
|
+
return inferSourceSegmentRelativePath(ctx, key);
|
|
4836
|
+
}
|
|
4837
|
+
function targetSegmentRelativePathForKey(ctx, localeCode, key, sourceLeaves) {
|
|
4838
|
+
const layout = resolveLocalesLayoutFromContext(ctx);
|
|
4839
|
+
const sourceCode = sourceLocaleCodeFromContext(ctx);
|
|
4840
|
+
const sourceRel = sourceSegmentRelativePathForKey(ctx, key, sourceLeaves);
|
|
4841
|
+
if (localeCode === sourceCode) {
|
|
4842
|
+
return sourceRel;
|
|
4843
|
+
}
|
|
4844
|
+
const swapped = swapLocaleInSegmentRelativePath({
|
|
4845
|
+
structure: layout.structure,
|
|
4846
|
+
relativePath: sourceRel,
|
|
4847
|
+
targetLocale: localeCode
|
|
4848
|
+
});
|
|
4849
|
+
if (swapped !== null) {
|
|
4850
|
+
return swapped;
|
|
4851
|
+
}
|
|
4852
|
+
const primary = primarySegmentForLocale(ctx, localeCode);
|
|
4853
|
+
return primary?.relativePath ?? `${localeCode}.json`;
|
|
4854
|
+
}
|
|
4855
|
+
|
|
4856
|
+
// src/shared/locales/surface/syncSegment.ts
|
|
4857
|
+
function buildSegmentTemplateFromSource(_sourceRaw, leaves) {
|
|
4858
|
+
let template = {};
|
|
4859
|
+
for (const leaf of leaves) {
|
|
4860
|
+
template = setAtPath(template, leaf.path, leaf.value);
|
|
4861
|
+
}
|
|
4862
|
+
return template;
|
|
4863
|
+
}
|
|
4864
|
+
function resolveSyncSegmentSourcePlan(ctx, input) {
|
|
4865
|
+
const sourceRelativePath = pairedSourceSegmentRelativePath(ctx, input.targetSegmentRelativePath, input.targetLocaleCode) ?? input.targetSegmentRelativePath;
|
|
4866
|
+
const sourceAbsolutePath = resolvePairedSourceSegmentAbsolutePath(
|
|
4867
|
+
ctx,
|
|
4868
|
+
input.targetSegmentRelativePath,
|
|
4869
|
+
input.targetLocaleCode
|
|
4870
|
+
);
|
|
4871
|
+
let sourceRaw = {};
|
|
4872
|
+
let allSourceLeaves = [];
|
|
4873
|
+
if (existsRuntimeFsSync(sourceAbsolutePath, ctx.adapters.fs)) {
|
|
4874
|
+
const read = readLocaleSegmentFromContext(ctx, sourceAbsolutePath);
|
|
4875
|
+
if (read.ok) {
|
|
4876
|
+
sourceRaw = read.document;
|
|
4877
|
+
allSourceLeaves = read.leaves;
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4880
|
+
const effectiveSchemaPaths = input.schemaPaths.size > 0 ? input.schemaPaths : new Set(allSourceLeaves.map((l) => l.path));
|
|
4881
|
+
const effectiveSourceLeaves = allSourceLeaves.filter((l) => effectiveSchemaPaths.has(l.path));
|
|
4882
|
+
const template = buildSegmentTemplateFromSource(sourceRaw, effectiveSourceLeaves);
|
|
4883
|
+
return {
|
|
4884
|
+
sourceRelativePath,
|
|
4885
|
+
sourceAbsolutePath,
|
|
4886
|
+
sourceRaw,
|
|
4887
|
+
effectiveSourceLeaves,
|
|
4888
|
+
template,
|
|
4889
|
+
sourceMap: new Map(effectiveSourceLeaves.map((l) => [l.path, l.value]))
|
|
4890
|
+
};
|
|
4891
|
+
}
|
|
4892
|
+
function resolveGlobalSyncSchemaPaths(ctx, schemaPaths) {
|
|
4893
|
+
if (schemaPaths.size > 0) return schemaPaths;
|
|
4894
|
+
return new Set(readSourceLocaleLeaves(ctx).map((l) => l.path));
|
|
4895
|
+
}
|
|
4896
|
+
|
|
4897
|
+
export { ANALYSIS_BASENAME, CACHE_PROFILE_DEFAULTS, CACHE_SCHEMA_VERSION, DEFAULT_CACHE_PROFILE_ID, DEFAULT_HEAL_EVERY_RUNS, DEFAULT_LIST_TOP, DEFAULT_MAX_SHARE_JSON_BYTES, DEFAULT_MISSING_LEAF_PLACEHOLDER, DEFAULT_WORKER_API_URL, DEMO_REPORT_URL, DEMO_WEB_APP_BASE, DOCS_ISSUES_PAGE_PATH, DOCS_SITE_BASE, DOCS_SITE_ORIGIN, ENV_TRANSLATE_DEEPL_API_KEY, ENV_TRANSLATE_LIBRE_URL, ENV_TRANSLATE_LLM_API_KEY, ENV_TRANSLATE_LLM_BASE_URL, ENV_TRANSLATE_LLM_MODEL, ENV_TRANSLATE_MAX_WORKERS, ENV_TRANSLATE_PROVIDER, GITHUB_BASE, GITHUB_DOCS_BASE, GITHUB_DOCS_TREE_BASE, GITHUB_OWNER, GITHUB_REPO, GITHUB_REPO_URL, HOSTED_PROJECT_SNAPSHOT_SCHEMA_VERSION, I18NPRUNE_CONFIG_BASENAME, I18NPRUNE_CONFIG_JSON_FILE_NAME, I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES, I18NPRUNE_CONFIG_SCRIPT_FILE_NAMES_SET, I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES, I18NPRUNE_CONFIG_SNAPSHOT_FILE_NAMES_SET, I18nPruneError, I18nPruneJsonParseError, ISSUE_CLEANUP_RIPGREP_UNAVAILABLE, ISSUE_CLEANUP_UNCERTAIN_PATHS_EXCLUDED, ISSUE_CLI_INVALID_JSON_PRETTY, ISSUE_CONFIG_INVALID, ISSUE_CONFIG_LOAD_FAILED, ISSUE_CONFIG_MISSING, ISSUE_CONTEXT_DISCOVERY_WARNING, ISSUE_CONTEXT_RESOLUTION_FAILED, ISSUE_DOCTOR_CONFIG_MISSING_FILE, ISSUE_DOCTOR_PATHS_DIRECTORIES_MISSING, ISSUE_DOCTOR_PATHS_SOURCE_LOCALE_MISSING, ISSUE_DOCTOR_RUNTIME_UNSUPPORTED_NODE, ISSUE_DOCTOR_TOOLS_RG_NOT_ON_PATH, ISSUE_GENERATE_SOURCE_EMPTY_STRING_LEAVES, ISSUE_GENERATE_TRANSLATE_NETWORK_ERROR, ISSUE_GENERATE_TRANSLATE_RATE_LIMITED, ISSUE_GENERATE_USAGE, ISSUE_IO_READ_FAILED, ISSUE_LANGUAGES_EMPTY_FILTER, ISSUE_LANGUAGES_UNSUPPORTED_LANGUAGE_CODE, ISSUE_LOCALES_USAGE, ISSUE_LOCALE_SOURCE_PLACEHOLDER_LEAVES, ISSUE_LOCALE_TARGET_NOT_FOUND, ISSUE_LOCALE_TARGET_PLACEHOLDER_LEAVES, ISSUE_MISSING_PATHS_NOT_IN_SCAN, ISSUE_PATCHING_CATALOG_MISMATCH_DIRECTION, ISSUE_PATCHING_CATALOG_MISMATCH_ENGLISH, ISSUE_PATCHING_CATALOG_MISMATCH_NATIVE, ISSUE_PATCHING_CONFIG_INVALID_SCHEMA, ISSUE_PATCHING_CONFIG_LOCALE_MISSING_FILE, ISSUE_PATCHING_CONFIG_PARSE_FAILED, ISSUE_PATCHING_CONFIG_SECTION_INCOMPLETE, ISSUE_PATCHING_CONFIG_SIZE_ANOMALY, ISSUE_PATCHING_CONFIG_TOO_LARGE, ISSUE_PATCHING_FILE_LOCALE_MISSING_CONFIG, ISSUE_PATHS_NETWORK_DRIVE, ISSUE_PATHS_WINDOWS_LONG_PATH, ISSUE_PATHS_WINDOWS_RESERVED_NAME, ISSUE_PROJECT_CONFIG_FILE_MISSING, ISSUE_PROJECT_HOSTED_SNAPSHOT_INVALID, ISSUE_PROJECT_HOSTED_SNAPSHOT_SCHEMA_VERSION, ISSUE_PROJECT_LOCALES_DIR_UNAVAILABLE, ISSUE_PROJECT_LOCALES_SOURCE_NOT_IN_BUNDLE, ISSUE_PROJECT_LOCALES_SOURCE_NOT_LANGUAGE_CODE, ISSUE_PROJECT_LOCALES_STRUCTURE_REQUIRED, ISSUE_PROJECT_SOURCE_LOCALE_INVALID_JSON, ISSUE_PROJECT_SOURCE_LOCALE_INVALID_SHAPE, ISSUE_PROJECT_SOURCE_LOCALE_MISSING_SEGMENTS, ISSUE_PROJECT_SOURCE_LOCALE_NOT_FOUND, ISSUE_PROJECT_SOURCE_LOCALE_UNAVAILABLE, ISSUE_PROJECT_SRC_ROOT_UNAVAILABLE, ISSUE_PROJECT_UPLOAD_CONFIG_JSON_INVALID, ISSUE_PROJECT_UPLOAD_CONFIG_REQUIRED, ISSUE_QUALITY_ENGLISH_IDENTICAL_LEAVES, ISSUE_REPORT_HOSTED_REPORT_INVALID, ISSUE_REPORT_INVALID_FORMAT, ISSUE_SCAN_DYNAMIC_KEY_SITES, ISSUE_SHARE_CACHE_EMPTY, ISSUE_SHARE_CACHE_ENTRY_NOT_FOUND, ISSUE_SHARE_JSON_REPAIRED, ISSUE_SHARE_JSON_WRITE_FAILED, ISSUE_SHARE_PREPARE_ANALYSIS_FAILED, ISSUE_SHARE_PREPARE_NOTHING_REQUESTED, ISSUE_SHARE_PREPARE_REPORT_FROM_ARCHIVE_FAILED, ISSUE_SHARE_PREPARE_REPORT_HOST_REQUIRED, ISSUE_SHARE_REMOTE_ERROR, ISSUE_SHARE_REMOTE_PAYLOAD_TOO_LARGE, ISSUE_SHARE_REMOTE_PROJECT_NOT_FOUND, ISSUE_SHARE_REMOTE_REPORT_NOT_FOUND, ISSUE_SHARE_REMOTE_REPORT_REJECTED, ISSUE_SHARE_REMOTE_UNAVAILABLE, ISSUE_SHARE_REMOTE_UPLOAD_REJECTED, ISSUE_SHARE_SNAPSHOT_EMPTY, ISSUE_SHARE_STALE_CACHE_ROW_REMOVED, ISSUE_SHARE_ZIP_FAILED, ISSUE_SYNC_LOCALE_FILE_NOT_FOUND, ISSUE_SYNC_METADATA_FLAG_CONFLICT, ISSUE_TRANSLATE_CONFIG_DEFAULT_APPLIED, ISSUE_TRANSLATE_HANDOFF_NO_ELIGIBLE_PROVIDER, ISSUE_TRANSLATE_IDENTITY_STREAK_ABORT, ISSUE_TRANSLATE_IDENTITY_STREAK_WARNING, ISSUE_TRANSLATE_MISSING_CREDENTIALS, ISSUE_TRANSLATE_PROVIDER_NOT_IMPLEMENTED_YET, ISSUE_TRANSLATE_UNKNOWN_TRANSLATION_PROVIDER, ISSUE_VALIDATE_DYNAMIC_KEY_SITES, ISSUE_VALIDATE_MISSING_LITERAL_KEYS, ISSUE_VALIDATE_SOURCE_LOCALE_READ_FAILED, LICENSE_URL, LIST_MORE_HINT, LIST_WINDOW_DEFAULT_TOP, LIST_WINDOW_HARD_CAP, MAX_ANALYSIS_BYTES, MAX_MISSING_TARGET_SUGGESTIONS, MAX_PROJECTS_INDEX_BYTES, MAX_PROJECT_FILES_BYTES, MAX_TRANSLATIONS_CACHE_BYTES, META_WORKER_URL, NPM_PACKAGE_NAME, NPM_PACKAGE_URL, PROJECT_REPORT_KIND, PROJECT_REPORT_SCHEMA_VERSION, PROJECT_SHARE_PREPARED_MAX_BYTES, PROJECT_UPLOAD_MAX_FILES, PROJECT_UPLOAD_MAX_TEXT_BYTES, PROJECT_UPLOAD_MAX_ZIP_BYTES, PROJECT_UPLOAD_ZIP_LIMITS, REPORT_INLINE_PAYLOAD_PLACEHOLDER, REPORT_SHARE_MAX_BYTES, RESULT_API_VERSION, SDK_PACKAGE_NAME, SDK_VERSION, SHARE_BAK_DIRNAME, SHARE_CACHE_REASON_MESSAGES, SHARE_JSON_BASENAME, TRANSLATE_WORKERS_CAP, TRANSLATIONS_DIR, WORKER_IDLE_RETENTION_MS, WORKER_INGEST_FORCE_QUERY, applyListWindow, applyLocaleLeafMode, applyLocaleLeafNormalization, applyPreserveFromSource, buildCliJsonEnvelope, buildLanguageCatalog, buildLocaleJsonByTagFromArchive, buildSegmentTemplateFromSource, collectLocaleStructuralParityDiagnostics, collectSourceLocaleMissingSegmentDiagnostics, collectTranslationSurfaceLeaves, constants_exports as constants, createLocaleReadCache, deepClone, deleteAtPath, detectLocalePlaceholderLeaves, detectSourcePlaceholderLeaves, docsCommandUrl, emitIssuesAsRunErrors, emitRunErrorFromUnknown, emitRunEvent, emitRunMessage, enrichIssuesWithDocHrefs, errors_exports as errors, filterLanguageCatalog, formatListOmittedSuffix, formatListShownOmitted, formatSourcePlaceholderMessage, formatSyncSourcePlaceholderMessage, formatTargetPlaceholderMessage, generatedLanguageCatalog, getAtPath, getDocsUrl, getJsonParseLocation, getLanguageByCodeFromCatalog, getProjectedLeafString, getRunOptions, invalidateLocaleReadCacheForAbsolutePath, invalidateLocaleReadCacheForLocaleCode, isCompleteStructuredLocaleLeafMeta, isErrnoCode, isLocalesLayoutReadSupported, isLocalesLayoutWriteSupported, isProgressEvent, isStructuredLocaleLeafNode, issueCodeDocHref, issueCodeRepoDocPathForIssueCode, issueFromI18nPruneError, issuesFromSourcePlaceholderLeaves, issuesFromTargetPlaceholderLeaves, json_exports as json, catalog_exports as languagesCatalog, listLocaleCodes, listLocaleCodesFromArchive, listLocaleCodesFromContext, listLocaleSegmentTargets, listLocaleSegments, listLocaleSegmentsFromContext, listSourceLocaleWriteTargets, localeCodeForSegment, localeCodesFromContext, localeJsonFromTranslationSurfaceLeaves, localeJsonValueFromTranslation, leaves_exports as localeLeaves, localeSegmentRefFromAbsolute, localeSegmentSourceForFile, localeStructuralSlot, layout_exports as localesLayout, read_exports as localesRead, write_exports as localesWrite, mask, materializeGenerateWorkingBySegment, mergeToTemplateShape, metadataModeEnabledFromConfig, noopRunEmitter, normalizeRepoDocPath, normalizeUnknownError, nowMs, options_exports as options, pairedSourceSegmentRelativePath, parseJsonText, placeholders_exports as placeholders, primarySegmentForLocale, projectLocaleLeaves, projects_exports as projects, pruneToTemplateShape, readFlatLocaleJsonSurface, readLocaleBundle, readLocaleCodeSurfaceFromContext, readLocaleJsonFromContextSync, readLocaleJsonOrEmpty, readLocaleLeavesForCode, readLocalePerDirLocaleSurface, readLocaleSegmentFromContext, readSourceLocaleLeaves, paths_exports as reference, resetRunOptions, resolveGlobalSyncSchemaPaths, resolveIssueCodeDocLink, resolveListWindow, resolveLocaleLeafMode, resolveLocaleSegmentAbsolutePath, resolveLocaleSegmentTargets, resolveLocalesLayout, resolveLocalesLayoutFromContext, resolvePairedSourceSegmentAbsolutePath, resolvePrimaryTargetWritePath, resolveSyncSegmentSourcePlan, resolveTargetLocaleWritePlan, restore, result_exports as result, rethrowAsI18n, run_exports as run, scanSources, scanner_exports as scanner, segmentsForLocaleCode, setAtPath, setRunOptions, sourceLocaleCodeForLayout, sourceLocaleCodeFromContext, sourcePlaceholderValues, sourcePlaceholders_exports as sourcePlaceholders, sourceSegmentRelativePathForKey, splitPath, stringifyCliCommandJson, stringifyEnvelope, suggestCatalogCodesForInvalidInputFromCatalog, swapLocaleInSegmentRelativePath, targetLocaleCodesFromContext, targetLocaleCoversAllSourcePaths, targetSegmentRelativePathForKey, translateLeaf, translationSurfacePathValueMap, translator_exports as translator, tryParseJsonText, validateLeafTranslationString, validateRestored, walkLocaleJsonSegments, writeFlatLocaleJsonDocument, writeLocaleBundle, writeLocaleJsonFromContextSync };
|