@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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +165 -0
  3. package/dist/adapters-gp1lXp0T.d.ts +12 -0
  4. package/dist/capabilities-x74cD2Hu.d.ts +48 -0
  5. package/dist/cleanup.d.ts +64 -0
  6. package/dist/cleanup.js +3999 -0
  7. package/dist/config.d.ts +201 -0
  8. package/dist/config.js +2865 -0
  9. package/dist/coreContext-DMaWLvmB.d.ts +388 -0
  10. package/dist/fs-BUYD8ZhA.d.ts +20 -0
  11. package/dist/generate.d.ts +487 -0
  12. package/dist/generate.js +9389 -0
  13. package/dist/humanEmit-ygNlYX-S.d.ts +79 -0
  14. package/dist/index-BQuLEQ9b.d.ts +7 -0
  15. package/dist/index-B_ow_Xvr.d.ts +97 -0
  16. package/dist/index-BgG01AKL.d.ts +287 -0
  17. package/dist/index-CIzZl4W8.d.ts +124 -0
  18. package/dist/index-Csm1w7XD.d.ts +58 -0
  19. package/dist/index-DLwTogCo.d.ts +43 -0
  20. package/dist/index-DVT26v11.d.ts +61 -0
  21. package/dist/index-DdjljwMj.d.ts +39 -0
  22. package/dist/index-DeIw-cZd.d.ts +52 -0
  23. package/dist/index-X50E1FIX.d.ts +50 -0
  24. package/dist/index.d.ts +9180 -0
  25. package/dist/index.js +21888 -0
  26. package/dist/init.d.ts +86 -0
  27. package/dist/init.js +848 -0
  28. package/dist/listWindow-XEFxQZi1.d.ts +30 -0
  29. package/dist/localeTargetCodes-BBIQjauw.d.ts +11 -0
  30. package/dist/locales.d.ts +39 -0
  31. package/dist/locales.js +2288 -0
  32. package/dist/missing-BVCvgUC8.d.ts +10 -0
  33. package/dist/missing.d.ts +85 -0
  34. package/dist/missing.js +5892 -0
  35. package/dist/modeResolve-cGVaY5Hh.d.ts +25 -0
  36. package/dist/path-Bfn3SAts.d.ts +11 -0
  37. package/dist/profile-BwOP9WKh.d.ts +9 -0
  38. package/dist/providers-0uMEfT6q.d.ts +82 -0
  39. package/dist/prune-c6hKZCv_.d.ts +33 -0
  40. package/dist/quality.d.ts +36 -0
  41. package/dist/quality.js +3868 -0
  42. package/dist/report-D5-6bVFj.d.ts +8 -0
  43. package/dist/report-schema.d.ts +102 -0
  44. package/dist/report-schema.js +42 -0
  45. package/dist/resumeCandidates-xR13eEwt.d.ts +200 -0
  46. package/dist/root-2-kCaBvQ.d.ts +1110 -0
  47. package/dist/runtime/edge.d.ts +21 -0
  48. package/dist/runtime/edge.js +87 -0
  49. package/dist/runtime/helpers/sync.d.ts +16 -0
  50. package/dist/runtime/helpers/sync.js +117 -0
  51. package/dist/runtime/node.d.ts +24 -0
  52. package/dist/runtime/node.js +204 -0
  53. package/dist/runtime/web.d.ts +21 -0
  54. package/dist/runtime/web.js +84 -0
  55. package/dist/shared.d.ts +1177 -0
  56. package/dist/shared.js +4897 -0
  57. package/dist/sourceContext-1LQg3HiQ.d.ts +36 -0
  58. package/dist/sourceSurface-mDtwGo1E.d.ts +122 -0
  59. package/dist/sync.d.ts +86 -0
  60. package/dist/sync.js +4971 -0
  61. package/dist/syncSegment-Bx6He2Mu.d.ts +149 -0
  62. package/dist/targets-EmtKyr6F.d.ts +23 -0
  63. package/dist/template-CGM-_WLT.d.ts +139 -0
  64. package/dist/translate-CIHYp7wi.d.ts +77 -0
  65. package/dist/types/shared.d.ts +21 -0
  66. package/dist/types/shared.js +1 -0
  67. package/dist/types.d.ts +1345 -0
  68. package/dist/types.js +1 -0
  69. package/dist/validate.d.ts +126 -0
  70. package/dist/validate.js +3717 -0
  71. package/package.json +128 -0
@@ -0,0 +1,2288 @@
1
+ // src/shared/errors/internal.ts
2
+ var I18nPruneError = class extends Error {
3
+ code;
4
+ issueCode;
5
+ constructor(message, code, options) {
6
+ super(message, options?.cause !== void 0 ? { cause: options.cause } : void 0);
7
+ this.name = "I18nPruneError";
8
+ this.code = code;
9
+ this.issueCode = options?.issueCode;
10
+ }
11
+ };
12
+
13
+ // src/shared/languages/normalize.ts
14
+ function normalizeLanguageCode(code) {
15
+ return code.trim().toLowerCase().replace(/_/g, "-");
16
+ }
17
+
18
+ // src/locales/source.ts
19
+ function getSourceLocaleSlug(path, sourceLocalePath) {
20
+ return normalizeLanguageCode(path.basename(sourceLocalePath, ".json"));
21
+ }
22
+ function getDisplaySourceLocaleCode(ctx) {
23
+ return getSourceLocaleSlug(ctx.path, ctx.paths.sourceLocale);
24
+ }
25
+ function buildSourceLocaleTruthLabel(displaySlug) {
26
+ return `(${displaySlug} - source of truth)`;
27
+ }
28
+ function isSourceLocaleSlug(path, candidate, sourceLocalePath) {
29
+ return normalizeLanguageCode(candidate) === getSourceLocaleSlug(path, sourceLocalePath);
30
+ }
31
+ function excludeSourceLocaleSlugs(path, slugs, sourceLocalePath) {
32
+ const n = getSourceLocaleSlug(path, sourceLocalePath);
33
+ return slugs.filter((s) => normalizeLanguageCode(s) !== n);
34
+ }
35
+ function assertNotSourceTargetLocale(command, lang, sourceLocalePath, ctx) {
36
+ if (!isSourceLocaleSlug(ctx.path, lang, sourceLocalePath)) return;
37
+ const display = getDisplaySourceLocaleCode(ctx);
38
+ throw new I18nPruneError(
39
+ `${command} does not apply to the source locale ${buildSourceLocaleTruthLabel(display)}. Pass a target language code.`,
40
+ "USAGE"
41
+ );
42
+ }
43
+
44
+ // src/runtime/helpers/sync/assert.ts
45
+ function isThenable(value) {
46
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
47
+ }
48
+ function assertSyncPortResult(value, label, at) {
49
+ if (isThenable(value)) {
50
+ throw new I18nPruneError(
51
+ `Synchronous ${label} requires a plain value (got a Promise at ${at})`,
52
+ "USAGE"
53
+ );
54
+ }
55
+ return value;
56
+ }
57
+
58
+ // src/runtime/helpers/sync/fs.ts
59
+ function readRuntimeFsTextSync(filePath, fs) {
60
+ return assertSyncPortResult(fs.readText(filePath), "fs.readText", filePath);
61
+ }
62
+ function existsRuntimeFsSync(filePath, fs) {
63
+ return assertSyncPortResult(fs.exists(filePath), "fs.exists", filePath);
64
+ }
65
+ function listRuntimeFsDirSync(dirPath, fs) {
66
+ return assertSyncPortResult(fs.listDir(dirPath), "fs.listDir", dirPath);
67
+ }
68
+
69
+ // src/shared/constants/issueCodes.ts
70
+ var ISSUE_LANGUAGES_UNSUPPORTED_LANGUAGE_CODE = "i18nprune.languages.unsupported_language_code";
71
+ var ISSUE_IO_READ_FAILED = "i18nprune.io.read_failed";
72
+
73
+ // src/shared/json/parse.ts
74
+ var I18nPruneJsonParseError = class extends I18nPruneError {
75
+ filePath;
76
+ line;
77
+ column;
78
+ offset;
79
+ constructor(input) {
80
+ const options = input.issueCode !== void 0 ? { cause: input.cause, issueCode: input.issueCode } : { cause: input.cause };
81
+ super(input.message, input.code, options);
82
+ this.name = "I18nPruneJsonParseError";
83
+ this.filePath = input.filePath;
84
+ this.line = input.location.line;
85
+ this.column = input.location.column;
86
+ this.offset = input.location.offset;
87
+ }
88
+ };
89
+ function locationFromOffset(text, offset) {
90
+ let line = 1;
91
+ let column = 1;
92
+ const capped = Math.max(0, Math.min(offset, text.length));
93
+ for (let i = 0; i < capped; i += 1) {
94
+ if (text.charCodeAt(i) === 10) {
95
+ line += 1;
96
+ column = 1;
97
+ } else {
98
+ column += 1;
99
+ }
100
+ }
101
+ return { line, column, offset };
102
+ }
103
+ function getJsonParseLocation(error, text) {
104
+ const message = error instanceof Error ? error.message : String(error);
105
+ const positionMatch = /\bposition\s+(\d+)\b/i.exec(message);
106
+ if (positionMatch?.[1]) {
107
+ return locationFromOffset(text, Number.parseInt(positionMatch[1], 10));
108
+ }
109
+ const lineColumnMatch = /\bline\s+(\d+)\s+column\s+(\d+)\b/i.exec(message);
110
+ if (lineColumnMatch?.[1] && lineColumnMatch[2]) {
111
+ return {
112
+ line: Number.parseInt(lineColumnMatch[1], 10),
113
+ column: Number.parseInt(lineColumnMatch[2], 10)
114
+ };
115
+ }
116
+ return {};
117
+ }
118
+ function formatJsonParseMessage(filePath, location, cause) {
119
+ const subject = filePath ? `Invalid JSON in ${filePath}` : "Invalid JSON";
120
+ 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)}` : "";
121
+ const detail = cause instanceof Error ? cause.message : String(cause);
122
+ return `${subject}${at}: ${detail}`;
123
+ }
124
+ function parseJsonText(text, options = {}) {
125
+ try {
126
+ return JSON.parse(text);
127
+ } catch (cause) {
128
+ const location = getJsonParseLocation(cause, text);
129
+ throw new I18nPruneJsonParseError({
130
+ message: formatJsonParseMessage(options.filePath, location, cause),
131
+ code: options.code ?? "IO",
132
+ cause,
133
+ location,
134
+ ...options.issueCode !== void 0 ? { issueCode: options.issueCode } : {},
135
+ ...options.filePath !== void 0 ? { filePath: options.filePath } : {}
136
+ });
137
+ }
138
+ }
139
+
140
+ // src/locales/otherLocales.ts
141
+ function listOtherLocaleCodes(runtime, localesDir, sourceBase) {
142
+ const { fs, path } = runtime;
143
+ if (!existsRuntimeFsSync(localesDir, fs)) return [];
144
+ return listRuntimeFsDirSync(localesDir, fs).filter((e) => e.kind === "file" && e.name.endsWith(".json")).map((e) => path.basename(e.name, ".json")).filter((c) => c !== sourceBase);
145
+ }
146
+
147
+ // src/shared/locales/layout/requireStructure.ts
148
+ function localesMode(config) {
149
+ return config.mode ?? "flat_file";
150
+ }
151
+ function resolveLocalesStructure(config) {
152
+ if (config.structure !== void 0) {
153
+ return config.structure;
154
+ }
155
+ if (localesMode(config) === "flat_file") {
156
+ return "locale_file";
157
+ }
158
+ throw new Error("locales.structure is required when locales.mode is locale_directory");
159
+ }
160
+
161
+ // src/shared/locales/layout/resolveLayout.ts
162
+ function resolveLocalesLayout(config, directoryAbsolute) {
163
+ const mode = localesMode(config);
164
+ const structure = resolveLocalesStructure(config);
165
+ return { mode, structure, directoryAbsolute, config };
166
+ }
167
+ function resolveLocalesLayoutFromContext(ctx) {
168
+ return resolveLocalesLayout(ctx.config.locales, ctx.paths.localesDir);
169
+ }
170
+ function isLocalesLayoutReadSupported(layout) {
171
+ return layout.mode === "flat_file" && layout.structure === "locale_file" || layout.mode === "locale_directory" && (layout.structure === "locale_per_dir" || layout.structure === "feature_bundle");
172
+ }
173
+
174
+ // src/shared/locales/enumerate/parseSegmentLocale.ts
175
+ function localeCodeForSegment(structure, path, segment) {
176
+ if (structure === "locale_file") {
177
+ if (segment.relativePath.includes("/")) return null;
178
+ return path.basename(segment.absolutePath, ".json");
179
+ }
180
+ if (structure === "locale_per_dir") {
181
+ const slash = segment.relativePath.indexOf("/");
182
+ if (slash < 0) return null;
183
+ const locale = segment.relativePath.slice(0, slash);
184
+ return locale.length > 0 ? locale : null;
185
+ }
186
+ if (structure === "feature_bundle") {
187
+ return path.basename(segment.absolutePath, ".json");
188
+ }
189
+ return null;
190
+ }
191
+
192
+ // src/shared/locales/leaves/segmentSource/localeSegmentSourceForFile.ts
193
+ function localeSegmentSourceForFile(input) {
194
+ const { path, absoluteFile, localesDir, structure } = input;
195
+ let relativePath = path.relative(localesDir, absoluteFile);
196
+ if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
197
+ relativePath = path.basename(absoluteFile);
198
+ }
199
+ relativePath = relativePath.replace(/\\/g, "/");
200
+ const locale = localeCodeForSegment(structure, path, { absolutePath: absoluteFile, relativePath });
201
+ if (locale === null) return null;
202
+ return { file: absoluteFile, locale, relativePath };
203
+ }
204
+
205
+ // src/shared/locales/leaves/walk/translationSurfaceWalk.ts
206
+ function isPlainObject(x) {
207
+ return typeof x === "object" && x !== null && !Array.isArray(x);
208
+ }
209
+ function isStructuredLocaleLeafNode(x) {
210
+ return isPlainObject(x) && typeof x.value === "string";
211
+ }
212
+ function readOptionalStatus(o) {
213
+ const s = o.status;
214
+ if (typeof s !== "string" || !s.trim()) return void 0;
215
+ return s;
216
+ }
217
+ function readOptionalLeafSource(o) {
218
+ const s = o.source;
219
+ if (typeof s !== "string" || !s.trim()) return void 0;
220
+ return s;
221
+ }
222
+ function readConfidence(o) {
223
+ const c = o.confidence;
224
+ if (c === null || c === void 0) return null;
225
+ if (typeof c !== "number" || !Number.isFinite(c)) return null;
226
+ const clamped = Math.max(0, Math.min(1, c));
227
+ return Math.round(clamped * 100) / 100;
228
+ }
229
+ function readNeedsReview(o) {
230
+ if (!("needsReview" in o)) return null;
231
+ return typeof o.needsReview === "boolean" ? o.needsReview : null;
232
+ }
233
+ function readNeedsTranslationAgain(o) {
234
+ if (!("needsTranslationAgain" in o)) return null;
235
+ return typeof o.needsTranslationAgain === "boolean" ? o.needsTranslationAgain : null;
236
+ }
237
+ function isCompleteStructuredLocaleLeafMeta(node) {
238
+ if (!isStructuredLocaleLeafNode(node)) return false;
239
+ const o = node;
240
+ if (typeof o.status !== "string" || !o.status.trim()) return false;
241
+ if (!(o.confidence === null || typeof o.confidence === "number" && Number.isFinite(o.confidence))) return false;
242
+ if (typeof o.needsReview !== "boolean") return false;
243
+ if (typeof o.needsTranslationAgain !== "boolean") return false;
244
+ if (typeof o.source !== "string" || !o.source.trim()) return false;
245
+ return true;
246
+ }
247
+ function pushStructuredRow(out, prefix, root, fileOrigin) {
248
+ out.push({
249
+ path: prefix,
250
+ value: root.value,
251
+ shape: "structured",
252
+ status: readOptionalStatus(root),
253
+ confidence: readConfidence(root),
254
+ needsReview: readNeedsReview(root),
255
+ needsTranslationAgain: readNeedsTranslationAgain(root),
256
+ source: readOptionalLeafSource(root),
257
+ structuredMetaComplete: isCompleteStructuredLocaleLeafMeta(root),
258
+ ...fileOrigin ? { fileOrigin } : {}
259
+ });
260
+ }
261
+ function collectTranslationSurfaceLeaves(root, prefix = "", out = [], fileOrigin) {
262
+ if (typeof root === "string") {
263
+ if (prefix) {
264
+ out.push({
265
+ path: prefix,
266
+ value: root,
267
+ shape: "legacy_string",
268
+ confidence: null,
269
+ needsReview: null,
270
+ ...fileOrigin ? { fileOrigin } : {}
271
+ });
272
+ }
273
+ return out;
274
+ }
275
+ if (isStructuredLocaleLeafNode(root)) {
276
+ if (prefix) pushStructuredRow(out, prefix, root, fileOrigin);
277
+ return out;
278
+ }
279
+ if (Array.isArray(root)) {
280
+ root.forEach((item, i) => {
281
+ const p = prefix ? `${prefix}[${i}]` : `[${i}]`;
282
+ collectTranslationSurfaceLeaves(item, p, out, fileOrigin);
283
+ });
284
+ return out;
285
+ }
286
+ if (isPlainObject(root)) {
287
+ for (const k of Object.keys(root)) {
288
+ const p = prefix ? `${prefix}.${k}` : k;
289
+ collectTranslationSurfaceLeaves(root[k], p, out, fileOrigin);
290
+ }
291
+ }
292
+ return out;
293
+ }
294
+
295
+ // src/shared/locales/read/flatFileSurface.ts
296
+ function readFlatLocaleJsonSurface(input) {
297
+ const diagnostics = [];
298
+ const emit = (d) => {
299
+ diagnostics.push(d);
300
+ };
301
+ try {
302
+ const text = readRuntimeFsTextSync(input.absoluteFile, input.fs);
303
+ let json;
304
+ try {
305
+ json = parseJsonText(text, {
306
+ filePath: input.absoluteFile,
307
+ code: "IO",
308
+ issueCode: ISSUE_IO_READ_FAILED
309
+ });
310
+ } catch (e) {
311
+ const message = e instanceof Error ? e.message : String(e);
312
+ emit({ level: "error", code: "locale_json_parse_failed", message, path: input.absoluteFile });
313
+ return { ok: false, leaves: [], diagnostics };
314
+ }
315
+ const fileOrigin = localeSegmentSourceForFile({
316
+ path: input.path,
317
+ absoluteFile: input.absoluteFile,
318
+ localesDir: input.localesDir,
319
+ structure: input.structure
320
+ });
321
+ const leaves = collectTranslationSurfaceLeaves(json, "", [], fileOrigin ?? void 0);
322
+ return { ok: true, document: json, leaves, text, diagnostics };
323
+ } catch (e) {
324
+ const message = e instanceof Error ? e.message : String(e);
325
+ emit({ level: "error", code: "locale_fs_read_failed", message, path: input.absoluteFile });
326
+ return { ok: false, leaves: [], diagnostics };
327
+ }
328
+ }
329
+
330
+ // src/shared/path/posix.ts
331
+ function toPosixPath(value) {
332
+ return value.replace(/\\/g, "/");
333
+ }
334
+
335
+ // src/shared/locales/enumerate/resolveSegmentPath.ts
336
+ function localeSegmentRefFromAbsolute(input) {
337
+ const { layout, path, absolutePath } = input;
338
+ let relativePath = path.relative(layout.directoryAbsolute, absolutePath);
339
+ if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
340
+ return null;
341
+ }
342
+ relativePath = relativePath.replace(/\\/g, "/");
343
+ if (!relativePath.endsWith(".json")) {
344
+ return null;
345
+ }
346
+ const locale = localeCodeForSegment(layout.structure, path, { absolutePath, relativePath });
347
+ if (locale === null) return null;
348
+ return { locale, relativePath, absolutePath: toPosixPath(absolutePath) };
349
+ }
350
+
351
+ // src/shared/locales/read/bundle.ts
352
+ function readLocaleBundle(input) {
353
+ const diagnostics = [];
354
+ const emit = (d) => {
355
+ diagnostics.push(d);
356
+ };
357
+ if (!isLocalesLayoutReadSupported(input.layout)) {
358
+ emit({
359
+ level: "error",
360
+ code: "locale_layout_unsupported",
361
+ message: `locale read is not implemented for mode=${input.layout.mode} structure=${input.layout.structure}`,
362
+ path: input.absoluteFile
363
+ });
364
+ return { ok: false, leaves: [], diagnostics };
365
+ }
366
+ const segmentRef = localeSegmentRefFromAbsolute({
367
+ layout: input.layout,
368
+ path: input.path,
369
+ absolutePath: input.absoluteFile
370
+ });
371
+ if (segmentRef === null) {
372
+ emit({
373
+ level: "warn",
374
+ code: "locale_read_path_layout_mismatch",
375
+ message: `path does not match configured layout mode=${input.layout.mode} structure=${input.layout.structure}`,
376
+ path: input.absoluteFile
377
+ });
378
+ return { ok: false, leaves: [], diagnostics };
379
+ }
380
+ return readFlatLocaleJsonSurface({
381
+ fs: input.fs,
382
+ path: input.path,
383
+ absoluteFile: input.absoluteFile,
384
+ localesDir: input.layout.directoryAbsolute,
385
+ structure: input.layout.structure,
386
+ onDiagnostic: input.onDiagnostic
387
+ });
388
+ }
389
+
390
+ // src/shared/locales/diagnostics/structuralParity.ts
391
+ function localeStructuralSlot(structure, relativePath) {
392
+ if (structure === "locale_per_dir") {
393
+ const slash = relativePath.indexOf("/");
394
+ if (slash < 0) return null;
395
+ const slot = relativePath.slice(slash + 1);
396
+ return slot.length > 0 ? slot : null;
397
+ }
398
+ if (structure === "feature_bundle") {
399
+ const slash = relativePath.lastIndexOf("/");
400
+ if (slash < 0) return null;
401
+ const slot = relativePath.slice(0, slash);
402
+ return slot.length > 0 ? slot : null;
403
+ }
404
+ return null;
405
+ }
406
+ function slotsByLocale(structure, segments) {
407
+ const byLocale = /* @__PURE__ */ new Map();
408
+ for (const segment of segments) {
409
+ const slot = localeStructuralSlot(structure, segment.relativePath);
410
+ if (slot === null) continue;
411
+ let set = byLocale.get(segment.locale);
412
+ if (!set) {
413
+ set = /* @__PURE__ */ new Set();
414
+ byLocale.set(segment.locale, set);
415
+ }
416
+ set.add(slot);
417
+ }
418
+ return byLocale;
419
+ }
420
+ function pickReferenceLocale(byLocale, preferred) {
421
+ if (preferred !== void 0 && byLocale.has(preferred)) return preferred;
422
+ let best = null;
423
+ let bestSize = -1;
424
+ for (const [locale, slots] of byLocale) {
425
+ if (slots.size > bestSize) {
426
+ best = locale;
427
+ bestSize = slots.size;
428
+ }
429
+ }
430
+ return best;
431
+ }
432
+ function collectLocaleStructuralParityDiagnostics(input) {
433
+ const { structure, segments } = input;
434
+ if (structure !== "locale_per_dir" && structure !== "feature_bundle") {
435
+ return [];
436
+ }
437
+ const byLocale = slotsByLocale(structure, segments);
438
+ if (byLocale.size < 2) return [];
439
+ const reference = pickReferenceLocale(byLocale, input.referenceLocale);
440
+ if (reference === null) return [];
441
+ const referenceSlots = byLocale.get(reference);
442
+ if (!referenceSlots || referenceSlots.size === 0) return [];
443
+ const diagnostics = [];
444
+ for (const [locale, slots] of byLocale) {
445
+ if (locale === reference) continue;
446
+ for (const slot of referenceSlots) {
447
+ if (!slots.has(slot)) {
448
+ diagnostics.push({
449
+ level: "warn",
450
+ code: "locale_structure_slot_missing",
451
+ message: `locale ${locale} is missing segment slot ${slot} (present for reference locale ${reference})`
452
+ });
453
+ }
454
+ }
455
+ for (const slot of slots) {
456
+ if (!referenceSlots.has(slot)) {
457
+ diagnostics.push({
458
+ level: "warn",
459
+ code: "locale_structure_slot_extra",
460
+ message: `locale ${locale} has extra segment slot ${slot} (not present for reference locale ${reference})`
461
+ });
462
+ }
463
+ }
464
+ }
465
+ diagnostics.sort((a, b) => a.message.localeCompare(b.message));
466
+ return diagnostics;
467
+ }
468
+
469
+ // src/shared/constants/locales.ts
470
+ var MAX_LOCALE_SEGMENT_TREE_DEPTH = 16;
471
+
472
+ // src/shared/locales/enumerate/walkJsonTree.ts
473
+ function posixRelative(pathApi, root, absolute) {
474
+ let rel = pathApi.relative(root, absolute);
475
+ if (rel.startsWith("..") || pathApi.isAbsolute(rel)) {
476
+ rel = pathApi.basename(absolute);
477
+ }
478
+ return rel.replace(/\\/g, "/");
479
+ }
480
+ function walkLocaleJsonSegments(input) {
481
+ const { fs, path, rootAbsolute, recursive } = input;
482
+ const maxDepth = input.maxDepth ?? MAX_LOCALE_SEGMENT_TREE_DEPTH;
483
+ const out = [];
484
+ function visit(dirAbsolute, depth) {
485
+ if (!existsRuntimeFsSync(dirAbsolute, fs)) return;
486
+ const entries = listRuntimeFsDirSync(dirAbsolute, fs);
487
+ for (const entry of entries) {
488
+ const childAbsolute = path.join(dirAbsolute, entry.name);
489
+ if (entry.kind === "file" && entry.name.endsWith(".json")) {
490
+ out.push({
491
+ absolutePath: childAbsolute,
492
+ relativePath: posixRelative(path, rootAbsolute, childAbsolute)
493
+ });
494
+ } else if (recursive && entry.kind === "directory" && depth < maxDepth) {
495
+ visit(childAbsolute, depth + 1);
496
+ }
497
+ }
498
+ }
499
+ visit(rootAbsolute, 0);
500
+ return out;
501
+ }
502
+
503
+ // src/shared/locales/enumerate/listLocaleSegments.ts
504
+ function listLocaleSegments(input) {
505
+ const diagnostics = [];
506
+ const { layout, fs, path } = input;
507
+ const recursive = layout.structure !== "locale_file";
508
+ const walked = walkLocaleJsonSegments({
509
+ fs,
510
+ path,
511
+ rootAbsolute: layout.directoryAbsolute,
512
+ recursive
513
+ });
514
+ const segments = [];
515
+ for (const segment of walked) {
516
+ const locale = localeCodeForSegment(layout.structure, path, segment);
517
+ if (locale === null) continue;
518
+ segments.push({
519
+ locale,
520
+ relativePath: segment.relativePath,
521
+ absolutePath: segment.absolutePath
522
+ });
523
+ }
524
+ segments.sort((a, b) => {
525
+ const byLocale = a.locale.localeCompare(b.locale);
526
+ if (byLocale !== 0) return byLocale;
527
+ return a.relativePath.localeCompare(b.relativePath);
528
+ });
529
+ diagnostics.push(
530
+ ...collectLocaleStructuralParityDiagnostics({
531
+ structure: layout.structure,
532
+ segments
533
+ })
534
+ );
535
+ return { segments, diagnostics };
536
+ }
537
+
538
+ // src/shared/locales/enumerate/listLocaleCodes.ts
539
+ function listLocaleCodes(input) {
540
+ const { segments, diagnostics } = listLocaleSegments(input);
541
+ const codes = [...new Set(segments.map((s) => s.locale))].sort((a, b) => a.localeCompare(b));
542
+ return { codes, diagnostics };
543
+ }
544
+
545
+ // src/shared/locales/enumerate/fromContext.ts
546
+ function listLocaleSegmentsFromContext(ctx) {
547
+ return listLocaleSegments({
548
+ layout: resolveLocalesLayoutFromContext(ctx),
549
+ fs: ctx.adapters.fs,
550
+ path: ctx.adapters.path
551
+ });
552
+ }
553
+ function listLocaleCodesFromContext(ctx) {
554
+ return listLocaleCodes({
555
+ layout: resolveLocalesLayoutFromContext(ctx),
556
+ fs: ctx.adapters.fs,
557
+ path: ctx.adapters.path
558
+ });
559
+ }
560
+
561
+ // src/shared/locales/targets/context.ts
562
+ function normalizeCode(code) {
563
+ return normalizeLanguageCode(code);
564
+ }
565
+ function listLocaleSegmentTargets(ctx) {
566
+ const { segments } = listLocaleSegmentsFromContext(ctx);
567
+ return segments.map((segment) => ({
568
+ ...segment,
569
+ reportKey: segment.relativePath
570
+ }));
571
+ }
572
+ function sourceLocaleCodeFromContext(ctx) {
573
+ const layout = resolveLocalesLayoutFromContext(ctx);
574
+ const ref = localeSegmentRefFromAbsolute({
575
+ layout,
576
+ path: ctx.adapters.path,
577
+ absolutePath: ctx.paths.sourceLocale
578
+ });
579
+ if (ref !== null) {
580
+ return normalizeCode(ref.locale);
581
+ }
582
+ return normalizeCode(ctx.adapters.path.basename(ctx.paths.sourceLocale, ".json"));
583
+ }
584
+ function localeCodesFromContext(ctx) {
585
+ return listLocaleCodesFromContext(ctx).codes.map((c) => normalizeCode(c));
586
+ }
587
+ function targetLocaleCodesFromContext(ctx) {
588
+ const source = sourceLocaleCodeFromContext(ctx);
589
+ return localeCodesFromContext(ctx).filter((c) => c !== source);
590
+ }
591
+ function segmentsForLocaleCode(ctx, localeCode) {
592
+ const want = normalizeCode(localeCode);
593
+ return listLocaleSegmentTargets(ctx).filter((s) => normalizeCode(s.locale) === want);
594
+ }
595
+ function primarySegmentForLocale(ctx, localeCode) {
596
+ const segments = segmentsForLocaleCode(ctx, localeCode);
597
+ if (segments.length === 0) return void 0;
598
+ const sourceResolved = ctx.adapters.path.resolve(ctx.paths.sourceLocale);
599
+ const sourceMatch = segments.find((s) => ctx.adapters.path.resolve(s.absolutePath) === sourceResolved);
600
+ if (sourceMatch) return sourceMatch;
601
+ return segments.slice().sort((a, b) => a.relativePath.localeCompare(b.relativePath))[0];
602
+ }
603
+
604
+ // src/shared/locales/read/cache.ts
605
+ function dropLocaleCodeReadCache(ctx, localeCode) {
606
+ ctx.localeRead.localeCodes.delete(normalizeLanguageCode(localeCode));
607
+ }
608
+
609
+ // src/shared/locales/read/fromContext.ts
610
+ function storeSegmentSnapshot(ctx, absoluteFile, snapshot) {
611
+ ctx.localeRead.segments.set(absoluteFile, snapshot);
612
+ if (snapshot.ok) {
613
+ const layout = resolveLocalesLayoutFromContext(ctx);
614
+ const ref = localeSegmentRefFromAbsolute({
615
+ layout,
616
+ path: ctx.adapters.path,
617
+ absolutePath: absoluteFile
618
+ });
619
+ if (ref !== null) {
620
+ dropLocaleCodeReadCache(ctx, ref.locale);
621
+ }
622
+ }
623
+ }
624
+ function segmentSnapshotToResult(snapshot) {
625
+ if (snapshot.ok) {
626
+ return {
627
+ ok: true,
628
+ document: snapshot.document,
629
+ leaves: snapshot.leaves,
630
+ text: snapshot.text,
631
+ diagnostics: []
632
+ };
633
+ }
634
+ return { ok: false, leaves: [], diagnostics: snapshot.diagnostics };
635
+ }
636
+ function readLocaleSegmentFromContext(ctx, absoluteFile, onDiagnostic) {
637
+ const cached = ctx.localeRead.segments.get(absoluteFile);
638
+ if (cached !== void 0) {
639
+ return segmentSnapshotToResult(cached);
640
+ }
641
+ const result = readLocaleBundle({
642
+ layout: resolveLocalesLayoutFromContext(ctx),
643
+ fs: ctx.adapters.fs,
644
+ path: ctx.adapters.path,
645
+ absoluteFile,
646
+ onDiagnostic
647
+ });
648
+ if (result.ok) {
649
+ storeSegmentSnapshot(ctx, absoluteFile, {
650
+ ok: true,
651
+ absolutePath: absoluteFile,
652
+ document: result.document,
653
+ leaves: result.leaves,
654
+ text: result.text
655
+ });
656
+ } else {
657
+ storeSegmentSnapshot(ctx, absoluteFile, {
658
+ ok: false,
659
+ absolutePath: absoluteFile,
660
+ diagnostics: result.diagnostics
661
+ });
662
+ }
663
+ return result;
664
+ }
665
+
666
+ // src/shared/projects/localeSurfaceMap.ts
667
+ function translationSurfacePathValueMapFromLeaves(leaves) {
668
+ return new Map(leaves.map((row) => [row.path, row.value]));
669
+ }
670
+
671
+ // src/locales/summary.ts
672
+ function toLeafMap(ctx, absoluteFile) {
673
+ if (!isLocalesLayoutReadSupported(resolveLocalesLayoutFromContext(ctx))) {
674
+ return /* @__PURE__ */ new Map();
675
+ }
676
+ const read = readLocaleSegmentFromContext(ctx, absoluteFile);
677
+ if (!read.ok) return /* @__PURE__ */ new Map();
678
+ return translationSurfacePathValueMapFromLeaves(read.leaves);
679
+ }
680
+ function buildLocaleListRows(ctx, localeCodes) {
681
+ const { sourceLocale } = ctx.paths;
682
+ const pathApi = ctx.adapters.path;
683
+ const sourceMap = toLeafMap(ctx, sourceLocale);
684
+ const sourceCode = sourceLocaleCodeFromContext(ctx);
685
+ return localeCodes.slice().sort((a, b) => a.localeCompare(b)).map((code) => {
686
+ const normalized = normalizeLanguageCode(code);
687
+ const segments = segmentsForLocaleCode(ctx, normalized);
688
+ const primary = primarySegmentForLocale(ctx, normalized);
689
+ const localePath = toPosixPath(
690
+ primary?.absolutePath ?? pathApi.join(ctx.paths.localesDir, `${normalized}.json`)
691
+ );
692
+ const isSourceLocale = normalized === sourceCode;
693
+ const leafMaps = segments.map((s) => toLeafMap(ctx, s.absolutePath));
694
+ const leafCount = leafMaps.reduce((sum, m) => sum + m.size, 0);
695
+ let englishIdenticalLeafCount = null;
696
+ if (!isSourceLocale) {
697
+ let identical = 0;
698
+ for (const localeMap of leafMaps) {
699
+ for (const [leafPath, value] of localeMap) {
700
+ if (sourceMap.get(leafPath) === value) identical += 1;
701
+ }
702
+ }
703
+ englishIdenticalLeafCount = identical;
704
+ }
705
+ const segmentRelativePaths = segments.map((s) => s.relativePath).sort((a, b) => a.localeCompare(b));
706
+ return {
707
+ code: normalized,
708
+ localePath,
709
+ segmentCount: segments.length,
710
+ segmentRelativePaths,
711
+ leafCount,
712
+ englishIdenticalLeafCount,
713
+ isSourceLocale
714
+ };
715
+ });
716
+ }
717
+
718
+ // src/shared/languages/catalog/languages.json
719
+ var languages_default = [
720
+ {
721
+ code: "ab",
722
+ english: "Abkhazian",
723
+ native: "Abkhazian",
724
+ direction: "ltr"
725
+ },
726
+ {
727
+ code: "ace",
728
+ english: "Acehnese",
729
+ native: "Acehnese",
730
+ direction: "ltr"
731
+ },
732
+ {
733
+ code: "ach",
734
+ english: "Acoli",
735
+ native: "Acoli",
736
+ direction: "ltr"
737
+ },
738
+ {
739
+ code: "af",
740
+ english: "Afrikaans",
741
+ native: "Afrikaans",
742
+ direction: "ltr"
743
+ },
744
+ {
745
+ code: "ak",
746
+ english: "Akan",
747
+ native: "Akan",
748
+ direction: "ltr"
749
+ },
750
+ {
751
+ code: "alz",
752
+ english: "alz",
753
+ native: "alz",
754
+ direction: "ltr"
755
+ },
756
+ {
757
+ code: "am",
758
+ english: "Amharic",
759
+ native: "\u12A0\u121B\u122D\u129B",
760
+ direction: "ltr"
761
+ },
762
+ {
763
+ code: "ar",
764
+ english: "Arabic",
765
+ native: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629",
766
+ direction: "rtl"
767
+ },
768
+ {
769
+ code: "ar-sa",
770
+ english: "Arabic (Saudi Arabia)",
771
+ 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)",
772
+ direction: "rtl"
773
+ },
774
+ {
775
+ code: "as",
776
+ english: "Assamese",
777
+ native: "\u0985\u09B8\u09AE\u09C0\u09AF\u09BC\u09BE",
778
+ direction: "ltr"
779
+ },
780
+ {
781
+ code: "awa",
782
+ english: "Awadhi",
783
+ native: "Awadhi",
784
+ direction: "ltr"
785
+ },
786
+ {
787
+ code: "ay",
788
+ english: "Aymara",
789
+ native: "Aymara",
790
+ direction: "ltr"
791
+ },
792
+ {
793
+ code: "az",
794
+ english: "Azerbaijani",
795
+ native: "az\u0259rbaycan",
796
+ direction: "ltr"
797
+ },
798
+ {
799
+ code: "ba",
800
+ english: "Bashkir",
801
+ native: "Bashkir",
802
+ direction: "ltr"
803
+ },
804
+ {
805
+ code: "ban",
806
+ english: "Balinese",
807
+ native: "Balinese",
808
+ direction: "ltr"
809
+ },
810
+ {
811
+ code: "bbc",
812
+ english: "Batak Toba",
813
+ native: "Batak Toba",
814
+ direction: "ltr"
815
+ },
816
+ {
817
+ code: "be",
818
+ english: "Belarusian",
819
+ native: "\u0431\u0435\u043B\u0430\u0440\u0443\u0441\u043A\u0430\u044F",
820
+ direction: "ltr"
821
+ },
822
+ {
823
+ code: "bem",
824
+ english: "Bemba",
825
+ native: "Ichibemba",
826
+ direction: "ltr"
827
+ },
828
+ {
829
+ code: "bew",
830
+ english: "Betawi",
831
+ native: "Betawi",
832
+ direction: "ltr"
833
+ },
834
+ {
835
+ code: "bg",
836
+ english: "Bulgarian",
837
+ native: "\u0431\u044A\u043B\u0433\u0430\u0440\u0441\u043A\u0438",
838
+ direction: "ltr"
839
+ },
840
+ {
841
+ code: "bho",
842
+ english: "Bhojpuri",
843
+ native: "\u092D\u094B\u091C\u092A\u0941\u0930\u0940",
844
+ direction: "ltr"
845
+ },
846
+ {
847
+ code: "bik",
848
+ english: "Bikol",
849
+ native: "Bikol",
850
+ direction: "ltr"
851
+ },
852
+ {
853
+ code: "bm",
854
+ english: "Bambara",
855
+ native: "bamanakan",
856
+ direction: "ltr"
857
+ },
858
+ {
859
+ code: "bn",
860
+ english: "Bangla",
861
+ native: "\u09AC\u09BE\u0982\u09B2\u09BE",
862
+ direction: "ltr"
863
+ },
864
+ {
865
+ code: "bn-in",
866
+ english: "Bangla (India)",
867
+ native: "\u09AC\u09BE\u0982\u09B2\u09BE (\u09AD\u09BE\u09B0\u09A4)",
868
+ direction: "ltr"
869
+ },
870
+ {
871
+ code: "br",
872
+ english: "Breton",
873
+ native: "brezhoneg",
874
+ direction: "ltr"
875
+ },
876
+ {
877
+ code: "bs",
878
+ english: "Bosnian",
879
+ native: "bosanski",
880
+ direction: "ltr"
881
+ },
882
+ {
883
+ code: "bs-cyrl",
884
+ english: "Bosnian (Cyrillic)",
885
+ native: "\u0431\u043E\u0441\u0430\u043D\u0441\u043A\u0438 (\u045B\u0438\u0440\u0438\u043B\u0438\u0446\u0430)",
886
+ direction: "ltr"
887
+ },
888
+ {
889
+ code: "bts",
890
+ english: "bts",
891
+ native: "bts",
892
+ direction: "ltr"
893
+ },
894
+ {
895
+ code: "btx",
896
+ english: "btx",
897
+ native: "btx",
898
+ direction: "ltr"
899
+ },
900
+ {
901
+ code: "bua",
902
+ english: "Buriat",
903
+ native: "Buriat",
904
+ direction: "ltr"
905
+ },
906
+ {
907
+ code: "ca",
908
+ english: "Catalan",
909
+ native: "catal\xE0",
910
+ direction: "ltr"
911
+ },
912
+ {
913
+ code: "ceb",
914
+ english: "Cebuano",
915
+ native: "Cebuano",
916
+ direction: "ltr"
917
+ },
918
+ {
919
+ code: "cgg",
920
+ english: "Chiga",
921
+ native: "Rukiga",
922
+ direction: "ltr"
923
+ },
924
+ {
925
+ code: "chm",
926
+ english: "Mari",
927
+ native: "Mari",
928
+ direction: "ltr"
929
+ },
930
+ {
931
+ code: "ckb",
932
+ english: "Central Kurdish",
933
+ native: "\u06A9\u0648\u0631\u062F\u06CC\u06CC \u0646\u0627\u0648\u06D5\u0646\u062F\u06CC",
934
+ direction: "rtl"
935
+ },
936
+ {
937
+ code: "cnh",
938
+ english: "cnh",
939
+ native: "cnh",
940
+ direction: "ltr"
941
+ },
942
+ {
943
+ code: "co",
944
+ english: "Corsican",
945
+ native: "Corsican",
946
+ direction: "ltr"
947
+ },
948
+ {
949
+ code: "crh",
950
+ english: "Crimean Tatar",
951
+ native: "Crimean Tatar",
952
+ direction: "ltr"
953
+ },
954
+ {
955
+ code: "crs",
956
+ english: "Seselwa Creole French",
957
+ native: "Seselwa Creole French",
958
+ direction: "ltr"
959
+ },
960
+ {
961
+ code: "cs",
962
+ english: "Czech",
963
+ native: "\u010De\u0161tina",
964
+ direction: "ltr"
965
+ },
966
+ {
967
+ code: "cv",
968
+ english: "Chuvash",
969
+ native: "\u0447\u04D1\u0432\u0430\u0448",
970
+ direction: "ltr"
971
+ },
972
+ {
973
+ code: "cy",
974
+ english: "Welsh",
975
+ native: "Cymraeg",
976
+ direction: "ltr"
977
+ },
978
+ {
979
+ code: "da",
980
+ english: "Danish",
981
+ native: "dansk",
982
+ direction: "ltr"
983
+ },
984
+ {
985
+ code: "de",
986
+ english: "German",
987
+ native: "Deutsch",
988
+ direction: "ltr"
989
+ },
990
+ {
991
+ code: "din",
992
+ english: "Dinka",
993
+ native: "Dinka",
994
+ direction: "ltr"
995
+ },
996
+ {
997
+ code: "doi",
998
+ english: "Dogri",
999
+ native: "\u0921\u094B\u0917\u0930\u0940",
1000
+ direction: "ltr"
1001
+ },
1002
+ {
1003
+ code: "dov",
1004
+ english: "dov",
1005
+ native: "dov",
1006
+ direction: "ltr"
1007
+ },
1008
+ {
1009
+ code: "dv",
1010
+ english: "Divehi",
1011
+ native: "Divehi",
1012
+ direction: "rtl"
1013
+ },
1014
+ {
1015
+ code: "dz",
1016
+ english: "Dzongkha",
1017
+ native: "\u0F62\u0FAB\u0F7C\u0F44\u0F0B\u0F41",
1018
+ direction: "ltr"
1019
+ },
1020
+ {
1021
+ code: "ee",
1022
+ english: "Ewe",
1023
+ native: "E\u028Begbe",
1024
+ direction: "ltr"
1025
+ },
1026
+ {
1027
+ code: "el",
1028
+ english: "Greek",
1029
+ native: "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC",
1030
+ direction: "ltr"
1031
+ },
1032
+ {
1033
+ code: "en",
1034
+ english: "English",
1035
+ native: "English",
1036
+ direction: "ltr"
1037
+ },
1038
+ {
1039
+ code: "en-au",
1040
+ english: "Australian English",
1041
+ native: "Australian English",
1042
+ direction: "ltr"
1043
+ },
1044
+ {
1045
+ code: "en-ca",
1046
+ english: "Canadian English",
1047
+ native: "Canadian English",
1048
+ direction: "ltr"
1049
+ },
1050
+ {
1051
+ code: "en-gb",
1052
+ english: "British English",
1053
+ native: "British English",
1054
+ direction: "ltr"
1055
+ },
1056
+ {
1057
+ code: "en-nz",
1058
+ english: "English (New Zealand)",
1059
+ native: "English (New Zealand)",
1060
+ direction: "ltr"
1061
+ },
1062
+ {
1063
+ code: "en-ph",
1064
+ english: "English (Philippines)",
1065
+ native: "English (Philippines)",
1066
+ direction: "ltr"
1067
+ },
1068
+ {
1069
+ code: "en-us",
1070
+ english: "American English",
1071
+ native: "American English",
1072
+ direction: "ltr"
1073
+ },
1074
+ {
1075
+ code: "en-za",
1076
+ english: "English (South Africa)",
1077
+ native: "English (South Africa)",
1078
+ direction: "ltr"
1079
+ },
1080
+ {
1081
+ code: "eo",
1082
+ english: "Esperanto",
1083
+ native: "Esperanto",
1084
+ direction: "ltr"
1085
+ },
1086
+ {
1087
+ code: "es",
1088
+ english: "Spanish",
1089
+ native: "espa\xF1ol",
1090
+ direction: "ltr"
1091
+ },
1092
+ {
1093
+ code: "es-419",
1094
+ english: "Latin American Spanish",
1095
+ native: "espa\xF1ol latinoamericano",
1096
+ direction: "ltr"
1097
+ },
1098
+ {
1099
+ code: "es-ar",
1100
+ english: "Spanish (Argentina)",
1101
+ native: "espa\xF1ol (Argentina)",
1102
+ direction: "ltr"
1103
+ },
1104
+ {
1105
+ code: "es-cl",
1106
+ english: "Spanish (Chile)",
1107
+ native: "espa\xF1ol (Chile)",
1108
+ direction: "ltr"
1109
+ },
1110
+ {
1111
+ code: "es-co",
1112
+ english: "Spanish (Colombia)",
1113
+ native: "espa\xF1ol (Colombia)",
1114
+ direction: "ltr"
1115
+ },
1116
+ {
1117
+ code: "es-cr",
1118
+ english: "Spanish (Costa Rica)",
1119
+ native: "espa\xF1ol (Costa Rica)",
1120
+ direction: "ltr"
1121
+ },
1122
+ {
1123
+ code: "es-ec",
1124
+ english: "Spanish (Ecuador)",
1125
+ native: "espa\xF1ol (Ecuador)",
1126
+ direction: "ltr"
1127
+ },
1128
+ {
1129
+ code: "es-es",
1130
+ english: "European Spanish",
1131
+ native: "espa\xF1ol de Espa\xF1a",
1132
+ direction: "ltr"
1133
+ },
1134
+ {
1135
+ code: "es-gt",
1136
+ english: "Spanish (Guatemala)",
1137
+ native: "espa\xF1ol (Guatemala)",
1138
+ direction: "ltr"
1139
+ },
1140
+ {
1141
+ code: "es-hn",
1142
+ english: "Spanish (Honduras)",
1143
+ native: "espa\xF1ol (Honduras)",
1144
+ direction: "ltr"
1145
+ },
1146
+ {
1147
+ code: "es-ht",
1148
+ english: "Spanish (Haiti)",
1149
+ native: "espa\xF1ol (Hait\xED)",
1150
+ direction: "ltr"
1151
+ },
1152
+ {
1153
+ code: "es-mx",
1154
+ english: "Mexican Spanish",
1155
+ native: "espa\xF1ol de M\xE9xico",
1156
+ direction: "ltr"
1157
+ },
1158
+ {
1159
+ code: "es-ni",
1160
+ english: "Spanish (Nicaragua)",
1161
+ native: "espa\xF1ol (Nicaragua)",
1162
+ direction: "ltr"
1163
+ },
1164
+ {
1165
+ code: "es-pa",
1166
+ english: "Spanish (Panama)",
1167
+ native: "espa\xF1ol (Panam\xE1)",
1168
+ direction: "ltr"
1169
+ },
1170
+ {
1171
+ code: "es-pe",
1172
+ english: "Spanish (Peru)",
1173
+ native: "espa\xF1ol (Per\xFA)",
1174
+ direction: "ltr"
1175
+ },
1176
+ {
1177
+ code: "es-pr",
1178
+ english: "Spanish (Puerto Rico)",
1179
+ native: "espa\xF1ol (Puerto Rico)",
1180
+ direction: "ltr"
1181
+ },
1182
+ {
1183
+ code: "es-py",
1184
+ english: "Spanish (Paraguay)",
1185
+ native: "espa\xF1ol (Paraguay)",
1186
+ direction: "ltr"
1187
+ },
1188
+ {
1189
+ code: "es-sv",
1190
+ english: "Spanish (El Salvador)",
1191
+ native: "espa\xF1ol (El Salvador)",
1192
+ direction: "ltr"
1193
+ },
1194
+ {
1195
+ code: "es-us",
1196
+ english: "Spanish (United States)",
1197
+ native: "espa\xF1ol (Estados Unidos)",
1198
+ direction: "ltr"
1199
+ },
1200
+ {
1201
+ code: "es-uy",
1202
+ english: "Spanish (Uruguay)",
1203
+ native: "espa\xF1ol (Uruguay)",
1204
+ direction: "ltr"
1205
+ },
1206
+ {
1207
+ code: "es-ve",
1208
+ english: "Spanish (Venezuela)",
1209
+ native: "espa\xF1ol (Venezuela)",
1210
+ direction: "ltr"
1211
+ },
1212
+ {
1213
+ code: "et",
1214
+ english: "Estonian",
1215
+ native: "eesti",
1216
+ direction: "ltr"
1217
+ },
1218
+ {
1219
+ code: "eu",
1220
+ english: "Basque",
1221
+ native: "euskara",
1222
+ direction: "ltr"
1223
+ },
1224
+ {
1225
+ code: "fa",
1226
+ english: "Persian",
1227
+ native: "\u0641\u0627\u0631\u0633\u06CC",
1228
+ direction: "rtl"
1229
+ },
1230
+ {
1231
+ code: "ff",
1232
+ english: "Fula",
1233
+ native: "Pulaar",
1234
+ direction: "rtl"
1235
+ },
1236
+ {
1237
+ code: "fi",
1238
+ english: "Finnish",
1239
+ native: "suomi",
1240
+ direction: "ltr"
1241
+ },
1242
+ {
1243
+ code: "fil",
1244
+ english: "Filipino",
1245
+ native: "Filipino",
1246
+ direction: "ltr"
1247
+ },
1248
+ {
1249
+ code: "fj",
1250
+ english: "Fijian",
1251
+ native: "Fijian",
1252
+ direction: "ltr"
1253
+ },
1254
+ {
1255
+ code: "fr",
1256
+ english: "French",
1257
+ native: "fran\xE7ais",
1258
+ direction: "ltr"
1259
+ },
1260
+ {
1261
+ code: "fr-ca",
1262
+ english: "Canadian French",
1263
+ native: "fran\xE7ais canadien",
1264
+ direction: "ltr"
1265
+ },
1266
+ {
1267
+ code: "fr-ch",
1268
+ english: "Swiss French",
1269
+ native: "fran\xE7ais suisse",
1270
+ direction: "ltr"
1271
+ },
1272
+ {
1273
+ code: "fr-fr",
1274
+ english: "French (France)",
1275
+ native: "fran\xE7ais (France)",
1276
+ direction: "ltr"
1277
+ },
1278
+ {
1279
+ code: "fy",
1280
+ english: "Western Frisian",
1281
+ native: "Frysk",
1282
+ direction: "ltr"
1283
+ },
1284
+ {
1285
+ code: "ga",
1286
+ english: "Irish",
1287
+ native: "Gaeilge",
1288
+ direction: "ltr"
1289
+ },
1290
+ {
1291
+ code: "gaa",
1292
+ english: "Ga",
1293
+ native: "Ga",
1294
+ direction: "ltr"
1295
+ },
1296
+ {
1297
+ code: "gd",
1298
+ english: "Scottish Gaelic",
1299
+ native: "G\xE0idhlig",
1300
+ direction: "ltr"
1301
+ },
1302
+ {
1303
+ code: "gl",
1304
+ english: "Galician",
1305
+ native: "galego",
1306
+ direction: "ltr"
1307
+ },
1308
+ {
1309
+ code: "gn",
1310
+ english: "Guarani",
1311
+ native: "Guarani",
1312
+ direction: "ltr"
1313
+ },
1314
+ {
1315
+ code: "gom",
1316
+ english: "Goan Konkani",
1317
+ native: "Goan Konkani",
1318
+ direction: "ltr"
1319
+ },
1320
+ {
1321
+ code: "gu",
1322
+ english: "Gujarati",
1323
+ native: "\u0A97\u0AC1\u0A9C\u0AB0\u0ABE\u0AA4\u0AC0",
1324
+ direction: "ltr"
1325
+ },
1326
+ {
1327
+ code: "ha",
1328
+ english: "Hausa",
1329
+ native: "Hausa",
1330
+ direction: "rtl"
1331
+ },
1332
+ {
1333
+ code: "haw",
1334
+ english: "Hawaiian",
1335
+ native: "\u02BB\u014Clelo Hawai\u02BBi",
1336
+ direction: "ltr"
1337
+ },
1338
+ {
1339
+ code: "he",
1340
+ english: "Hebrew",
1341
+ native: "\u05E2\u05D1\u05E8\u05D9\u05EA",
1342
+ direction: "rtl"
1343
+ },
1344
+ {
1345
+ code: "hi",
1346
+ english: "Hindi",
1347
+ native: "\u0939\u093F\u0928\u094D\u0926\u0940",
1348
+ direction: "ltr"
1349
+ },
1350
+ {
1351
+ code: "hil",
1352
+ english: "Hiligaynon",
1353
+ native: "Hiligaynon",
1354
+ direction: "ltr"
1355
+ },
1356
+ {
1357
+ code: "hmn",
1358
+ english: "Hmong",
1359
+ native: "Hmong",
1360
+ direction: "ltr"
1361
+ },
1362
+ {
1363
+ code: "hr",
1364
+ english: "Croatian",
1365
+ native: "hrvatski",
1366
+ direction: "ltr"
1367
+ },
1368
+ {
1369
+ code: "hrx",
1370
+ english: "hrx",
1371
+ native: "hrx",
1372
+ direction: "ltr"
1373
+ },
1374
+ {
1375
+ code: "ht",
1376
+ english: "Haitian Creole",
1377
+ native: "Haitian Creole",
1378
+ direction: "ltr"
1379
+ },
1380
+ {
1381
+ code: "hu",
1382
+ english: "Hungarian",
1383
+ native: "magyar",
1384
+ direction: "ltr"
1385
+ },
1386
+ {
1387
+ code: "hy",
1388
+ english: "Armenian",
1389
+ native: "\u0570\u0561\u0575\u0565\u0580\u0565\u0576",
1390
+ direction: "ltr"
1391
+ },
1392
+ {
1393
+ code: "id",
1394
+ english: "Indonesian",
1395
+ native: "Indonesia",
1396
+ direction: "ltr"
1397
+ },
1398
+ {
1399
+ code: "ig",
1400
+ english: "Igbo",
1401
+ native: "Igbo",
1402
+ direction: "ltr"
1403
+ },
1404
+ {
1405
+ code: "ilo",
1406
+ english: "Iloko",
1407
+ native: "Iloko",
1408
+ direction: "ltr"
1409
+ },
1410
+ {
1411
+ code: "is",
1412
+ english: "Icelandic",
1413
+ native: "\xEDslenska",
1414
+ direction: "ltr"
1415
+ },
1416
+ {
1417
+ code: "it",
1418
+ english: "Italian",
1419
+ native: "italiano",
1420
+ direction: "ltr"
1421
+ },
1422
+ {
1423
+ code: "iw",
1424
+ english: "Hebrew",
1425
+ native: "\u05E2\u05D1\u05E8\u05D9\u05EA",
1426
+ direction: "rtl"
1427
+ },
1428
+ {
1429
+ code: "ja",
1430
+ english: "Japanese",
1431
+ native: "\u65E5\u672C\u8A9E",
1432
+ direction: "ltr"
1433
+ },
1434
+ {
1435
+ code: "jv",
1436
+ english: "Javanese",
1437
+ native: "Jawa",
1438
+ direction: "ltr"
1439
+ },
1440
+ {
1441
+ code: "jw",
1442
+ english: "Javanese",
1443
+ native: "Jawa",
1444
+ direction: "ltr"
1445
+ },
1446
+ {
1447
+ code: "ka",
1448
+ english: "Georgian",
1449
+ native: "\u10E5\u10D0\u10E0\u10D7\u10E3\u10DA\u10D8",
1450
+ direction: "ltr"
1451
+ },
1452
+ {
1453
+ code: "kk",
1454
+ english: "Kazakh",
1455
+ native: "\u049B\u0430\u0437\u0430\u049B \u0442\u0456\u043B\u0456",
1456
+ direction: "ltr"
1457
+ },
1458
+ {
1459
+ code: "km",
1460
+ english: "Khmer",
1461
+ native: "\u1781\u17D2\u1798\u17C2\u179A",
1462
+ direction: "ltr"
1463
+ },
1464
+ {
1465
+ code: "kn",
1466
+ english: "Kannada",
1467
+ native: "\u0C95\u0CA8\u0CCD\u0CA8\u0CA1",
1468
+ direction: "ltr"
1469
+ },
1470
+ {
1471
+ code: "ko",
1472
+ english: "Korean",
1473
+ native: "\uD55C\uAD6D\uC5B4",
1474
+ direction: "ltr"
1475
+ },
1476
+ {
1477
+ code: "kri",
1478
+ english: "Krio",
1479
+ native: "Krio",
1480
+ direction: "ltr"
1481
+ },
1482
+ {
1483
+ code: "ktu",
1484
+ english: "ktu",
1485
+ native: "ktu",
1486
+ direction: "ltr"
1487
+ },
1488
+ {
1489
+ code: "ku",
1490
+ english: "Kurdish",
1491
+ native: "kurd\xEE (kurmanc\xEE)",
1492
+ direction: "ltr"
1493
+ },
1494
+ {
1495
+ code: "ky",
1496
+ english: "Kyrgyz",
1497
+ native: "\u043A\u044B\u0440\u0433\u044B\u0437\u0447\u0430",
1498
+ direction: "ltr"
1499
+ },
1500
+ {
1501
+ code: "la",
1502
+ english: "Latin",
1503
+ native: "Latin",
1504
+ direction: "ltr"
1505
+ },
1506
+ {
1507
+ code: "lb",
1508
+ english: "Luxembourgish",
1509
+ native: "L\xEBtzebuergesch",
1510
+ direction: "ltr"
1511
+ },
1512
+ {
1513
+ code: "lg",
1514
+ english: "Ganda",
1515
+ native: "Luganda",
1516
+ direction: "ltr"
1517
+ },
1518
+ {
1519
+ code: "li",
1520
+ english: "Limburgish",
1521
+ native: "Limburgish",
1522
+ direction: "ltr"
1523
+ },
1524
+ {
1525
+ code: "lij",
1526
+ english: "Ligurian",
1527
+ native: "ligure",
1528
+ direction: "ltr"
1529
+ },
1530
+ {
1531
+ code: "lmo",
1532
+ english: "Lombard",
1533
+ native: "Lombard",
1534
+ direction: "ltr"
1535
+ },
1536
+ {
1537
+ code: "ln",
1538
+ english: "Lingala",
1539
+ native: "ling\xE1la",
1540
+ direction: "ltr"
1541
+ },
1542
+ {
1543
+ code: "lo",
1544
+ english: "Lao",
1545
+ native: "\u0EA5\u0EB2\u0EA7",
1546
+ direction: "ltr"
1547
+ },
1548
+ {
1549
+ code: "lt",
1550
+ english: "Lithuanian",
1551
+ native: "lietuvi\u0173",
1552
+ direction: "ltr"
1553
+ },
1554
+ {
1555
+ code: "ltg",
1556
+ english: "Latgalian",
1557
+ native: "Latgalian",
1558
+ direction: "ltr"
1559
+ },
1560
+ {
1561
+ code: "luo",
1562
+ english: "Luo",
1563
+ native: "Dholuo",
1564
+ direction: "ltr"
1565
+ },
1566
+ {
1567
+ code: "lus",
1568
+ english: "Mizo",
1569
+ native: "Mizo",
1570
+ direction: "ltr"
1571
+ },
1572
+ {
1573
+ code: "lv",
1574
+ english: "Latvian",
1575
+ native: "latvie\u0161u",
1576
+ direction: "ltr"
1577
+ },
1578
+ {
1579
+ code: "mai",
1580
+ english: "Maithili",
1581
+ native: "\u092E\u0948\u0925\u093F\u0932\u0940",
1582
+ direction: "ltr"
1583
+ },
1584
+ {
1585
+ code: "mak",
1586
+ english: "Makasar",
1587
+ native: "Makasar",
1588
+ direction: "ltr"
1589
+ },
1590
+ {
1591
+ code: "mg",
1592
+ english: "Malagasy",
1593
+ native: "Malagasy",
1594
+ direction: "ltr"
1595
+ },
1596
+ {
1597
+ code: "mi",
1598
+ english: "M\u0101ori",
1599
+ native: "M\u0101ori",
1600
+ direction: "ltr"
1601
+ },
1602
+ {
1603
+ code: "min",
1604
+ english: "Minangkabau",
1605
+ native: "Minangkabau",
1606
+ direction: "ltr"
1607
+ },
1608
+ {
1609
+ code: "mk",
1610
+ english: "Macedonian",
1611
+ native: "\u043C\u0430\u043A\u0435\u0434\u043E\u043D\u0441\u043A\u0438",
1612
+ direction: "ltr"
1613
+ },
1614
+ {
1615
+ code: "ml",
1616
+ english: "Malayalam",
1617
+ native: "\u0D2E\u0D32\u0D2F\u0D3E\u0D33\u0D02",
1618
+ direction: "ltr"
1619
+ },
1620
+ {
1621
+ code: "mn",
1622
+ english: "Mongolian",
1623
+ native: "\u043C\u043E\u043D\u0433\u043E\u043B",
1624
+ direction: "ltr"
1625
+ },
1626
+ {
1627
+ code: "mni-mtei",
1628
+ english: "Manipuri (Meitei Mayek)",
1629
+ native: "\u09AE\u09C8\u09A4\u09C8\u09B2\u09CB\u09A8\u09CD (\u09AE\u09C0\u09A4\u09C8 \u09AE\u09AF\u09BC\u09C7\u0995)",
1630
+ direction: "ltr"
1631
+ },
1632
+ {
1633
+ code: "mr",
1634
+ english: "Marathi",
1635
+ native: "\u092E\u0930\u093E\u0920\u0940",
1636
+ direction: "ltr"
1637
+ },
1638
+ {
1639
+ code: "ms",
1640
+ english: "Malay",
1641
+ native: "Melayu",
1642
+ direction: "ltr"
1643
+ },
1644
+ {
1645
+ code: "ms-arab",
1646
+ english: "Malay (Arabic)",
1647
+ native: "Melayu (Arab)",
1648
+ direction: "ltr"
1649
+ },
1650
+ {
1651
+ code: "mt",
1652
+ english: "Maltese",
1653
+ native: "Malti",
1654
+ direction: "ltr"
1655
+ },
1656
+ {
1657
+ code: "my",
1658
+ english: "Burmese",
1659
+ native: "\u1019\u103C\u1014\u103A\u1019\u102C",
1660
+ direction: "ltr"
1661
+ },
1662
+ {
1663
+ code: "nb",
1664
+ english: "Norwegian Bokm\xE5l",
1665
+ native: "norsk bokm\xE5l",
1666
+ direction: "ltr"
1667
+ },
1668
+ {
1669
+ code: "ne",
1670
+ english: "Nepali",
1671
+ native: "\u0928\u0947\u092A\u093E\u0932\u0940",
1672
+ direction: "ltr"
1673
+ },
1674
+ {
1675
+ code: "new",
1676
+ english: "Newari",
1677
+ native: "Newari",
1678
+ direction: "ltr"
1679
+ },
1680
+ {
1681
+ code: "nl",
1682
+ english: "Dutch",
1683
+ native: "Nederlands",
1684
+ direction: "ltr"
1685
+ },
1686
+ {
1687
+ code: "nl-be",
1688
+ english: "Flemish",
1689
+ native: "Vlaams",
1690
+ direction: "ltr"
1691
+ },
1692
+ {
1693
+ code: "no",
1694
+ english: "Norwegian",
1695
+ native: "norsk",
1696
+ direction: "ltr"
1697
+ },
1698
+ {
1699
+ code: "nr",
1700
+ english: "South Ndebele",
1701
+ native: "South Ndebele",
1702
+ direction: "ltr"
1703
+ },
1704
+ {
1705
+ code: "nso",
1706
+ english: "Northern Sotho",
1707
+ native: "Northern Sotho",
1708
+ direction: "ltr"
1709
+ },
1710
+ {
1711
+ code: "nus",
1712
+ english: "Nuer",
1713
+ native: "Thok Nath",
1714
+ direction: "ltr"
1715
+ },
1716
+ {
1717
+ code: "ny",
1718
+ english: "Nyanja",
1719
+ native: "Nyanja",
1720
+ direction: "ltr"
1721
+ },
1722
+ {
1723
+ code: "oc",
1724
+ english: "Occitan",
1725
+ native: "occitan",
1726
+ direction: "ltr"
1727
+ },
1728
+ {
1729
+ code: "om",
1730
+ english: "Oromo",
1731
+ native: "Oromoo",
1732
+ direction: "ltr"
1733
+ },
1734
+ {
1735
+ code: "or",
1736
+ english: "Odia",
1737
+ native: "\u0B13\u0B21\u0B3C\u0B3F\u0B06",
1738
+ direction: "ltr"
1739
+ },
1740
+ {
1741
+ code: "pa",
1742
+ english: "Punjabi",
1743
+ native: "\u0A2A\u0A70\u0A1C\u0A3E\u0A2C\u0A40",
1744
+ direction: "ltr"
1745
+ },
1746
+ {
1747
+ code: "pa-arab",
1748
+ english: "Punjabi (Arabic)",
1749
+ native: "\u067E\u0646\u062C\u0627\u0628\u06CC (\u0639\u0631\u0628\u06CC)",
1750
+ direction: "ltr"
1751
+ },
1752
+ {
1753
+ code: "pa-pk",
1754
+ english: "Punjabi (Pakistan)",
1755
+ native: "\u067E\u0646\u062C\u0627\u0628\u06CC (\u067E\u0627\u06A9\u0633\u062A\u0627\u0646)",
1756
+ direction: "ltr"
1757
+ },
1758
+ {
1759
+ code: "pag",
1760
+ english: "Pangasinan",
1761
+ native: "Pangasinan",
1762
+ direction: "ltr"
1763
+ },
1764
+ {
1765
+ code: "pam",
1766
+ english: "Pampanga",
1767
+ native: "Pampanga",
1768
+ direction: "ltr"
1769
+ },
1770
+ {
1771
+ code: "pap",
1772
+ english: "Papiamento",
1773
+ native: "Papiamento",
1774
+ direction: "ltr"
1775
+ },
1776
+ {
1777
+ code: "pl",
1778
+ english: "Polish",
1779
+ native: "polski",
1780
+ direction: "ltr"
1781
+ },
1782
+ {
1783
+ code: "ps",
1784
+ english: "Pashto",
1785
+ native: "\u067E\u069A\u062A\u0648",
1786
+ direction: "rtl"
1787
+ },
1788
+ {
1789
+ code: "pt",
1790
+ english: "Portuguese",
1791
+ native: "portugu\xEAs",
1792
+ direction: "ltr"
1793
+ },
1794
+ {
1795
+ code: "pt-br",
1796
+ english: "Brazilian Portuguese",
1797
+ native: "portugu\xEAs (Brasil)",
1798
+ direction: "ltr"
1799
+ },
1800
+ {
1801
+ code: "pt-pt",
1802
+ english: "European Portuguese",
1803
+ native: "portugu\xEAs europeu",
1804
+ direction: "ltr"
1805
+ },
1806
+ {
1807
+ code: "qu",
1808
+ english: "Quechua",
1809
+ native: "Runasimi",
1810
+ direction: "ltr"
1811
+ },
1812
+ {
1813
+ code: "rn",
1814
+ english: "Rundi",
1815
+ native: "Ikirundi",
1816
+ direction: "ltr"
1817
+ },
1818
+ {
1819
+ code: "ro",
1820
+ english: "Romanian",
1821
+ native: "rom\xE2n\u0103",
1822
+ direction: "ltr"
1823
+ },
1824
+ {
1825
+ code: "rom",
1826
+ english: "Romany",
1827
+ native: "Romany",
1828
+ direction: "ltr"
1829
+ },
1830
+ {
1831
+ code: "ru",
1832
+ english: "Russian",
1833
+ native: "\u0440\u0443\u0441\u0441\u043A\u0438\u0439",
1834
+ direction: "ltr"
1835
+ },
1836
+ {
1837
+ code: "rw",
1838
+ english: "Kinyarwanda",
1839
+ native: "Kinyarwanda",
1840
+ direction: "ltr"
1841
+ },
1842
+ {
1843
+ code: "sa",
1844
+ english: "Sanskrit",
1845
+ native: "\u0938\u0902\u0938\u094D\u0915\u0943\u0924 \u092D\u093E\u0937\u093E",
1846
+ direction: "ltr"
1847
+ },
1848
+ {
1849
+ code: "scn",
1850
+ english: "Sicilian",
1851
+ native: "Sicilian",
1852
+ direction: "ltr"
1853
+ },
1854
+ {
1855
+ code: "sd",
1856
+ english: "Sindhi",
1857
+ native: "\u0633\u0646\u068C\u064A",
1858
+ direction: "rtl"
1859
+ },
1860
+ {
1861
+ code: "sg",
1862
+ english: "Sango",
1863
+ native: "S\xE4ng\xF6",
1864
+ direction: "ltr"
1865
+ },
1866
+ {
1867
+ code: "shn",
1868
+ english: "Shan",
1869
+ native: "Shan",
1870
+ direction: "ltr"
1871
+ },
1872
+ {
1873
+ code: "si",
1874
+ english: "Sinhala",
1875
+ native: "\u0DC3\u0DD2\u0D82\u0DC4\u0DBD",
1876
+ direction: "ltr"
1877
+ },
1878
+ {
1879
+ code: "sk",
1880
+ english: "Slovak",
1881
+ native: "sloven\u010Dina",
1882
+ direction: "ltr"
1883
+ },
1884
+ {
1885
+ code: "sl",
1886
+ english: "Slovenian",
1887
+ native: "sloven\u0161\u010Dina",
1888
+ direction: "ltr"
1889
+ },
1890
+ {
1891
+ code: "sm",
1892
+ english: "Samoan",
1893
+ native: "Samoan",
1894
+ direction: "ltr"
1895
+ },
1896
+ {
1897
+ code: "sn",
1898
+ english: "Shona",
1899
+ native: "chiShona",
1900
+ direction: "ltr"
1901
+ },
1902
+ {
1903
+ code: "so",
1904
+ english: "Somali",
1905
+ native: "Soomaali",
1906
+ direction: "ltr"
1907
+ },
1908
+ {
1909
+ code: "sq",
1910
+ english: "Albanian",
1911
+ native: "shqip",
1912
+ direction: "ltr"
1913
+ },
1914
+ {
1915
+ code: "sr",
1916
+ english: "Serbian",
1917
+ native: "\u0441\u0440\u043F\u0441\u043A\u0438",
1918
+ direction: "ltr"
1919
+ },
1920
+ {
1921
+ code: "ss",
1922
+ english: "Swati",
1923
+ native: "Swati",
1924
+ direction: "ltr"
1925
+ },
1926
+ {
1927
+ code: "st",
1928
+ english: "Southern Sotho",
1929
+ native: "Southern Sotho",
1930
+ direction: "ltr"
1931
+ },
1932
+ {
1933
+ code: "su",
1934
+ english: "Sundanese",
1935
+ native: "Basa Sunda",
1936
+ direction: "ltr"
1937
+ },
1938
+ {
1939
+ code: "sv",
1940
+ english: "Swedish",
1941
+ native: "svenska",
1942
+ direction: "ltr"
1943
+ },
1944
+ {
1945
+ code: "sw",
1946
+ english: "Swahili",
1947
+ native: "Kiswahili",
1948
+ direction: "ltr"
1949
+ },
1950
+ {
1951
+ code: "szl",
1952
+ english: "Silesian",
1953
+ native: "\u015Bl\u014Dnski",
1954
+ direction: "ltr"
1955
+ },
1956
+ {
1957
+ code: "ta",
1958
+ english: "Tamil",
1959
+ native: "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD",
1960
+ direction: "ltr"
1961
+ },
1962
+ {
1963
+ code: "te",
1964
+ english: "Telugu",
1965
+ native: "\u0C24\u0C46\u0C32\u0C41\u0C17\u0C41",
1966
+ direction: "ltr"
1967
+ },
1968
+ {
1969
+ code: "tet",
1970
+ english: "Tetum",
1971
+ native: "Tetum",
1972
+ direction: "ltr"
1973
+ },
1974
+ {
1975
+ code: "tg",
1976
+ english: "Tajik",
1977
+ native: "\u0442\u043E\u04B7\u0438\u043A\u04E3",
1978
+ direction: "ltr"
1979
+ },
1980
+ {
1981
+ code: "th",
1982
+ english: "Thai",
1983
+ native: "\u0E44\u0E17\u0E22",
1984
+ direction: "ltr"
1985
+ },
1986
+ {
1987
+ code: "ti",
1988
+ english: "Tigrinya",
1989
+ native: "\u1275\u130D\u122D\u129B",
1990
+ direction: "ltr"
1991
+ },
1992
+ {
1993
+ code: "tk",
1994
+ english: "Turkmen",
1995
+ native: "t\xFCrkmen dili",
1996
+ direction: "ltr"
1997
+ },
1998
+ {
1999
+ code: "tl",
2000
+ english: "Filipino",
2001
+ native: "Filipino",
2002
+ direction: "ltr"
2003
+ },
2004
+ {
2005
+ code: "tn",
2006
+ english: "Tswana",
2007
+ native: "Tswana",
2008
+ direction: "ltr"
2009
+ },
2010
+ {
2011
+ code: "tr",
2012
+ english: "Turkish",
2013
+ native: "T\xFCrk\xE7e",
2014
+ direction: "ltr"
2015
+ },
2016
+ {
2017
+ code: "ts",
2018
+ english: "Tsonga",
2019
+ native: "Tsonga",
2020
+ direction: "ltr"
2021
+ },
2022
+ {
2023
+ code: "tt",
2024
+ english: "Tatar",
2025
+ native: "\u0442\u0430\u0442\u0430\u0440",
2026
+ direction: "ltr"
2027
+ },
2028
+ {
2029
+ code: "ug",
2030
+ english: "Uyghur",
2031
+ native: "\u0626\u06C7\u064A\u063A\u06C7\u0631\u0686\u06D5",
2032
+ direction: "rtl"
2033
+ },
2034
+ {
2035
+ code: "uk",
2036
+ english: "Ukrainian",
2037
+ native: "\u0443\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430",
2038
+ direction: "ltr"
2039
+ },
2040
+ {
2041
+ code: "ur",
2042
+ english: "Urdu",
2043
+ native: "\u0627\u0631\u062F\u0648",
2044
+ direction: "rtl"
2045
+ },
2046
+ {
2047
+ code: "uz",
2048
+ english: "Uzbek",
2049
+ native: "o\u2018zbek",
2050
+ direction: "ltr"
2051
+ },
2052
+ {
2053
+ code: "vi",
2054
+ english: "Vietnamese",
2055
+ native: "Ti\u1EBFng Vi\u1EC7t",
2056
+ direction: "ltr"
2057
+ },
2058
+ {
2059
+ code: "xh",
2060
+ english: "Xhosa",
2061
+ native: "IsiXhosa",
2062
+ direction: "ltr"
2063
+ },
2064
+ {
2065
+ code: "yi",
2066
+ english: "Yiddish",
2067
+ native: "\u05D9\u05D9\u05B4\u05D3\u05D9\u05E9",
2068
+ direction: "rtl"
2069
+ },
2070
+ {
2071
+ code: "yo",
2072
+ english: "Yoruba",
2073
+ native: "\xC8d\xE8 Yor\xF9b\xE1",
2074
+ direction: "ltr"
2075
+ },
2076
+ {
2077
+ code: "yua",
2078
+ english: "yua",
2079
+ native: "yua",
2080
+ direction: "ltr"
2081
+ },
2082
+ {
2083
+ code: "yue",
2084
+ english: "Cantonese",
2085
+ native: "\u7CB5\u8A9E",
2086
+ direction: "ltr"
2087
+ },
2088
+ {
2089
+ code: "zh",
2090
+ english: "Chinese",
2091
+ native: "\u4E2D\u6587",
2092
+ direction: "ltr"
2093
+ },
2094
+ {
2095
+ code: "zh-cn",
2096
+ english: "Chinese (China)",
2097
+ native: "\u4E2D\u6587\uFF08\u4E2D\u56FD\uFF09",
2098
+ direction: "ltr"
2099
+ },
2100
+ {
2101
+ code: "zh-hans",
2102
+ english: "Simplified Chinese",
2103
+ native: "\u7B80\u4F53\u4E2D\u6587",
2104
+ direction: "ltr"
2105
+ },
2106
+ {
2107
+ code: "zh-hant",
2108
+ english: "Traditional Chinese",
2109
+ native: "\u7E41\u9AD4\u4E2D\u6587",
2110
+ direction: "ltr"
2111
+ },
2112
+ {
2113
+ code: "zh-hk",
2114
+ english: "Chinese (Hong Kong SAR China)",
2115
+ native: "\u4E2D\u6587\uFF08\u4E2D\u570B\u9999\u6E2F\u7279\u5225\u884C\u653F\u5340\uFF09",
2116
+ direction: "ltr"
2117
+ },
2118
+ {
2119
+ code: "zh-tw",
2120
+ english: "Chinese (Taiwan)",
2121
+ native: "\u4E2D\u6587\uFF08\u53F0\u7063\uFF09",
2122
+ direction: "ltr"
2123
+ },
2124
+ {
2125
+ code: "zu",
2126
+ english: "Zulu",
2127
+ native: "isiZulu",
2128
+ direction: "ltr"
2129
+ }
2130
+ ];
2131
+
2132
+ // src/shared/languages/catalog/index.ts
2133
+ var generatedLanguageCatalog = languages_default;
2134
+ function buildLanguageCatalog(raw) {
2135
+ return Object.freeze(raw.map((r) => ({ ...r, code: normalizeLanguageCode(r.code) })));
2136
+ }
2137
+ function filterLanguageCatalog(catalog2, filter) {
2138
+ const all = [...catalog2];
2139
+ const q = filter?.trim().toLowerCase();
2140
+ if (!q) return all.sort((a, b) => a.code.localeCompare(b.code));
2141
+ return all.filter(
2142
+ (r) => r.code.includes(q) || r.english.toLowerCase().includes(q) || r.native.toLowerCase().includes(q)
2143
+ ).sort((a, b) => a.code.localeCompare(b.code));
2144
+ }
2145
+ function getLanguageByCodeFromCatalog(catalog2, code) {
2146
+ const n = normalizeLanguageCode(code);
2147
+ return catalog2.find((r) => r.code === n);
2148
+ }
2149
+ function suggestCatalogCodesForInvalidInputFromCatalog(catalog2, code, maxCodesInCatalogHint = 5) {
2150
+ const n = normalizeLanguageCode(code);
2151
+ const all = [...catalog2].sort((a, b) => a.code.localeCompare(b.code));
2152
+ const out = [];
2153
+ const seen = /* @__PURE__ */ new Set();
2154
+ const push = (c) => {
2155
+ if (!seen.has(c)) {
2156
+ seen.add(c);
2157
+ out.push(c);
2158
+ }
2159
+ };
2160
+ for (const r of filterLanguageCatalog(catalog2, n)) {
2161
+ push(r.code);
2162
+ if (out.length >= maxCodesInCatalogHint) return out;
2163
+ }
2164
+ if (n.length >= 2) {
2165
+ const prefix = n.slice(0, 2);
2166
+ for (const r of all) {
2167
+ if (r.code.startsWith(prefix)) push(r.code);
2168
+ if (out.length >= maxCodesInCatalogHint) return out;
2169
+ }
2170
+ }
2171
+ for (const r of all) {
2172
+ push(r.code);
2173
+ if (out.length >= maxCodesInCatalogHint) return out;
2174
+ }
2175
+ return out;
2176
+ }
2177
+
2178
+ // src/shared/languages/validateTargetCode.ts
2179
+ var MAX_HINT = 5;
2180
+ function catalog() {
2181
+ return buildLanguageCatalog(generatedLanguageCatalog);
2182
+ }
2183
+ function assertSupportedTargetLanguageCode(code) {
2184
+ const cat = catalog();
2185
+ if (getLanguageByCodeFromCatalog(cat, code)) return;
2186
+ const hints = suggestCatalogCodesForInvalidInputFromCatalog(cat, code, MAX_HINT);
2187
+ const hintStr = hints.length > 0 ? hints.join(", ") : "run i18nprune languages for supported codes";
2188
+ throw new I18nPruneError(`Unsupported language code "${code}" \u2014 try: ${hintStr}`, "USAGE", {
2189
+ issueCode: ISSUE_LANGUAGES_UNSUPPORTED_LANGUAGE_CODE
2190
+ });
2191
+ }
2192
+
2193
+ // src/locales/targets.ts
2194
+ var ALL_LOCALES_TOKEN = "all";
2195
+ function parseLocaleCodesList(raw) {
2196
+ return raw.split(",").map((s) => s.trim()).filter(Boolean).map((c) => normalizeLanguageCode(c));
2197
+ }
2198
+ function isAllLocaleToken(raw) {
2199
+ return raw.trim().toLowerCase() === ALL_LOCALES_TOKEN;
2200
+ }
2201
+ function pickTargetSelector(target) {
2202
+ const t = target?.trim();
2203
+ if (t) return t;
2204
+ return void 0;
2205
+ }
2206
+ function parseSyncLangSelection(lang) {
2207
+ const primary = lang?.trim();
2208
+ if (primary) {
2209
+ if (isAllLocaleToken(primary)) return { mode: "all" };
2210
+ return { mode: "codes", codes: parseLocaleCodesList(primary) };
2211
+ }
2212
+ return { mode: "all" };
2213
+ }
2214
+ function resolveTargetLocaleSlugs(path, localeSlugs, sourceLocalePath) {
2215
+ return excludeSourceLocaleSlugs(path, localeSlugs, sourceLocalePath);
2216
+ }
2217
+ function resolveLocaleTargetCodes(input) {
2218
+ const { commandName, rawTarget, localeSlugs, sourceLocalePath, path } = input;
2219
+ const targetSlugs = resolveTargetLocaleSlugs(path, localeSlugs, sourceLocalePath);
2220
+ if (targetSlugs.length === 0) {
2221
+ throw new I18nPruneError(`${commandName}: no target locale files found in localesDir`, "USAGE");
2222
+ }
2223
+ const selected = pickTargetSelector(rawTarget);
2224
+ if (!selected) {
2225
+ throw new I18nPruneError(`${commandName} requires --target <code[,code]|all>`, "USAGE");
2226
+ }
2227
+ if (isAllLocaleToken(selected)) {
2228
+ return targetSlugs.map((x) => normalizeLanguageCode(x));
2229
+ }
2230
+ const parsed = parseLocaleCodesList(selected);
2231
+ for (const code of parsed) {
2232
+ assertNotSourceTargetLocale(commandName, code, sourceLocalePath, {
2233
+ paths: { sourceLocale: sourceLocalePath },
2234
+ path
2235
+ });
2236
+ if (!targetSlugs.some((x) => normalizeLanguageCode(x) === code)) {
2237
+ throw new I18nPruneError(`${commandName}: locale file not found for target "${code}"`, "USAGE");
2238
+ }
2239
+ }
2240
+ return parsed;
2241
+ }
2242
+
2243
+ // src/locales/resumeTargets.ts
2244
+ function resolveResumeAllTargetCodes(ctx, commandName) {
2245
+ const codes = targetLocaleCodesFromContext(ctx);
2246
+ if (codes.length === 0) {
2247
+ throw new I18nPruneError(`${commandName}: no target locale files found in localesDir`, "USAGE");
2248
+ }
2249
+ return codes.map((c) => normalizeLanguageCode(c));
2250
+ }
2251
+ function resolveResumeTargetCodesFromRaw(input) {
2252
+ const { commandName, raw, ctx } = input;
2253
+ const sourceLocalePath = ctx.paths.sourceLocale;
2254
+ const assertCtx = {
2255
+ paths: { sourceLocale: sourceLocalePath },
2256
+ path: ctx.adapters.path
2257
+ };
2258
+ if (isAllLocaleToken(raw)) {
2259
+ return resolveResumeAllTargetCodes(ctx, commandName);
2260
+ }
2261
+ if (raw.includes(",")) {
2262
+ const codes = parseLocaleCodesList(raw);
2263
+ for (const c of codes) {
2264
+ assertNotSourceTargetLocale(commandName, c, sourceLocalePath, assertCtx);
2265
+ assertSupportedTargetLanguageCode(c);
2266
+ }
2267
+ return codes;
2268
+ }
2269
+ const code = normalizeLanguageCode(raw);
2270
+ assertNotSourceTargetLocale(commandName, code, sourceLocalePath, assertCtx);
2271
+ assertSupportedTargetLanguageCode(code);
2272
+ return [code];
2273
+ }
2274
+
2275
+ // src/locales/generateTargets.ts
2276
+ function assertGenerateTargetCodes(input) {
2277
+ const { commandName, codes, sourceLocalePath, path } = input;
2278
+ const ctx = {
2279
+ paths: { sourceLocale: sourceLocalePath },
2280
+ path
2281
+ };
2282
+ for (const target of codes) {
2283
+ assertNotSourceTargetLocale(commandName, target, sourceLocalePath, ctx);
2284
+ assertSupportedTargetLanguageCode(target);
2285
+ }
2286
+ }
2287
+
2288
+ export { ALL_LOCALES_TOKEN, assertGenerateTargetCodes, assertNotSourceTargetLocale, buildLocaleListRows, buildSourceLocaleTruthLabel, excludeSourceLocaleSlugs, getDisplaySourceLocaleCode, getSourceLocaleSlug, isAllLocaleToken, isSourceLocaleSlug, listOtherLocaleCodes, parseLocaleCodesList, parseSyncLangSelection, pickTargetSelector, resolveLocaleTargetCodes, resolveResumeAllTargetCodes, resolveResumeTargetCodesFromRaw, resolveTargetLocaleSlugs };