poly-lexis 0.2.1 → 0.3.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.
@@ -0,0 +1,505 @@
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 DEEPL_LANGUAGES = [
45
+ "ar",
46
+ // Arabic
47
+ "bg",
48
+ // Bulgarian
49
+ "cs",
50
+ // Czech
51
+ "da",
52
+ // Danish
53
+ "de",
54
+ // German
55
+ "el",
56
+ // Greek
57
+ "en",
58
+ // English (unspecified)
59
+ "en_gb",
60
+ // English (British)
61
+ "en_us",
62
+ // English (American)
63
+ "es",
64
+ // Spanish
65
+ "es_419",
66
+ // Spanish (Latin American)
67
+ "et",
68
+ // Estonian
69
+ "fi",
70
+ // Finnish
71
+ "fr",
72
+ // French
73
+ "he",
74
+ // Hebrew (next-gen models only)
75
+ "hu",
76
+ // Hungarian
77
+ "id",
78
+ // Indonesian
79
+ "it",
80
+ // Italian
81
+ "ja",
82
+ // Japanese
83
+ "ko",
84
+ // Korean
85
+ "lt",
86
+ // Lithuanian
87
+ "lv",
88
+ // Latvian
89
+ "nb",
90
+ // Norwegian Bokmål
91
+ "nl",
92
+ // Dutch
93
+ "pl",
94
+ // Polish
95
+ "pt",
96
+ // Portuguese (unspecified)
97
+ "pt_br",
98
+ // Portuguese (Brazilian)
99
+ "pt_pt",
100
+ // Portuguese (excluding Brazilian)
101
+ "ro",
102
+ // Romanian
103
+ "ru",
104
+ // Russian
105
+ "sk",
106
+ // Slovak
107
+ "sl",
108
+ // Slovenian
109
+ "sv",
110
+ // Swedish
111
+ "th",
112
+ // Thai (next-gen models only)
113
+ "tr",
114
+ // Turkish
115
+ "uk",
116
+ // Ukrainian
117
+ "vi",
118
+ // Vietnamese (next-gen models only)
119
+ "zh",
120
+ // Chinese (unspecified)
121
+ "zh_hans",
122
+ // Chinese (simplified)
123
+ "zh_hant"
124
+ // Chinese (traditional)
125
+ ];
126
+ var GOOGLE_LANGUAGES = [
127
+ "af",
128
+ // Afrikaans
129
+ "sq",
130
+ // Albanian
131
+ "am",
132
+ // Amharic
133
+ "ar",
134
+ // Arabic
135
+ "hy",
136
+ // Armenian
137
+ "az",
138
+ // Azerbaijani
139
+ "eu",
140
+ // Basque
141
+ "be",
142
+ // Belarusian
143
+ "bn",
144
+ // Bengali
145
+ "bs",
146
+ // Bosnian
147
+ "bg",
148
+ // Bulgarian
149
+ "ca",
150
+ // Catalan
151
+ "ceb",
152
+ // Cebuano
153
+ "zh",
154
+ // Chinese (Simplified)
155
+ "zh_cn",
156
+ // Chinese (Simplified)
157
+ "zh_tw",
158
+ // Chinese (Traditional)
159
+ "co",
160
+ // Corsican
161
+ "hr",
162
+ // Croatian
163
+ "cs",
164
+ // Czech
165
+ "da",
166
+ // Danish
167
+ "nl",
168
+ // Dutch
169
+ "en",
170
+ // English
171
+ "eo",
172
+ // Esperanto
173
+ "et",
174
+ // Estonian
175
+ "fi",
176
+ // Finnish
177
+ "fr",
178
+ // French
179
+ "fy",
180
+ // Frisian
181
+ "gl",
182
+ // Galician
183
+ "ka",
184
+ // Georgian
185
+ "de",
186
+ // German
187
+ "el",
188
+ // Greek
189
+ "gu",
190
+ // Gujarati
191
+ "ht",
192
+ // Haitian Creole
193
+ "ha",
194
+ // Hausa
195
+ "haw",
196
+ // Hawaiian
197
+ "he",
198
+ // Hebrew
199
+ "hi",
200
+ // Hindi
201
+ "hmn",
202
+ // Hmong
203
+ "hu",
204
+ // Hungarian
205
+ "is",
206
+ // Icelandic
207
+ "ig",
208
+ // Igbo
209
+ "id",
210
+ // Indonesian
211
+ "ga",
212
+ // Irish
213
+ "it",
214
+ // Italian
215
+ "ja",
216
+ // Japanese
217
+ "jv",
218
+ // Javanese
219
+ "kn",
220
+ // Kannada
221
+ "kk",
222
+ // Kazakh
223
+ "km",
224
+ // Khmer
225
+ "rw",
226
+ // Kinyarwanda
227
+ "ko",
228
+ // Korean
229
+ "ku",
230
+ // Kurdish
231
+ "ky",
232
+ // Kyrgyz
233
+ "lo",
234
+ // Lao
235
+ "la",
236
+ // Latin
237
+ "lv",
238
+ // Latvian
239
+ "lt",
240
+ // Lithuanian
241
+ "lb",
242
+ // Luxembourgish
243
+ "mk",
244
+ // Macedonian
245
+ "mg",
246
+ // Malagasy
247
+ "ms",
248
+ // Malay
249
+ "ml",
250
+ // Malayalam
251
+ "mt",
252
+ // Maltese
253
+ "mi",
254
+ // Maori
255
+ "mr",
256
+ // Marathi
257
+ "mn",
258
+ // Mongolian
259
+ "my",
260
+ // Myanmar (Burmese)
261
+ "ne",
262
+ // Nepali
263
+ "no",
264
+ // Norwegian
265
+ "ny",
266
+ // Nyanja (Chichewa)
267
+ "or",
268
+ // Odia (Oriya)
269
+ "ps",
270
+ // Pashto
271
+ "fa",
272
+ // Persian
273
+ "pl",
274
+ // Polish
275
+ "pt",
276
+ // Portuguese
277
+ "pt_br",
278
+ // Portuguese (Brazil)
279
+ "pa",
280
+ // Punjabi
281
+ "ro",
282
+ // Romanian
283
+ "ru",
284
+ // Russian
285
+ "sm",
286
+ // Samoan
287
+ "gd",
288
+ // Scots Gaelic
289
+ "sr",
290
+ // Serbian
291
+ "st",
292
+ // Sesotho
293
+ "sn",
294
+ // Shona
295
+ "sd",
296
+ // Sindhi
297
+ "si",
298
+ // Sinhala (Sinhalese)
299
+ "sk",
300
+ // Slovak
301
+ "sl",
302
+ // Slovenian
303
+ "so",
304
+ // Somali
305
+ "es",
306
+ // Spanish
307
+ "su",
308
+ // Sundanese
309
+ "sw",
310
+ // Swahili
311
+ "sv",
312
+ // Swedish
313
+ "tl",
314
+ // Tagalog (Filipino)
315
+ "tg",
316
+ // Tajik
317
+ "ta",
318
+ // Tamil
319
+ "tt",
320
+ // Tatar
321
+ "te",
322
+ // Telugu
323
+ "th",
324
+ // Thai
325
+ "tr",
326
+ // Turkish
327
+ "tk",
328
+ // Turkmen
329
+ "uk",
330
+ // Ukrainian
331
+ "ur",
332
+ // Urdu
333
+ "ug",
334
+ // Uyghur
335
+ "uz",
336
+ // Uzbek
337
+ "vi",
338
+ // Vietnamese
339
+ "cy",
340
+ // Welsh
341
+ "xh",
342
+ // Xhosa
343
+ "yi",
344
+ // Yiddish
345
+ "yo",
346
+ // Yoruba
347
+ "zu"
348
+ // Zulu
349
+ ];
350
+ var SUPPORTED_LANGUAGES = Array.from(
351
+ /* @__PURE__ */ new Set([...DEEPL_LANGUAGES, ...GOOGLE_LANGUAGES])
352
+ ).sort();
353
+ function isValidLanguage(lang) {
354
+ return SUPPORTED_LANGUAGES.includes(lang);
355
+ }
356
+ function validateLanguages(languages) {
357
+ const invalid = languages.filter((lang) => !isValidLanguage(lang));
358
+ return {
359
+ valid: invalid.length === 0,
360
+ invalid
361
+ };
362
+ }
363
+
364
+ // src/translations/core/types.ts
365
+ var DEFAULT_CONFIG = {
366
+ translationsPath: "public/static/locales",
367
+ languages: ["en"],
368
+ sourceLanguage: "en",
369
+ typesOutputPath: "src/types/i18nTypes.ts"
370
+ };
371
+
372
+ // src/translations/cli/init.ts
373
+ function detectExistingTranslations(projectRoot) {
374
+ const possiblePaths = ["public/static/locales", "public/locales", "src/locales", "locales", "i18n", "translations"];
375
+ for (const possiblePath of possiblePaths) {
376
+ const fullPath = path2.join(projectRoot, possiblePath);
377
+ if (fs2.existsSync(fullPath)) {
378
+ const languages = getAvailableLanguages(fullPath);
379
+ if (languages.length > 0) {
380
+ return { path: possiblePath, languages };
381
+ }
382
+ }
383
+ }
384
+ return { path: null, languages: [] };
385
+ }
386
+ function loadConfig(projectRoot) {
387
+ const configPath = path2.join(projectRoot, ".translationsrc.json");
388
+ if (!fs2.existsSync(configPath)) {
389
+ const existing = detectExistingTranslations(projectRoot);
390
+ if (existing.path && existing.languages.length > 0) {
391
+ console.log(`\u2139\uFE0F No config found, but detected translations at ${existing.path}`);
392
+ return {
393
+ ...DEFAULT_CONFIG,
394
+ translationsPath: existing.path,
395
+ languages: existing.languages
396
+ };
397
+ }
398
+ return DEFAULT_CONFIG;
399
+ }
400
+ const configContent = fs2.readFileSync(configPath, "utf-8");
401
+ const config = JSON.parse(configContent);
402
+ if (config.languages) {
403
+ const validation = validateLanguages(config.languages);
404
+ if (!validation.valid) {
405
+ console.warn(`\u26A0\uFE0F Warning: Invalid language codes in config: ${validation.invalid.join(", ")}`);
406
+ console.warn("Please update .translationsrc.json with valid language codes.");
407
+ }
408
+ }
409
+ return { ...DEFAULT_CONFIG, ...config };
410
+ }
411
+
412
+ // src/translations/cli/validate.ts
413
+ function validateTranslations(projectRoot = process.cwd()) {
414
+ const config = loadConfig(projectRoot);
415
+ const translationsPath = path3.join(projectRoot, config.translationsPath);
416
+ const sourceLanguage = config.sourceLanguage;
417
+ const missing = [];
418
+ const empty = [];
419
+ const sourceTranslations = readTranslations(translationsPath, sourceLanguage);
420
+ const sourceNamespaces = getNamespaces(translationsPath, sourceLanguage);
421
+ const languages = getAvailableLanguages(translationsPath).filter((lang) => lang !== sourceLanguage);
422
+ console.log("=====");
423
+ console.log("Validating translations");
424
+ console.log("=====");
425
+ console.log(`Source language: ${sourceLanguage}`);
426
+ console.log(`Target languages: ${languages.join(", ")}`);
427
+ console.log(`Namespaces: ${sourceNamespaces.join(", ")}`);
428
+ console.log("=====");
429
+ for (const language of languages) {
430
+ const targetTranslations = readTranslations(translationsPath, language);
431
+ for (const namespace of sourceNamespaces) {
432
+ const sourceKeys = sourceTranslations[namespace] || {};
433
+ const targetKeys = targetTranslations[namespace] || {};
434
+ for (const [key, sourceValue] of Object.entries(sourceKeys)) {
435
+ const targetValue = targetKeys[key];
436
+ if (targetValue === void 0) {
437
+ missing.push({
438
+ namespace,
439
+ key,
440
+ language,
441
+ sourceValue
442
+ });
443
+ } else if (typeof targetValue === "string" && targetValue.trim() === "") {
444
+ empty.push({
445
+ namespace,
446
+ key,
447
+ language,
448
+ sourceValue
449
+ });
450
+ }
451
+ }
452
+ }
453
+ }
454
+ const valid = missing.length === 0 && empty.length === 0;
455
+ if (valid) {
456
+ console.log("\u2713 All translations are valid!");
457
+ } else {
458
+ if (missing.length > 0) {
459
+ console.log(`
460
+ \u26A0 Found ${missing.length} missing translations:`);
461
+ for (const item of missing.slice(0, 10)) {
462
+ console.log(` ${item.language}/${item.namespace}.json -> ${item.key}`);
463
+ }
464
+ if (missing.length > 10) {
465
+ console.log(` ... and ${missing.length - 10} more`);
466
+ }
467
+ }
468
+ if (empty.length > 0) {
469
+ console.log(`
470
+ \u26A0 Found ${empty.length} empty translations:`);
471
+ for (const item of empty.slice(0, 10)) {
472
+ console.log(` ${item.language}/${item.namespace}.json -> ${item.key}`);
473
+ }
474
+ if (empty.length > 10) {
475
+ console.log(` ... and ${empty.length - 10} more`);
476
+ }
477
+ }
478
+ }
479
+ console.log("=====");
480
+ return { valid, missing, empty };
481
+ }
482
+
483
+ // src/scripts/verify-translations.ts
484
+ function verifyTranslations() {
485
+ const projectRoot = process.cwd();
486
+ try {
487
+ const result = validateTranslations(projectRoot);
488
+ if (!result.valid) {
489
+ console.error("\n\u274C Translation verification failed!");
490
+ console.error(
491
+ `Found ${result.missing.length} missing translations and ${result.empty.length} empty translations.`
492
+ );
493
+ console.error("Please fix these issues before proceeding.\n");
494
+ process.exit(1);
495
+ }
496
+ console.log("\n\u2705 All translations verified successfully!");
497
+ process.exit(0);
498
+ } catch (error) {
499
+ console.error("\n\u274C Error during translation verification:");
500
+ console.error(error instanceof Error ? error.message : String(error));
501
+ process.exit(1);
502
+ }
503
+ }
504
+ verifyTranslations();
505
+ //# 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 * Translation provider types\n */\nexport const TRANSLATION_PROVIDERS = ['deepl', 'google'] as const;\nexport type TranslationProviderType = (typeof TRANSLATION_PROVIDERS)[number];\n\n/**\n * DeepL supported target languages\n * Based on DeepL API v2 documentation\n */\nexport const DEEPL_LANGUAGES = [\n 'ar', // Arabic\n 'bg', // Bulgarian\n 'cs', // Czech\n 'da', // Danish\n 'de', // German\n 'el', // Greek\n 'en', // English (unspecified)\n 'en_gb', // English (British)\n 'en_us', // English (American)\n 'es', // Spanish\n 'es_419', // Spanish (Latin American)\n 'et', // Estonian\n 'fi', // Finnish\n 'fr', // French\n 'he', // Hebrew (next-gen models only)\n 'hu', // Hungarian\n 'id', // Indonesian\n 'it', // Italian\n 'ja', // Japanese\n 'ko', // Korean\n 'lt', // Lithuanian\n 'lv', // Latvian\n 'nb', // Norwegian Bokmål\n 'nl', // Dutch\n 'pl', // Polish\n 'pt', // Portuguese (unspecified)\n 'pt_br', // Portuguese (Brazilian)\n 'pt_pt', // Portuguese (excluding Brazilian)\n 'ro', // Romanian\n 'ru', // Russian\n 'sk', // Slovak\n 'sl', // Slovenian\n 'sv', // Swedish\n 'th', // Thai (next-gen models only)\n 'tr', // Turkish\n 'uk', // Ukrainian\n 'vi', // Vietnamese (next-gen models only)\n 'zh', // Chinese (unspecified)\n 'zh_hans', // Chinese (simplified)\n 'zh_hant' // Chinese (traditional)\n] as const;\n\n/**\n * Google Translate supported languages\n * Based on Google Cloud Translation API v2\n * Reference: https://docs.cloud.google.com/translate/docs/languages\n */\nexport const GOOGLE_LANGUAGES = [\n 'af', // Afrikaans\n 'sq', // Albanian\n 'am', // Amharic\n 'ar', // Arabic\n 'hy', // Armenian\n 'az', // Azerbaijani\n 'eu', // Basque\n 'be', // Belarusian\n 'bn', // Bengali\n 'bs', // Bosnian\n 'bg', // Bulgarian\n 'ca', // Catalan\n 'ceb', // Cebuano\n 'zh', // Chinese (Simplified)\n 'zh_cn', // Chinese (Simplified)\n 'zh_tw', // Chinese (Traditional)\n 'co', // Corsican\n 'hr', // Croatian\n 'cs', // Czech\n 'da', // Danish\n 'nl', // Dutch\n 'en', // English\n 'eo', // Esperanto\n 'et', // Estonian\n 'fi', // Finnish\n 'fr', // French\n 'fy', // Frisian\n 'gl', // Galician\n 'ka', // Georgian\n 'de', // German\n 'el', // Greek\n 'gu', // Gujarati\n 'ht', // Haitian Creole\n 'ha', // Hausa\n 'haw', // Hawaiian\n 'he', // Hebrew\n 'hi', // Hindi\n 'hmn', // Hmong\n 'hu', // Hungarian\n 'is', // Icelandic\n 'ig', // Igbo\n 'id', // Indonesian\n 'ga', // Irish\n 'it', // Italian\n 'ja', // Japanese\n 'jv', // Javanese\n 'kn', // Kannada\n 'kk', // Kazakh\n 'km', // Khmer\n 'rw', // Kinyarwanda\n 'ko', // Korean\n 'ku', // Kurdish\n 'ky', // Kyrgyz\n 'lo', // Lao\n 'la', // Latin\n 'lv', // Latvian\n 'lt', // Lithuanian\n 'lb', // Luxembourgish\n 'mk', // Macedonian\n 'mg', // Malagasy\n 'ms', // Malay\n 'ml', // Malayalam\n 'mt', // Maltese\n 'mi', // Maori\n 'mr', // Marathi\n 'mn', // Mongolian\n 'my', // Myanmar (Burmese)\n 'ne', // Nepali\n 'no', // Norwegian\n 'ny', // Nyanja (Chichewa)\n 'or', // Odia (Oriya)\n 'ps', // Pashto\n 'fa', // Persian\n 'pl', // Polish\n 'pt', // Portuguese\n 'pt_br', // Portuguese (Brazil)\n 'pa', // Punjabi\n 'ro', // Romanian\n 'ru', // Russian\n 'sm', // Samoan\n 'gd', // Scots Gaelic\n 'sr', // Serbian\n 'st', // Sesotho\n 'sn', // Shona\n 'sd', // Sindhi\n 'si', // Sinhala (Sinhalese)\n 'sk', // Slovak\n 'sl', // Slovenian\n 'so', // Somali\n 'es', // Spanish\n 'su', // Sundanese\n 'sw', // Swahili\n 'sv', // Swedish\n 'tl', // Tagalog (Filipino)\n 'tg', // Tajik\n 'ta', // Tamil\n 'tt', // Tatar\n 'te', // Telugu\n 'th', // Thai\n 'tr', // Turkish\n 'tk', // Turkmen\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\n/**\n * All supported language codes (union of DeepL and Google Translate)\n */\nexport const SUPPORTED_LANGUAGES = Array.from(\n new Set([...DEEPL_LANGUAGES, ...GOOGLE_LANGUAGES])\n).sort() as readonly string[];\n\nexport type DeepLLanguage = (typeof DEEPL_LANGUAGES)[number];\nexport type GoogleLanguage = (typeof GOOGLE_LANGUAGES)[number];\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 provider: {\n type: 'string',\n description: 'Translation provider to use (deepl or google)',\n enum: TRANSLATION_PROVIDERS,\n default: 'deepl'\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 if a language is supported by DeepL\n */\nexport function isValidDeepLLanguage(lang: string): lang is DeepLLanguage {\n return DEEPL_LANGUAGES.includes(lang as DeepLLanguage);\n}\n\n/**\n * Validate if a language is supported by Google Translate\n */\nexport function isValidGoogleLanguage(lang: string): lang is GoogleLanguage {\n return GOOGLE_LANGUAGES.includes(lang as GoogleLanguage);\n}\n\n/**\n * Validate if a language is supported by a specific provider\n */\nexport function isValidLanguageForProvider(\n lang: string,\n provider: TranslationProviderType\n): boolean {\n switch (provider) {\n case 'deepl':\n return isValidDeepLLanguage(lang);\n case 'google':\n return isValidGoogleLanguage(lang);\n default:\n return false;\n }\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\n/**\n * Validate languages array for a specific provider\n */\nexport function validateLanguagesForProvider(\n languages: string[],\n provider: TranslationProviderType\n): {\n valid: boolean;\n invalid: string[];\n} {\n const invalid = languages.filter((lang) => !isValidLanguageForProvider(lang, provider));\n return {\n valid: invalid.length === 0,\n invalid\n };\n}\n\n/**\n * Get supported languages for a specific provider\n */\nexport function getSupportedLanguages(provider: TranslationProviderType): readonly string[] {\n switch (provider) {\n case 'deepl':\n return DEEPL_LANGUAGES;\n case 'google':\n return GOOGLE_LANGUAGES;\n default:\n return [];\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;;;ACSf,IAAM,kBAAkB;AAAA,EAC7B;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;AACF;AAOO,IAAM,mBAAmB;AAAA,EAC9B;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;AAA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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.1",
3
+ "version": "0.3.0",
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"