`status`: Shows a summary of translation status without failing.
()
| 486 | |
| 487 | /** `status`: Shows a summary of translation status without failing. */ |
| 488 | async function status() { |
| 489 | console.log('Translation Status Report'); |
| 490 | console.log('========================'); |
| 491 | |
| 492 | const manifest = loadJson(MANIFEST_PATH); |
| 493 | const state = loadJson(STATE_PATH); |
| 494 | |
| 495 | if (Object.keys(manifest).length === 0) { |
| 496 | console.log('No manifest found. Run "npm run i18n:sync" to generate.'); |
| 497 | return; |
| 498 | } |
| 499 | |
| 500 | console.log(`Source locale: ${SOURCE_LOCALE}`); |
| 501 | console.log(`Total keys: ${Object.keys(manifest).length}`); |
| 502 | |
| 503 | if (Object.keys(state).length === 0) { |
| 504 | console.log('No translation state found. Run "npm run i18n:sync" to generate.'); |
| 505 | return; |
| 506 | } |
| 507 | |
| 508 | console.log('\nTranslation Coverage:'); |
| 509 | for (const locale in state) { |
| 510 | let translated = 0; |
| 511 | let stale = 0; |
| 512 | const total = Object.keys(manifest).length; |
| 513 | |
| 514 | for (const key in manifest) { |
| 515 | const sourceHash = manifest[key]; |
| 516 | const entry = normalizeStateEntry(state[locale]?.[key]); |
| 517 | |
| 518 | if (entry.translation) { |
| 519 | if (entry.source === sourceHash) { |
| 520 | translated++; |
| 521 | } else { |
| 522 | stale++; |
| 523 | } |
| 524 | } |
| 525 | } |
| 526 | |
| 527 | const percentage = Math.round((translated / total) * 100); |
| 528 | const stalePercentage = Math.round((stale / total) * 100); |
| 529 | console.log(` ${locale}: ${percentage}% translated, ${stalePercentage}% stale`); |
| 530 | } |
| 531 | } |
| 532 | |
| 533 | /** `find-unused`: Finds translation keys in en.ts that are not used in the source code */ |
| 534 | async function findUnused() { |
no test coverage detected