poly-lexis 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/cli/translations.js +14 -1
- package/dist/cli/translations.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/scripts/verify-translations.js +470 -0
- package/dist/scripts/verify-translations.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
|
|
4
|
+
// src/translations/cli/validate.ts
|
|
5
|
+
import * as path3 from "path";
|
|
6
|
+
|
|
7
|
+
// src/translations/utils/utils.ts
|
|
8
|
+
import * as fs from "fs";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
function readTranslations(translationsPath, language) {
|
|
11
|
+
const langPath = path.join(translationsPath, language);
|
|
12
|
+
if (!fs.existsSync(langPath)) {
|
|
13
|
+
return {};
|
|
14
|
+
}
|
|
15
|
+
const files = fs.readdirSync(langPath).filter((f) => f.endsWith(".json"));
|
|
16
|
+
const translations = {};
|
|
17
|
+
for (const file of files) {
|
|
18
|
+
const namespace = path.basename(file, ".json");
|
|
19
|
+
const filePath = path.join(langPath, file);
|
|
20
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
21
|
+
translations[namespace] = JSON.parse(content);
|
|
22
|
+
}
|
|
23
|
+
return translations;
|
|
24
|
+
}
|
|
25
|
+
function getAvailableLanguages(translationsPath) {
|
|
26
|
+
if (!fs.existsSync(translationsPath)) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
return fs.readdirSync(translationsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
30
|
+
}
|
|
31
|
+
function getNamespaces(translationsPath, language) {
|
|
32
|
+
const langPath = path.join(translationsPath, language);
|
|
33
|
+
if (!fs.existsSync(langPath)) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
return fs.readdirSync(langPath).filter((f) => f.endsWith(".json")).map((f) => path.basename(f, ".json"));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/translations/cli/init.ts
|
|
40
|
+
import * as fs2 from "fs";
|
|
41
|
+
import * as path2 from "path";
|
|
42
|
+
|
|
43
|
+
// src/translations/core/schema.ts
|
|
44
|
+
var SUPPORTED_LANGUAGES = [
|
|
45
|
+
"af",
|
|
46
|
+
// Afrikaans
|
|
47
|
+
"sq",
|
|
48
|
+
// Albanian
|
|
49
|
+
"am",
|
|
50
|
+
// Amharic
|
|
51
|
+
"ar",
|
|
52
|
+
// Arabic
|
|
53
|
+
"hy",
|
|
54
|
+
// Armenian
|
|
55
|
+
"as",
|
|
56
|
+
// Assamese
|
|
57
|
+
"ay",
|
|
58
|
+
// Aymara
|
|
59
|
+
"az",
|
|
60
|
+
// Azerbaijani
|
|
61
|
+
"bm",
|
|
62
|
+
// Bambara
|
|
63
|
+
"eu",
|
|
64
|
+
// Basque
|
|
65
|
+
"be",
|
|
66
|
+
// Belarusian
|
|
67
|
+
"bn",
|
|
68
|
+
// Bengali
|
|
69
|
+
"bho",
|
|
70
|
+
// Bhojpuri
|
|
71
|
+
"bs",
|
|
72
|
+
// Bosnian
|
|
73
|
+
"bg",
|
|
74
|
+
// Bulgarian
|
|
75
|
+
"ca",
|
|
76
|
+
// Catalan
|
|
77
|
+
"ceb",
|
|
78
|
+
// Cebuano
|
|
79
|
+
"ny",
|
|
80
|
+
// Chichewa
|
|
81
|
+
"zh",
|
|
82
|
+
// Chinese (Simplified) - Google uses 'zh' or 'zh-CN'
|
|
83
|
+
"zh_cn",
|
|
84
|
+
// Chinese (Simplified) - alternative format
|
|
85
|
+
"zh_tw",
|
|
86
|
+
// Chinese (Traditional)
|
|
87
|
+
"zh_hk",
|
|
88
|
+
// Chinese (Hong Kong)
|
|
89
|
+
"co",
|
|
90
|
+
// Corsican
|
|
91
|
+
"hr",
|
|
92
|
+
// Croatian
|
|
93
|
+
"cs",
|
|
94
|
+
// Czech
|
|
95
|
+
"da",
|
|
96
|
+
// Danish
|
|
97
|
+
"dv",
|
|
98
|
+
// Dhivehi
|
|
99
|
+
"doi",
|
|
100
|
+
// Dogri
|
|
101
|
+
"nl",
|
|
102
|
+
// Dutch
|
|
103
|
+
"en",
|
|
104
|
+
// English
|
|
105
|
+
"eo",
|
|
106
|
+
// Esperanto
|
|
107
|
+
"et",
|
|
108
|
+
// Estonian
|
|
109
|
+
"ee",
|
|
110
|
+
// Ewe
|
|
111
|
+
"tl",
|
|
112
|
+
// Filipino (Tagalog)
|
|
113
|
+
"fi",
|
|
114
|
+
// Finnish
|
|
115
|
+
"fr",
|
|
116
|
+
// French
|
|
117
|
+
"gl",
|
|
118
|
+
// Galician
|
|
119
|
+
"ka",
|
|
120
|
+
// Georgian
|
|
121
|
+
"de",
|
|
122
|
+
// German
|
|
123
|
+
"de_at",
|
|
124
|
+
// German (Austria)
|
|
125
|
+
"el",
|
|
126
|
+
// Greek
|
|
127
|
+
"gn",
|
|
128
|
+
// Guarani
|
|
129
|
+
"gu",
|
|
130
|
+
// Gujarati
|
|
131
|
+
"ht",
|
|
132
|
+
// Haitian Creole
|
|
133
|
+
"ha",
|
|
134
|
+
// Hausa
|
|
135
|
+
"haw",
|
|
136
|
+
// Hawaiian
|
|
137
|
+
"iw",
|
|
138
|
+
// Hebrew (legacy code, 'he' is preferred)
|
|
139
|
+
"he",
|
|
140
|
+
// Hebrew
|
|
141
|
+
"hi",
|
|
142
|
+
// Hindi
|
|
143
|
+
"hmn",
|
|
144
|
+
// Hmong
|
|
145
|
+
"hu",
|
|
146
|
+
// Hungarian
|
|
147
|
+
"is",
|
|
148
|
+
// Icelandic
|
|
149
|
+
"ig",
|
|
150
|
+
// Igbo
|
|
151
|
+
"ilo",
|
|
152
|
+
// Ilocano
|
|
153
|
+
"id",
|
|
154
|
+
// Indonesian
|
|
155
|
+
"ga",
|
|
156
|
+
// Irish
|
|
157
|
+
"it",
|
|
158
|
+
// Italian
|
|
159
|
+
"ja",
|
|
160
|
+
// Japanese
|
|
161
|
+
"jw",
|
|
162
|
+
// Javanese
|
|
163
|
+
"kn",
|
|
164
|
+
// Kannada
|
|
165
|
+
"kk",
|
|
166
|
+
// Kazakh
|
|
167
|
+
"km",
|
|
168
|
+
// Khmer
|
|
169
|
+
"rw",
|
|
170
|
+
// Kinyarwanda
|
|
171
|
+
"gom",
|
|
172
|
+
// Konkani
|
|
173
|
+
"ko",
|
|
174
|
+
// Korean
|
|
175
|
+
"kri",
|
|
176
|
+
// Krio
|
|
177
|
+
"ku",
|
|
178
|
+
// Kurdish (Kurmanji)
|
|
179
|
+
"ckb",
|
|
180
|
+
// Kurdish (Sorani)
|
|
181
|
+
"ky",
|
|
182
|
+
// Kyrgyz
|
|
183
|
+
"lo",
|
|
184
|
+
// Lao
|
|
185
|
+
"la",
|
|
186
|
+
// Latin
|
|
187
|
+
"lv",
|
|
188
|
+
// Latvian
|
|
189
|
+
"ln",
|
|
190
|
+
// Lingala
|
|
191
|
+
"lt",
|
|
192
|
+
// Lithuanian
|
|
193
|
+
"lg",
|
|
194
|
+
// Luganda
|
|
195
|
+
"lb",
|
|
196
|
+
// Luxembourgish
|
|
197
|
+
"mk",
|
|
198
|
+
// Macedonian
|
|
199
|
+
"mai",
|
|
200
|
+
// Maithili
|
|
201
|
+
"mg",
|
|
202
|
+
// Malagasy
|
|
203
|
+
"ms",
|
|
204
|
+
// Malay
|
|
205
|
+
"ml",
|
|
206
|
+
// Malayalam
|
|
207
|
+
"mt",
|
|
208
|
+
// Maltese
|
|
209
|
+
"mi",
|
|
210
|
+
// Maori
|
|
211
|
+
"mr",
|
|
212
|
+
// Marathi
|
|
213
|
+
"mni",
|
|
214
|
+
// Meiteilon (Manipuri)
|
|
215
|
+
"lus",
|
|
216
|
+
// Mizo
|
|
217
|
+
"mn",
|
|
218
|
+
// Mongolian
|
|
219
|
+
"my",
|
|
220
|
+
// Myanmar (Burmese)
|
|
221
|
+
"ne",
|
|
222
|
+
// Nepali
|
|
223
|
+
"no",
|
|
224
|
+
// Norwegian
|
|
225
|
+
"or",
|
|
226
|
+
// Odia
|
|
227
|
+
"om",
|
|
228
|
+
// Oromo
|
|
229
|
+
"ps",
|
|
230
|
+
// Pashto
|
|
231
|
+
"fa",
|
|
232
|
+
// Persian
|
|
233
|
+
"pl",
|
|
234
|
+
// Polish
|
|
235
|
+
"pt",
|
|
236
|
+
// Portuguese
|
|
237
|
+
"pt_br",
|
|
238
|
+
// Portuguese (Brazil)
|
|
239
|
+
"pa",
|
|
240
|
+
// Punjabi
|
|
241
|
+
"qu",
|
|
242
|
+
// Quechua
|
|
243
|
+
"ro",
|
|
244
|
+
// Romanian
|
|
245
|
+
"ru",
|
|
246
|
+
// Russian
|
|
247
|
+
"sm",
|
|
248
|
+
// Samoan
|
|
249
|
+
"sa",
|
|
250
|
+
// Sanskrit
|
|
251
|
+
"gd",
|
|
252
|
+
// Scottish Gaelic
|
|
253
|
+
"sr",
|
|
254
|
+
// Serbian
|
|
255
|
+
"st",
|
|
256
|
+
// Sesotho
|
|
257
|
+
"sn",
|
|
258
|
+
// Shona
|
|
259
|
+
"sd",
|
|
260
|
+
// Sindhi
|
|
261
|
+
"si",
|
|
262
|
+
// Sinhala
|
|
263
|
+
"sk",
|
|
264
|
+
// Slovak
|
|
265
|
+
"sl",
|
|
266
|
+
// Slovenian
|
|
267
|
+
"so",
|
|
268
|
+
// Somali
|
|
269
|
+
"es",
|
|
270
|
+
// Spanish
|
|
271
|
+
"su",
|
|
272
|
+
// Sundanese
|
|
273
|
+
"sw",
|
|
274
|
+
// Swahili
|
|
275
|
+
"sv",
|
|
276
|
+
// Swedish
|
|
277
|
+
"tg",
|
|
278
|
+
// Tajik
|
|
279
|
+
"ta",
|
|
280
|
+
// Tamil
|
|
281
|
+
"tt",
|
|
282
|
+
// Tatar
|
|
283
|
+
"te",
|
|
284
|
+
// Telugu
|
|
285
|
+
"th",
|
|
286
|
+
// Thai
|
|
287
|
+
"ti",
|
|
288
|
+
// Tigrinya
|
|
289
|
+
"ts",
|
|
290
|
+
// Tsonga
|
|
291
|
+
"tr",
|
|
292
|
+
// Turkish
|
|
293
|
+
"tk",
|
|
294
|
+
// Turkmen
|
|
295
|
+
"ak",
|
|
296
|
+
// Twi
|
|
297
|
+
"uk",
|
|
298
|
+
// Ukrainian
|
|
299
|
+
"ur",
|
|
300
|
+
// Urdu
|
|
301
|
+
"ug",
|
|
302
|
+
// Uyghur
|
|
303
|
+
"uz",
|
|
304
|
+
// Uzbek
|
|
305
|
+
"vi",
|
|
306
|
+
// Vietnamese
|
|
307
|
+
"cy",
|
|
308
|
+
// Welsh
|
|
309
|
+
"xh",
|
|
310
|
+
// Xhosa
|
|
311
|
+
"yi",
|
|
312
|
+
// Yiddish
|
|
313
|
+
"yo",
|
|
314
|
+
// Yoruba
|
|
315
|
+
"zu"
|
|
316
|
+
// Zulu
|
|
317
|
+
];
|
|
318
|
+
function isValidLanguage(lang) {
|
|
319
|
+
return SUPPORTED_LANGUAGES.includes(lang);
|
|
320
|
+
}
|
|
321
|
+
function validateLanguages(languages) {
|
|
322
|
+
const invalid = languages.filter((lang) => !isValidLanguage(lang));
|
|
323
|
+
return {
|
|
324
|
+
valid: invalid.length === 0,
|
|
325
|
+
invalid
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/translations/core/types.ts
|
|
330
|
+
var DEFAULT_CONFIG = {
|
|
331
|
+
translationsPath: "public/static/locales",
|
|
332
|
+
languages: ["en"],
|
|
333
|
+
sourceLanguage: "en",
|
|
334
|
+
typesOutputPath: "src/types/i18nTypes.ts"
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// src/translations/cli/init.ts
|
|
338
|
+
function detectExistingTranslations(projectRoot) {
|
|
339
|
+
const possiblePaths = ["public/static/locales", "public/locales", "src/locales", "locales", "i18n", "translations"];
|
|
340
|
+
for (const possiblePath of possiblePaths) {
|
|
341
|
+
const fullPath = path2.join(projectRoot, possiblePath);
|
|
342
|
+
if (fs2.existsSync(fullPath)) {
|
|
343
|
+
const languages = getAvailableLanguages(fullPath);
|
|
344
|
+
if (languages.length > 0) {
|
|
345
|
+
return { path: possiblePath, languages };
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return { path: null, languages: [] };
|
|
350
|
+
}
|
|
351
|
+
function loadConfig(projectRoot) {
|
|
352
|
+
const configPath = path2.join(projectRoot, ".translationsrc.json");
|
|
353
|
+
if (!fs2.existsSync(configPath)) {
|
|
354
|
+
const existing = detectExistingTranslations(projectRoot);
|
|
355
|
+
if (existing.path && existing.languages.length > 0) {
|
|
356
|
+
console.log(`\u2139\uFE0F No config found, but detected translations at ${existing.path}`);
|
|
357
|
+
return {
|
|
358
|
+
...DEFAULT_CONFIG,
|
|
359
|
+
translationsPath: existing.path,
|
|
360
|
+
languages: existing.languages
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
return DEFAULT_CONFIG;
|
|
364
|
+
}
|
|
365
|
+
const configContent = fs2.readFileSync(configPath, "utf-8");
|
|
366
|
+
const config = JSON.parse(configContent);
|
|
367
|
+
if (config.languages) {
|
|
368
|
+
const validation = validateLanguages(config.languages);
|
|
369
|
+
if (!validation.valid) {
|
|
370
|
+
console.warn(`\u26A0\uFE0F Warning: Invalid language codes in config: ${validation.invalid.join(", ")}`);
|
|
371
|
+
console.warn("Please update .translationsrc.json with valid language codes.");
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return { ...DEFAULT_CONFIG, ...config };
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/translations/cli/validate.ts
|
|
378
|
+
function validateTranslations(projectRoot = process.cwd()) {
|
|
379
|
+
const config = loadConfig(projectRoot);
|
|
380
|
+
const translationsPath = path3.join(projectRoot, config.translationsPath);
|
|
381
|
+
const sourceLanguage = config.sourceLanguage;
|
|
382
|
+
const missing = [];
|
|
383
|
+
const empty = [];
|
|
384
|
+
const sourceTranslations = readTranslations(translationsPath, sourceLanguage);
|
|
385
|
+
const sourceNamespaces = getNamespaces(translationsPath, sourceLanguage);
|
|
386
|
+
const languages = getAvailableLanguages(translationsPath).filter((lang) => lang !== sourceLanguage);
|
|
387
|
+
console.log("=====");
|
|
388
|
+
console.log("Validating translations");
|
|
389
|
+
console.log("=====");
|
|
390
|
+
console.log(`Source language: ${sourceLanguage}`);
|
|
391
|
+
console.log(`Target languages: ${languages.join(", ")}`);
|
|
392
|
+
console.log(`Namespaces: ${sourceNamespaces.join(", ")}`);
|
|
393
|
+
console.log("=====");
|
|
394
|
+
for (const language of languages) {
|
|
395
|
+
const targetTranslations = readTranslations(translationsPath, language);
|
|
396
|
+
for (const namespace of sourceNamespaces) {
|
|
397
|
+
const sourceKeys = sourceTranslations[namespace] || {};
|
|
398
|
+
const targetKeys = targetTranslations[namespace] || {};
|
|
399
|
+
for (const [key, sourceValue] of Object.entries(sourceKeys)) {
|
|
400
|
+
const targetValue = targetKeys[key];
|
|
401
|
+
if (targetValue === void 0) {
|
|
402
|
+
missing.push({
|
|
403
|
+
namespace,
|
|
404
|
+
key,
|
|
405
|
+
language,
|
|
406
|
+
sourceValue
|
|
407
|
+
});
|
|
408
|
+
} else if (typeof targetValue === "string" && targetValue.trim() === "") {
|
|
409
|
+
empty.push({
|
|
410
|
+
namespace,
|
|
411
|
+
key,
|
|
412
|
+
language,
|
|
413
|
+
sourceValue
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const valid = missing.length === 0 && empty.length === 0;
|
|
420
|
+
if (valid) {
|
|
421
|
+
console.log("\u2713 All translations are valid!");
|
|
422
|
+
} else {
|
|
423
|
+
if (missing.length > 0) {
|
|
424
|
+
console.log(`
|
|
425
|
+
\u26A0 Found ${missing.length} missing translations:`);
|
|
426
|
+
for (const item of missing.slice(0, 10)) {
|
|
427
|
+
console.log(` ${item.language}/${item.namespace}.json -> ${item.key}`);
|
|
428
|
+
}
|
|
429
|
+
if (missing.length > 10) {
|
|
430
|
+
console.log(` ... and ${missing.length - 10} more`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (empty.length > 0) {
|
|
434
|
+
console.log(`
|
|
435
|
+
\u26A0 Found ${empty.length} empty translations:`);
|
|
436
|
+
for (const item of empty.slice(0, 10)) {
|
|
437
|
+
console.log(` ${item.language}/${item.namespace}.json -> ${item.key}`);
|
|
438
|
+
}
|
|
439
|
+
if (empty.length > 10) {
|
|
440
|
+
console.log(` ... and ${empty.length - 10} more`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
console.log("=====");
|
|
445
|
+
return { valid, missing, empty };
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// src/scripts/verify-translations.ts
|
|
449
|
+
function verifyTranslations() {
|
|
450
|
+
const projectRoot = process.cwd();
|
|
451
|
+
try {
|
|
452
|
+
const result = validateTranslations(projectRoot);
|
|
453
|
+
if (!result.valid) {
|
|
454
|
+
console.error("\n\u274C Translation verification failed!");
|
|
455
|
+
console.error(
|
|
456
|
+
`Found ${result.missing.length} missing translations and ${result.empty.length} empty translations.`
|
|
457
|
+
);
|
|
458
|
+
console.error("Please fix these issues before proceeding.\n");
|
|
459
|
+
process.exit(1);
|
|
460
|
+
}
|
|
461
|
+
console.log("\n\u2705 All translations verified successfully!");
|
|
462
|
+
process.exit(0);
|
|
463
|
+
} catch (error) {
|
|
464
|
+
console.error("\n\u274C Error during translation verification:");
|
|
465
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
466
|
+
process.exit(1);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
verifyTranslations();
|
|
470
|
+
//# sourceMappingURL=verify-translations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/translations/cli/validate.ts","../../src/translations/utils/utils.ts","../../src/translations/cli/init.ts","../../src/translations/core/schema.ts","../../src/translations/core/types.ts","../../src/scripts/verify-translations.ts"],"sourcesContent":["import * as path from 'node:path';\nimport type { MissingTranslation, ValidationResult } from '../core/types.js';\nimport { getAvailableLanguages, getNamespaces, readTranslations } from '../utils/utils.js';\nimport { loadConfig } from './init.js';\n\n/**\n * Validate all translations against the source language\n * Checks for missing keys and empty values\n */\nexport function validateTranslations(projectRoot: string = process.cwd()): ValidationResult {\n const config = loadConfig(projectRoot);\n const translationsPath = path.join(projectRoot, config.translationsPath);\n const sourceLanguage = config.sourceLanguage;\n\n const missing: MissingTranslation[] = [];\n const empty: MissingTranslation[] = [];\n\n // Read source translations\n const sourceTranslations = readTranslations(translationsPath, sourceLanguage);\n const sourceNamespaces = getNamespaces(translationsPath, sourceLanguage);\n\n // Get all available languages\n const languages = getAvailableLanguages(translationsPath).filter((lang) => lang !== sourceLanguage);\n\n console.log('=====');\n console.log('Validating translations');\n console.log('=====');\n console.log(`Source language: ${sourceLanguage}`);\n console.log(`Target languages: ${languages.join(', ')}`);\n console.log(`Namespaces: ${sourceNamespaces.join(', ')}`);\n console.log('=====');\n\n // Validate each language\n for (const language of languages) {\n const targetTranslations = readTranslations(translationsPath, language);\n\n // Check each namespace\n for (const namespace of sourceNamespaces) {\n const sourceKeys = sourceTranslations[namespace] || {};\n const targetKeys = targetTranslations[namespace] || {};\n\n // Check for missing or empty translations\n for (const [key, sourceValue] of Object.entries(sourceKeys)) {\n const targetValue = targetKeys[key];\n\n // Missing key in target language\n if (targetValue === undefined) {\n missing.push({\n namespace,\n key,\n language,\n sourceValue\n });\n }\n // Empty value in target language\n else if (typeof targetValue === 'string' && targetValue.trim() === '') {\n empty.push({\n namespace,\n key,\n language,\n sourceValue\n });\n }\n }\n }\n }\n\n const valid = missing.length === 0 && empty.length === 0;\n\n if (valid) {\n console.log('✓ All translations are valid!');\n } else {\n if (missing.length > 0) {\n console.log(`\\n⚠ Found ${missing.length} missing translations:`);\n for (const item of missing.slice(0, 10)) {\n console.log(` ${item.language}/${item.namespace}.json -> ${item.key}`);\n }\n if (missing.length > 10) {\n console.log(` ... and ${missing.length - 10} more`);\n }\n }\n\n if (empty.length > 0) {\n console.log(`\\n⚠ Found ${empty.length} empty translations:`);\n for (const item of empty.slice(0, 10)) {\n console.log(` ${item.language}/${item.namespace}.json -> ${item.key}`);\n }\n if (empty.length > 10) {\n console.log(` ... and ${empty.length - 10} more`);\n }\n }\n }\n\n console.log('=====');\n\n return { valid, missing, empty };\n}\n\n/**\n * Get all missing or empty translations for a specific language\n */\nexport function getMissingForLanguage(\n projectRoot: string,\n language: string\n): Array<MissingTranslation & { type: 'missing' | 'empty' }> {\n const result = validateTranslations(projectRoot);\n const items = [\n ...result.missing.filter((m) => m.language === language).map((m) => ({ ...m, type: 'missing' as const })),\n ...result.empty.filter((e) => e.language === language).map((e) => ({ ...e, type: 'empty' as const }))\n ];\n\n return items;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { TranslationFile, TranslationFiles } from '../core/types.js';\n\n/**\n * Read all translation files for a specific language\n */\nexport function readTranslations(translationsPath: string, language: string): TranslationFiles {\n const langPath = path.join(translationsPath, language);\n\n if (!fs.existsSync(langPath)) {\n return {};\n }\n\n const files = fs.readdirSync(langPath).filter((f) => f.endsWith('.json'));\n const translations: TranslationFiles = {};\n\n for (const file of files) {\n const namespace = path.basename(file, '.json');\n const filePath = path.join(langPath, file);\n const content = fs.readFileSync(filePath, 'utf-8');\n translations[namespace] = JSON.parse(content) as TranslationFile;\n }\n\n return translations;\n}\n\n/**\n * Write translation file for a specific language and namespace\n */\nexport function writeTranslation(\n translationsPath: string,\n language: string,\n namespace: string,\n translations: TranslationFile\n): void {\n const langPath = path.join(translationsPath, language);\n\n if (!fs.existsSync(langPath)) {\n fs.mkdirSync(langPath, { recursive: true });\n }\n\n const filePath = path.join(langPath, `${namespace}.json`);\n fs.writeFileSync(filePath, `${JSON.stringify(translations, null, 2)}\\n`, 'utf-8');\n}\n\n/**\n * Get all available languages from the translations directory\n */\nexport function getAvailableLanguages(translationsPath: string): string[] {\n if (!fs.existsSync(translationsPath)) {\n return [];\n }\n\n return fs\n .readdirSync(translationsPath, { withFileTypes: true })\n .filter((dirent) => dirent.isDirectory())\n .map((dirent) => dirent.name);\n}\n\n/**\n * Get all namespaces for a specific language\n */\nexport function getNamespaces(translationsPath: string, language: string): string[] {\n const langPath = path.join(translationsPath, language);\n\n if (!fs.existsSync(langPath)) {\n return [];\n }\n\n return fs\n .readdirSync(langPath)\n .filter((f) => f.endsWith('.json'))\n .map((f) => path.basename(f, '.json'));\n}\n\n/**\n * Check if a string contains interpolation variables (e.g., {{variable}})\n */\nexport function hasInterpolation(text: string): boolean {\n return /\\{\\{[^}]+\\}\\}/g.test(text);\n}\n\n/**\n * Extract interpolation variable names from a string\n */\nexport function extractVariables(text: string): string[] {\n const matches = text.match(/\\{\\{([^}]+)\\}\\}/g);\n if (!matches) return [];\n return matches.map((match) => match.replace(/\\{\\{|\\}\\}/g, '').trim());\n}\n\n/**\n * Validate that translated text has the same variables as source text\n */\nexport function validateVariables(sourceText: string, translatedText: string): boolean {\n const sourceVars = extractVariables(sourceText).sort();\n const translatedVars = extractVariables(translatedText).sort();\n\n if (sourceVars.length !== translatedVars.length) {\n return false;\n }\n\n return sourceVars.every((v, i) => v === translatedVars[i]);\n}\n\n/**\n * Sort object keys alphabetically\n */\nexport function sortKeys<T extends Record<string, unknown>>(obj: T): T {\n const sorted = {} as T;\n const keys = Object.keys(obj).sort();\n for (const key of keys) {\n sorted[key as keyof T] = obj[key as keyof T];\n }\n return sorted;\n}\n\n/**\n * Ensure translations path exists and has proper structure\n */\nexport function ensureTranslationsStructure(translationsPath: string, languages: string[]): void {\n if (!fs.existsSync(translationsPath)) {\n fs.mkdirSync(translationsPath, { recursive: true });\n }\n\n for (const lang of languages) {\n const langPath = path.join(translationsPath, lang);\n if (!fs.existsSync(langPath)) {\n fs.mkdirSync(langPath, { recursive: true });\n }\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { validateLanguages } from '../core/schema.js';\nimport type { TranslationConfig } from '../core/types.js';\nimport { DEFAULT_CONFIG, DEFAULT_LANGUAGES } from '../core/types.js';\nimport { ensureTranslationsStructure, getAvailableLanguages } from '../utils/utils.js';\n\n/**\n * Detect existing translation structure in common locations\n */\nexport function detectExistingTranslations(projectRoot: string): {\n path: string | null;\n languages: string[];\n} {\n const possiblePaths = ['public/static/locales', 'public/locales', 'src/locales', 'locales', 'i18n', 'translations'];\n\n for (const possiblePath of possiblePaths) {\n const fullPath = path.join(projectRoot, possiblePath);\n if (fs.existsSync(fullPath)) {\n const languages = getAvailableLanguages(fullPath);\n if (languages.length > 0) {\n return { path: possiblePath, languages };\n }\n }\n }\n\n return { path: null, languages: [] };\n}\n\n/**\n * Initialize translation structure for a project\n */\nexport function initTranslations(projectRoot: string, config: TranslationConfig = {}): void {\n console.log('=====');\n console.log('Initializing translation structure');\n console.log('=====');\n\n // Detect existing translations\n const existing = detectExistingTranslations(projectRoot);\n\n let finalConfig = { ...DEFAULT_CONFIG, ...config };\n\n // Use detected path and languages if found\n if (existing.path && existing.languages.length > 0) {\n console.log(`✓ Detected existing translations at: ${existing.path}`);\n console.log(`✓ Found languages: ${existing.languages.join(', ')}`);\n\n // Validate detected languages\n const validation = validateLanguages(existing.languages);\n if (!validation.valid) {\n console.log(`⚠️ Warning: Invalid language codes found: ${validation.invalid.join(', ')}`);\n console.log('These languages will be skipped.');\n }\n\n const validLanguages = existing.languages.filter((lang) => !validation.invalid.includes(lang));\n\n finalConfig = {\n ...finalConfig,\n translationsPath: existing.path,\n languages: validLanguages.length > 0 ? validLanguages : finalConfig.languages\n };\n }\n\n const translationsPath = path.join(projectRoot, finalConfig.translationsPath);\n const languages = finalConfig.languages.length > 0 ? finalConfig.languages : [...DEFAULT_LANGUAGES];\n\n console.log(`Project root: ${projectRoot}`);\n console.log(`Translations path: ${translationsPath}`);\n console.log(`Languages: ${languages.join(', ')}`);\n console.log('=====');\n\n // Validate languages\n const validation = validateLanguages(languages);\n if (!validation.valid) {\n throw new Error(`Invalid language codes: ${validation.invalid.join(', ')}`);\n }\n\n // Create directory structure\n ensureTranslationsStructure(translationsPath, languages);\n\n // Create sample translation files for English (source language)\n const sourceLanguage = finalConfig.sourceLanguage;\n const sourcePath = path.join(translationsPath, sourceLanguage);\n\n // Create a sample common.json if it doesn't exist\n const commonPath = path.join(sourcePath, 'common.json');\n if (!fs.existsSync(commonPath)) {\n const sampleTranslations = {\n LOADING: 'Loading',\n SAVE: 'Save',\n CANCEL: 'Cancel',\n SUBMIT: 'Submit',\n ERROR: 'Error',\n SUCCESS: 'Success'\n };\n\n fs.writeFileSync(commonPath, `${JSON.stringify(sampleTranslations, null, 2)}\\n`, 'utf-8');\n console.log(`Created sample file: ${commonPath}`);\n }\n\n // Create empty translation files for other languages\n for (const lang of languages) {\n if (lang === sourceLanguage) continue;\n\n const langCommonPath = path.join(translationsPath, lang, 'common.json');\n if (!fs.existsSync(langCommonPath)) {\n fs.writeFileSync(langCommonPath, '{}\\n', 'utf-8');\n console.log(`Created empty file: ${langCommonPath}`);\n }\n }\n\n // Create config file with schema reference\n const configPath = path.join(projectRoot, '.translationsrc.json');\n if (!fs.existsSync(configPath)) {\n const configContent = {\n $schema: './node_modules/@repo/env-scripts/dist/translations/core/translations-config.schema.json',\n translationsPath: finalConfig.translationsPath,\n languages,\n sourceLanguage,\n typesOutputPath: finalConfig.typesOutputPath\n };\n\n fs.writeFileSync(configPath, `${JSON.stringify(configContent, null, 2)}\\n`, 'utf-8');\n console.log(`Created config file: ${configPath}`);\n }\n\n console.log('=====');\n console.log('Translation structure initialized successfully!');\n console.log('=====');\n}\n\n/**\n * Load translation configuration from .translationsrc.json\n */\nexport function loadConfig(projectRoot: string): Required<TranslationConfig> {\n const configPath = path.join(projectRoot, '.translationsrc.json');\n\n if (!fs.existsSync(configPath)) {\n // Try to detect existing translations\n const existing = detectExistingTranslations(projectRoot);\n if (existing.path && existing.languages.length > 0) {\n console.log(`ℹ️ No config found, but detected translations at ${existing.path}`);\n return {\n ...DEFAULT_CONFIG,\n translationsPath: existing.path,\n languages: existing.languages\n };\n }\n return DEFAULT_CONFIG;\n }\n\n const configContent = fs.readFileSync(configPath, 'utf-8');\n const config = JSON.parse(configContent) as TranslationConfig;\n\n // Validate languages in config\n if (config.languages) {\n const validation = validateLanguages(config.languages);\n if (!validation.valid) {\n console.warn(`⚠️ Warning: Invalid language codes in config: ${validation.invalid.join(', ')}`);\n console.warn('Please update .translationsrc.json with valid language codes.');\n }\n }\n\n return { ...DEFAULT_CONFIG, ...config };\n}\n","/**\n * Supported language codes for translations\n * Based on Google Translate API supported languages (ISO 639-1 and regional variants)\n * Complete list of all languages supported by Google Cloud Translation API\n */\nexport const SUPPORTED_LANGUAGES = [\n 'af', // Afrikaans\n 'sq', // Albanian\n 'am', // Amharic\n 'ar', // Arabic\n 'hy', // Armenian\n 'as', // Assamese\n 'ay', // Aymara\n 'az', // Azerbaijani\n 'bm', // Bambara\n 'eu', // Basque\n 'be', // Belarusian\n 'bn', // Bengali\n 'bho', // Bhojpuri\n 'bs', // Bosnian\n 'bg', // Bulgarian\n 'ca', // Catalan\n 'ceb', // Cebuano\n 'ny', // Chichewa\n 'zh', // Chinese (Simplified) - Google uses 'zh' or 'zh-CN'\n 'zh_cn', // Chinese (Simplified) - alternative format\n 'zh_tw', // Chinese (Traditional)\n 'zh_hk', // Chinese (Hong Kong)\n 'co', // Corsican\n 'hr', // Croatian\n 'cs', // Czech\n 'da', // Danish\n 'dv', // Dhivehi\n 'doi', // Dogri\n 'nl', // Dutch\n 'en', // English\n 'eo', // Esperanto\n 'et', // Estonian\n 'ee', // Ewe\n 'tl', // Filipino (Tagalog)\n 'fi', // Finnish\n 'fr', // French\n 'gl', // Galician\n 'ka', // Georgian\n 'de', // German\n 'de_at', // German (Austria)\n 'el', // Greek\n 'gn', // Guarani\n 'gu', // Gujarati\n 'ht', // Haitian Creole\n 'ha', // Hausa\n 'haw', // Hawaiian\n 'iw', // Hebrew (legacy code, 'he' is preferred)\n 'he', // Hebrew\n 'hi', // Hindi\n 'hmn', // Hmong\n 'hu', // Hungarian\n 'is', // Icelandic\n 'ig', // Igbo\n 'ilo', // Ilocano\n 'id', // Indonesian\n 'ga', // Irish\n 'it', // Italian\n 'ja', // Japanese\n 'jw', // Javanese\n 'kn', // Kannada\n 'kk', // Kazakh\n 'km', // Khmer\n 'rw', // Kinyarwanda\n 'gom', // Konkani\n 'ko', // Korean\n 'kri', // Krio\n 'ku', // Kurdish (Kurmanji)\n 'ckb', // Kurdish (Sorani)\n 'ky', // Kyrgyz\n 'lo', // Lao\n 'la', // Latin\n 'lv', // Latvian\n 'ln', // Lingala\n 'lt', // Lithuanian\n 'lg', // Luganda\n 'lb', // Luxembourgish\n 'mk', // Macedonian\n 'mai', // Maithili\n 'mg', // Malagasy\n 'ms', // Malay\n 'ml', // Malayalam\n 'mt', // Maltese\n 'mi', // Maori\n 'mr', // Marathi\n 'mni', // Meiteilon (Manipuri)\n 'lus', // Mizo\n 'mn', // Mongolian\n 'my', // Myanmar (Burmese)\n 'ne', // Nepali\n 'no', // Norwegian\n 'or', // Odia\n 'om', // Oromo\n 'ps', // Pashto\n 'fa', // Persian\n 'pl', // Polish\n 'pt', // Portuguese\n 'pt_br', // Portuguese (Brazil)\n 'pa', // Punjabi\n 'qu', // Quechua\n 'ro', // Romanian\n 'ru', // Russian\n 'sm', // Samoan\n 'sa', // Sanskrit\n 'gd', // Scottish Gaelic\n 'sr', // Serbian\n 'st', // Sesotho\n 'sn', // Shona\n 'sd', // Sindhi\n 'si', // Sinhala\n 'sk', // Slovak\n 'sl', // Slovenian\n 'so', // Somali\n 'es', // Spanish\n 'su', // Sundanese\n 'sw', // Swahili\n 'sv', // Swedish\n 'tg', // Tajik\n 'ta', // Tamil\n 'tt', // Tatar\n 'te', // Telugu\n 'th', // Thai\n 'ti', // Tigrinya\n 'ts', // Tsonga\n 'tr', // Turkish\n 'tk', // Turkmen\n 'ak', // Twi\n 'uk', // Ukrainian\n 'ur', // Urdu\n 'ug', // Uyghur\n 'uz', // Uzbek\n 'vi', // Vietnamese\n 'cy', // Welsh\n 'xh', // Xhosa\n 'yi', // Yiddish\n 'yo', // Yoruba\n 'zu' // Zulu\n] as const;\n\nexport type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];\n\n/**\n * JSON Schema for .translationsrc.json\n */\nexport const TRANSLATION_CONFIG_SCHEMA = {\n $schema: 'http://json-schema.org/draft-07/schema#',\n title: 'Translation Configuration',\n description: 'Configuration for the translation management system',\n type: 'object',\n properties: {\n translationsPath: {\n type: 'string',\n description: 'Path to the translations directory relative to project root',\n default: 'public/static/locales'\n },\n languages: {\n type: 'array',\n description: 'List of language codes to support',\n items: {\n type: 'string',\n enum: SUPPORTED_LANGUAGES\n },\n minItems: 1,\n uniqueItems: true\n },\n sourceLanguage: {\n type: 'string',\n description: 'Source language for translations (usually \"en\")',\n enum: SUPPORTED_LANGUAGES,\n default: 'en'\n },\n typesOutputPath: {\n type: 'string',\n description: 'Path to output TypeScript types file',\n default: 'src/types/i18nTypes.ts'\n }\n },\n required: ['translationsPath', 'languages', 'sourceLanguage'],\n additionalProperties: false\n};\n\n/**\n * Validate if a language code is supported\n */\nexport function isValidLanguage(lang: string): lang is SupportedLanguage {\n return SUPPORTED_LANGUAGES.includes(lang as SupportedLanguage);\n}\n\n/**\n * Validate languages array\n */\nexport function validateLanguages(languages: string[]): {\n valid: boolean;\n invalid: string[];\n} {\n const invalid = languages.filter((lang) => !isValidLanguage(lang));\n return {\n valid: invalid.length === 0,\n invalid\n };\n}\n","export interface TranslationConfig {\n /** Path to the translations directory (default: public/static/locales) */\n translationsPath?: string;\n /** Languages to support (default: ['en']) */\n languages?: string[];\n /** Source language for translations (default: 'en') */\n sourceLanguage?: string;\n /** Path to output i18n types (default: src/types/i18nTypes.ts) */\n typesOutputPath?: string;\n}\n\nexport interface TranslationEntry {\n namespace: string;\n key: string;\n value: string;\n}\n\nexport interface TranslationFile {\n [key: string]: string;\n}\n\nexport interface TranslationFiles {\n [namespace: string]: TranslationFile;\n}\n\nexport interface MissingTranslation {\n namespace: string;\n key: string;\n language: string;\n sourceValue: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n missing: MissingTranslation[];\n empty: MissingTranslation[];\n}\n\nexport const DEFAULT_CONFIG: Required<TranslationConfig> = {\n translationsPath: 'public/static/locales',\n languages: ['en'],\n sourceLanguage: 'en',\n typesOutputPath: 'src/types/i18nTypes.ts'\n};\n\nexport const DEFAULT_LANGUAGES = [\n 'en',\n 'fr',\n 'it',\n 'pl',\n 'es',\n 'pt',\n 'de',\n 'de_at',\n 'nl',\n 'sv',\n 'hu',\n 'cs',\n 'ja',\n 'zh_hk'\n] as const;\n","#!/usr/bin/env node\nimport { validateTranslations } from '../translations/cli/validate.js';\n\n/**\n * Script to verify that all translations have no missing keys\n * Exits with error code 1 if there are any missing or empty translations\n * This is useful for CI/CD pipelines to ensure translation completeness\n */\nfunction verifyTranslations(): void {\n const projectRoot = process.cwd();\n\n try {\n const result = validateTranslations(projectRoot);\n\n if (!result.valid) {\n console.error('\\n❌ Translation verification failed!');\n console.error(\n `Found ${result.missing.length} missing translations and ${result.empty.length} empty translations.`\n );\n console.error('Please fix these issues before proceeding.\\n');\n process.exit(1);\n }\n\n console.log('\\n✅ All translations verified successfully!');\n process.exit(0);\n } catch (error) {\n console.error('\\n❌ Error during translation verification:');\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n}\n\nverifyTranslations();\n"],"mappings":";;;;AAAA,YAAYA,WAAU;;;ACAtB,YAAY,QAAQ;AACpB,YAAY,UAAU;AAMf,SAAS,iBAAiB,kBAA0B,UAAoC;AAC7F,QAAM,WAAgB,UAAK,kBAAkB,QAAQ;AAErD,MAAI,CAAI,cAAW,QAAQ,GAAG;AAC5B,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,QAAW,eAAY,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC;AACxE,QAAM,eAAiC,CAAC;AAExC,aAAW,QAAQ,OAAO;AACxB,UAAM,YAAiB,cAAS,MAAM,OAAO;AAC7C,UAAM,WAAgB,UAAK,UAAU,IAAI;AACzC,UAAM,UAAa,gBAAa,UAAU,OAAO;AACjD,iBAAa,SAAS,IAAI,KAAK,MAAM,OAAO;AAAA,EAC9C;AAEA,SAAO;AACT;AAwBO,SAAS,sBAAsB,kBAAoC;AACxE,MAAI,CAAI,cAAW,gBAAgB,GAAG;AACpC,WAAO,CAAC;AAAA,EACV;AAEA,SACG,eAAY,kBAAkB,EAAE,eAAe,KAAK,CAAC,EACrD,OAAO,CAAC,WAAW,OAAO,YAAY,CAAC,EACvC,IAAI,CAAC,WAAW,OAAO,IAAI;AAChC;AAKO,SAAS,cAAc,kBAA0B,UAA4B;AAClF,QAAM,WAAgB,UAAK,kBAAkB,QAAQ;AAErD,MAAI,CAAI,cAAW,QAAQ,GAAG;AAC5B,WAAO,CAAC;AAAA,EACV;AAEA,SACG,eAAY,QAAQ,EACpB,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC,EACjC,IAAI,CAAC,MAAW,cAAS,GAAG,OAAO,CAAC;AACzC;;;AC1EA,YAAYC,SAAQ;AACpB,YAAYC,WAAU;;;ACIf,IAAM,sBAAsB;AAAA,EACjC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,E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","names":["path","fs","path"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poly-lexis",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A powerful CLI and library for managing i18n translations with validation, auto-translation, and TypeScript type generation",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"lint": "biome check",
|
|
27
27
|
"format": "biome format --write .",
|
|
28
28
|
"check-types": "tsc --noEmit",
|
|
29
|
+
"verify-translations": "node dist/scripts/verify-translations.js",
|
|
29
30
|
"changeset": "changeset",
|
|
30
31
|
"version": "changeset version",
|
|
31
32
|
"release": "npm run build && changeset publish"
|