transduck 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/dist/cli.js CHANGED
@@ -298,6 +298,7 @@ export async function runWarm(opts) {
298
298
  export async function runScan(opts) {
299
299
  const cfg = loadConfig(opts.configPath);
300
300
  const scanDirs = opts.dirs.length > 0 ? opts.dirs : [process.cwd()];
301
+ console.log('Scanning...');
301
302
  const entries = scanDirectory(scanDirs);
302
303
  const regular = entries.filter(e => !e.plural);
303
304
  const plurals = entries.filter(e => e.plural);
@@ -337,78 +338,96 @@ export async function runScan(opts) {
337
338
  }
338
339
  // Warm
339
340
  if (opts.warm) {
340
- const targetLangs = opts.langs && opts.langs.length > 0
341
- ? opts.langs.map(l => l.toUpperCase())
342
- : cfg.targetLangs;
343
- const store = new TranslationStore(cfg.storagePath);
344
- await store.initialize();
345
- const projectContextHash = hash(cfg.projectContext);
346
- let translated = 0;
347
- let skipped = 0;
348
- let failed = 0;
349
- for (const entry of entries) {
350
- if (entry.plural) {
351
- const sourceKey = entry.one + '\x00' + entry.other;
352
- const stringContextHash = hash(entry.context ?? '');
353
- for (const lang of targetLangs) {
354
- const cachedForms = await store.lookupPlural({
355
- sourceText: sourceKey, sourceLang: cfg.sourceLang, targetLang: lang,
356
- projectContextHash, stringContextHash,
357
- });
358
- if (Object.keys(cachedForms).length > 0) {
359
- skipped++;
360
- continue;
361
- }
362
- try {
363
- const forms = await backendTranslatePlural(entry.one, entry.other, cfg.sourceLang, lang, cfg.projectContext, entry.context ?? null, cfg);
364
- for (const [cat, translatedText] of Object.entries(forms)) {
365
- await store.insertPlural({
366
- sourceText: sourceKey, sourceLang: cfg.sourceLang, targetLang: lang,
367
- projectContextHash, stringContextHash,
368
- pluralCategory: cat, translatedText: translatedText,
369
- model: cfg.backendModel, status: 'translated',
370
- });
341
+ if (entries.length === 0) {
342
+ lines.push('\nNothing to warm — no translatable strings found.');
343
+ }
344
+ else {
345
+ const targetLangs = opts.langs && opts.langs.length > 0
346
+ ? opts.langs.map(l => l.toUpperCase())
347
+ : cfg.targetLangs;
348
+ const store = new TranslationStore(cfg.storagePath);
349
+ await store.initialize();
350
+ const projectContextHash = hash(cfg.projectContext);
351
+ let translated = 0;
352
+ let skipped = 0;
353
+ let failed = 0;
354
+ const total = entries.length * targetLangs.length;
355
+ let done = 0;
356
+ for (const entry of entries) {
357
+ if (entry.plural) {
358
+ const sourceKey = entry.one + '\x00' + entry.other;
359
+ const stringContextHash = hash(entry.context ?? '');
360
+ const label = (entry.one ?? '').slice(0, 40);
361
+ for (const lang of targetLangs) {
362
+ done++;
363
+ const cachedForms = await store.lookupPlural({
364
+ sourceText: sourceKey, sourceLang: cfg.sourceLang, targetLang: lang,
365
+ projectContextHash, stringContextHash,
366
+ });
367
+ if (Object.keys(cachedForms).length > 0) {
368
+ skipped++;
369
+ console.log(` [${done}/${total}] ${lang} skipped (cached): ${label}`);
370
+ continue;
371
371
  }
372
- translated++;
373
- }
374
- catch {
375
- failed++;
376
- }
377
- }
378
- }
379
- else {
380
- const stringContextHash = hash(entry.context ?? '');
381
- for (const lang of targetLangs) {
382
- const cached = await store.lookup({
383
- sourceText: entry.text, sourceLang: cfg.sourceLang, targetLang: lang,
384
- projectContextHash, stringContextHash,
385
- });
386
- if (cached !== null) {
387
- skipped++;
388
- continue;
389
- }
390
- try {
391
- const result = await backendTranslate(entry.text, cfg.sourceLang, lang, cfg.projectContext, entry.context ?? null, cfg);
392
- if (validateTranslation(entry.text, result)) {
393
- await store.insert({
394
- sourceText: entry.text, sourceLang: cfg.sourceLang, targetLang: lang,
395
- projectContextHash, stringContextHash,
396
- translatedText: result, model: cfg.backendModel, status: 'translated',
397
- });
372
+ try {
373
+ const forms = await backendTranslatePlural(entry.one, entry.other, cfg.sourceLang, lang, cfg.projectContext, entry.context ?? null, cfg);
374
+ for (const [cat, translatedText] of Object.entries(forms)) {
375
+ await store.insertPlural({
376
+ sourceText: sourceKey, sourceLang: cfg.sourceLang, targetLang: lang,
377
+ projectContextHash, stringContextHash,
378
+ pluralCategory: cat, translatedText: translatedText,
379
+ model: cfg.backendModel, status: 'translated',
380
+ });
381
+ }
398
382
  translated++;
383
+ console.log(` [${done}/${total}] ${lang} translated: ${label}`);
399
384
  }
400
- else {
385
+ catch {
401
386
  failed++;
387
+ console.log(` [${done}/${total}] ${lang} failed: ${label}`);
402
388
  }
403
389
  }
404
- catch {
405
- failed++;
390
+ }
391
+ else {
392
+ const stringContextHash = hash(entry.context ?? '');
393
+ const label = (entry.text ?? '').slice(0, 40);
394
+ for (const lang of targetLangs) {
395
+ done++;
396
+ const cached = await store.lookup({
397
+ sourceText: entry.text, sourceLang: cfg.sourceLang, targetLang: lang,
398
+ projectContextHash, stringContextHash,
399
+ });
400
+ if (cached !== null) {
401
+ skipped++;
402
+ console.log(` [${done}/${total}] ${lang} skipped (cached): ${label}`);
403
+ continue;
404
+ }
405
+ try {
406
+ const result = await backendTranslate(entry.text, cfg.sourceLang, lang, cfg.projectContext, entry.context ?? null, cfg);
407
+ if (validateTranslation(entry.text, result)) {
408
+ await store.insert({
409
+ sourceText: entry.text, sourceLang: cfg.sourceLang, targetLang: lang,
410
+ projectContextHash, stringContextHash,
411
+ translatedText: result, model: cfg.backendModel, status: 'translated',
412
+ });
413
+ translated++;
414
+ console.log(` [${done}/${total}] ${lang} translated: ${label}`);
415
+ }
416
+ else {
417
+ failed++;
418
+ console.log(` [${done}/${total}] ${lang} failed: ${label}`);
419
+ }
420
+ }
421
+ catch {
422
+ failed++;
423
+ console.log(` [${done}/${total}] ${lang} failed: ${label}`);
424
+ }
406
425
  }
407
426
  }
408
427
  }
409
- }
410
- store.close();
411
- lines.push(`\nTranslated: ${translated} | Skipped: ${skipped} | Failed: ${failed}`);
428
+ store.close();
429
+ lines.push(`\nTranslated: ${translated} | Skipped: ${skipped} | Failed: ${failed}`);
430
+ } // end if entries.length > 0
412
431
  }
413
432
  if (!opts.warm && !opts.outputPath) {
414
433
  lines.push(`\nRun 'transduck scan --warm --langs DE,ES' to translate all strings.`);
@@ -1 +1,2 @@
1
+ 'use client';
1
2
  export { TransDuckProvider, t, ait, tPlural, aitPlural, useTransDuck, _resetReactState } from './provider.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "transduck",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "AI-native translation tool using source text as keys",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/cli.ts CHANGED
@@ -378,6 +378,7 @@ export interface ScanOptions {
378
378
  export async function runScan(opts: ScanOptions): Promise<string> {
379
379
  const cfg = loadConfig(opts.configPath);
380
380
  const scanDirs = opts.dirs.length > 0 ? opts.dirs : [process.cwd()];
381
+ console.log('Scanning...');
381
382
  const entries = scanDirectory(scanDirs);
382
383
 
383
384
  const regular = entries.filter(e => !e.plural);
@@ -421,6 +422,9 @@ export async function runScan(opts: ScanOptions): Promise<string> {
421
422
 
422
423
  // Warm
423
424
  if (opts.warm) {
425
+ if (entries.length === 0) {
426
+ lines.push('\nNothing to warm — no translatable strings found.');
427
+ } else {
424
428
  const targetLangs = opts.langs && opts.langs.length > 0
425
429
  ? opts.langs.map(l => l.toUpperCase())
426
430
  : cfg.targetLangs;
@@ -432,13 +436,17 @@ export async function runScan(opts: ScanOptions): Promise<string> {
432
436
  let translated = 0;
433
437
  let skipped = 0;
434
438
  let failed = 0;
439
+ const total = entries.length * targetLangs.length;
440
+ let done = 0;
435
441
 
436
442
  for (const entry of entries) {
437
443
  if (entry.plural) {
438
444
  const sourceKey = entry.one + '\x00' + entry.other;
439
445
  const stringContextHash = hash(entry.context ?? '');
446
+ const label = (entry.one ?? '').slice(0, 40);
440
447
 
441
448
  for (const lang of targetLangs) {
449
+ done++;
442
450
  const cachedForms = await store.lookupPlural({
443
451
  sourceText: sourceKey, sourceLang: cfg.sourceLang, targetLang: lang,
444
452
  projectContextHash, stringContextHash,
@@ -446,6 +454,7 @@ export async function runScan(opts: ScanOptions): Promise<string> {
446
454
 
447
455
  if (Object.keys(cachedForms).length > 0) {
448
456
  skipped++;
457
+ console.log(` [${done}/${total}] ${lang} skipped (cached): ${label}`);
449
458
  continue;
450
459
  }
451
460
 
@@ -465,14 +474,18 @@ export async function runScan(opts: ScanOptions): Promise<string> {
465
474
  });
466
475
  }
467
476
  translated++;
477
+ console.log(` [${done}/${total}] ${lang} translated: ${label}`);
468
478
  } catch {
469
479
  failed++;
480
+ console.log(` [${done}/${total}] ${lang} failed: ${label}`);
470
481
  }
471
482
  }
472
483
  } else {
473
484
  const stringContextHash = hash(entry.context ?? '');
485
+ const label = (entry.text ?? '').slice(0, 40);
474
486
 
475
487
  for (const lang of targetLangs) {
488
+ done++;
476
489
  const cached = await store.lookup({
477
490
  sourceText: entry.text!, sourceLang: cfg.sourceLang, targetLang: lang,
478
491
  projectContextHash, stringContextHash,
@@ -480,6 +493,7 @@ export async function runScan(opts: ScanOptions): Promise<string> {
480
493
 
481
494
  if (cached !== null) {
482
495
  skipped++;
496
+ console.log(` [${done}/${total}] ${lang} skipped (cached): ${label}`);
483
497
  continue;
484
498
  }
485
499
 
@@ -496,11 +510,14 @@ export async function runScan(opts: ScanOptions): Promise<string> {
496
510
  translatedText: result, model: cfg.backendModel, status: 'translated',
497
511
  });
498
512
  translated++;
513
+ console.log(` [${done}/${total}] ${lang} translated: ${label}`);
499
514
  } else {
500
515
  failed++;
516
+ console.log(` [${done}/${total}] ${lang} failed: ${label}`);
501
517
  }
502
518
  } catch {
503
519
  failed++;
520
+ console.log(` [${done}/${total}] ${lang} failed: ${label}`);
504
521
  }
505
522
  }
506
523
  }
@@ -508,6 +525,7 @@ export async function runScan(opts: ScanOptions): Promise<string> {
508
525
 
509
526
  store.close();
510
527
  lines.push(`\nTranslated: ${translated} | Skipped: ${skipped} | Failed: ${failed}`);
528
+ } // end if entries.length > 0
511
529
  }
512
530
 
513
531
  if (!opts.warm && !opts.outputPath) {
@@ -1 +1,3 @@
1
+ 'use client';
2
+
1
3
  export { TransDuckProvider, t, ait, tPlural, aitPlural, useTransDuck, _resetReactState } from './provider.js';