validate-translations.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #!/usr/bin/env node
  2. /**
  3. * Build-time validation script for navigation translations
  4. *
  5. * This script validates that all products have complete translations
  6. * for all required locales. It helps prevent maintenance drift by
  7. * ensuring that when navigation structure changes, translations are
  8. * kept in sync.
  9. *
  10. * Usage:
  11. * node scripts/validate-translations.js
  12. * node scripts/validate-translations.js --fail-on-warning
  13. */
  14. const { products } = require('../src/components/products/index.js')
  15. const {
  16. validateProductTranslations,
  17. extractNavigationKeys,
  18. generateTranslationTemplate
  19. } = require('../src/utils/navigation-localization.js')
  20. const REQUIRED_LOCALES = ['ja', 'ko']
  21. const FAIL_ON_WARNING = process.argv.includes('--fail-on-warning')
  22. const GENERATE_TEMPLATE = process.argv.includes('--generate-template')
  23. console.log('Validating navigation translations...\n')
  24. let hasErrors = false
  25. let hasWarnings = false
  26. const allResults = []
  27. products.forEach(product => {
  28. // Skip products without navigation
  29. if (!product.sections || product.sections.length === 0) {
  30. return
  31. }
  32. const keys = extractNavigationKeys(product)
  33. // Skip products with no navigable content
  34. if (keys.sections.length === 0 && keys.links.length === 0) {
  35. return
  36. }
  37. console.log(`Checking ${product.name}...`)
  38. // Generate template if requested
  39. if (GENERATE_TEMPLATE && (!product.localizedNavigation || Object.keys(product.localizedNavigation).length === 0)) {
  40. console.log(` Template for ${product.name}:`)
  41. REQUIRED_LOCALES.forEach(locale => {
  42. const template = generateTranslationTemplate(product, locale)
  43. console.log(` ${locale}:`, JSON.stringify(template, null, 2))
  44. })
  45. console.log()
  46. return
  47. }
  48. const validation = validateProductTranslations(product, REQUIRED_LOCALES)
  49. allResults.push({ product: product.name, validation })
  50. if (!validation.isValid) {
  51. hasErrors = true
  52. console.log(` ❌ Validation failed`)
  53. validation.errors.forEach(error => {
  54. console.log(` - ${error}`)
  55. })
  56. } else {
  57. console.log(` ✅ All translations complete`)
  58. }
  59. // Show detailed results for each locale
  60. Object.entries(validation.results).forEach(([locale, result]) => {
  61. if (!result.isValid) {
  62. hasWarnings = true
  63. console.log(` Locale ${locale}:`)
  64. if (result.missing.sections.length > 0) {
  65. console.log(` Missing sections: ${result.missing.sections.join(', ')}`)
  66. }
  67. if (result.missing.links.length > 0) {
  68. console.log(` Missing links: ${result.missing.links.join(', ')}`)
  69. }
  70. if (result.missing.headline) {
  71. console.log(` Missing headline`)
  72. }
  73. if (result.missing.description) {
  74. console.log(` Missing description`)
  75. }
  76. }
  77. })
  78. console.log()
  79. })
  80. // Summary
  81. console.log('Summary:')
  82. console.log(` Total products validated: ${allResults.length}`)
  83. console.log(` Products with errors: ${allResults.filter(r => !r.validation.isValid).length}`)
  84. console.log(` Products with warnings: ${allResults.filter(r => Object.values(r.validation.results).some(v => !v.isValid)).length}`)
  85. if (hasErrors || (FAIL_ON_WARNING && hasWarnings)) {
  86. console.log('\n❌ Translation validation failed!')
  87. console.log('Please ensure all navigation items have translations for all required locales.')
  88. process.exit(1)
  89. } else if (hasWarnings) {
  90. console.log('\n⚠️ Some warnings found, but validation passed.')
  91. console.log('Consider adding missing translations for better localization coverage.')
  92. process.exit(0)
  93. } else {
  94. console.log('\n✅ All translations validated successfully!')
  95. process.exit(0)
  96. }