const fs = require('fs') const Path = require('path') const GLOBALS = ['__appName__'] const LOCALES = Path.join(__dirname, '../../locales') const baseLocalePath = Path.join(LOCALES, 'en.json') const baseLocale = JSON.parse(fs.readFileSync(baseLocalePath, 'utf-8')) const baseLocaleKeys = Object.keys(baseLocale) const IGNORE_ORPHANED_TRANSLATIONS = process.argv.includes( '--ignore-orphaned-translations' ) const IGNORE_NESTING_FOR = { over_x_templates_easy_getting_started: ['__templates__'], all_packages_and_templates: ['__templatesLink__'], } function fetchKeys(str) { const matches = str.matchAll(/__.*?__/g) if (matches.length === 0) { return [] } return Array.from(matches).map(match => match[0]) } function difference(key, base, target) { const nesting = IGNORE_NESTING_FOR[key] || [] const keysInBaseButNotInTarget = base.filter( key => !target.includes(key) && !nesting.includes(key) ) const keysInTargetButNotInBase = target.filter( key => !base.includes(key) && !GLOBALS.includes(key) ) return { keysInBaseButNotInTarget, keysInTargetButNotInBase, } } let violations = 0 for (const localeName of fs.readdirSync(LOCALES)) { if (localeName === 'README.md') continue const localePath = Path.join(LOCALES, localeName) const locale = JSON.parse(fs.readFileSync(localePath, 'utf-8')) for (const key of Object.keys(locale)) { if (!baseLocaleKeys.includes(key)) { if (IGNORE_ORPHANED_TRANSLATIONS) continue violations += 1 console.warn(`[${localeName}] Orphaned key "${key}" not found in en.json`) continue } const keysInTranslation = fetchKeys(locale[key]) const keysInBase = fetchKeys(baseLocale[key]) const { keysInBaseButNotInTarget, keysInTargetButNotInBase } = difference( key, keysInBase, keysInTranslation ) if (keysInBaseButNotInTarget.length) { violations += keysInBaseButNotInTarget.length console.warn( `[${localeName}] Missing variables in key "${key}":`, keysInBaseButNotInTarget ) } if (keysInTargetButNotInBase.length) { violations += keysInTargetButNotInBase.length console.warn( `[${localeName}] Extra variables in key "${key}":`, keysInTargetButNotInBase ) } } } if (violations) { console.warn('Variables are not in sync between translations.') process.exit(1) } else { console.log('Variables are in sync.') process.exit(0) }