| 
									
										
										
										
											2022-03-04 12:00:36 +01:00
										 |  |  | /* eslint-disable node/no-extraneous-require */ | 
					
						
							| 
									
										
										
										
											2022-08-08 15:50:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const path = require('path'); | 
					
						
							|  |  |  | const chalk = require('chalk'); | 
					
						
							|  |  |  | const inquirer = require('inquirer'); | 
					
						
							|  |  |  | const { kebabCase } = require('lodash'); | 
					
						
							|  |  |  | const FilesContentSearch = require('../utils/search-files-content'); | 
					
						
							|  |  |  | const { readAllTranslationFiles, writeAllTranslationFiles } = require('../utils/translation-files'); | 
					
						
							|  |  |  | const { findDuplicatedTranslations } = require('./find-duplicated-translation'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const fcs = new FilesContentSearch( | 
					
						
							|  |  |  |   [path.join(__dirname, '../../../')], | 
					
						
							|  |  |  |   ['**/*.js'], | 
					
						
							|  |  |  |   ['**/node_modules/**', '**/cache/**', '**/build/**'] | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const mapDuplicates = async (duplicatesObject, fn) => { | 
					
						
							|  |  |  |   Object.entries(duplicatesObject).forEach(([value, pkgs]) => fn(value, pkgs)); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const mapDuplicateValues = async (pkgs, fn) => { | 
					
						
							|  |  |  |   Object.entries(pkgs).forEach(([packageName, keys]) => { | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |     keys.forEach((key) => fn(key, packageName)); | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |   }); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const promptShouldMerge = async () => { | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     await inquirer.prompt({ | 
					
						
							|  |  |  |       type: 'confirm', | 
					
						
							|  |  |  |       message: 'Should merge?', | 
					
						
							|  |  |  |       name: 'shouldMerge', | 
					
						
							|  |  |  |       default: false, | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   ).shouldMerge; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const promptTargetKey = async (valueGroup) => { | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |   return ( | 
					
						
							|  |  |  |     await inquirer.prompt({ | 
					
						
							|  |  |  |       type: 'input', | 
					
						
							|  |  |  |       name: 'targetKey', | 
					
						
							|  |  |  |       message: 'Target key name:', | 
					
						
							|  |  |  |       default: `global.${kebabCase(valueGroup[0].value)}`, | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   ).targetKey; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const printToMerge = (valueGroup) => { | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |   console.log(`Value: "${chalk.yellow(valueGroup[0].value)}"`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   console.table( | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |     valueGroup.map((keyGroup) => ({ | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |       key: keyGroup.key, | 
					
						
							|  |  |  |       package: keyGroup.packageName, | 
					
						
							|  |  |  |       usageCount: keyGroup.resultsCount, | 
					
						
							|  |  |  |     })) | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const applyPackageScope = (packageName, searchResults) => { | 
					
						
							|  |  |  |   return searchResults.filter( | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |     (result) => packageName === 'core/admin' || result.path.includes(packageName) | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |   ); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Filters out duplicated transtations that are not in use
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const getValuesToMerge = (keyUsage) => | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |   keyUsage | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |     .map((value) => value.dups.filter((dup) => dup.resultsCount > 0)) | 
					
						
							|  |  |  |     .filter((value) => value.length > 1); | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Returns an array of duplicated translations that are in use in the codebase
 | 
					
						
							|  |  |  | // (found in at least one .js files)
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const getKeysUsage = (duplicatesObject) => { | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |   const keyUsage = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mapDuplicates(duplicatesObject, (value, pkgs) => { | 
					
						
							|  |  |  |     const dups = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mapDuplicateValues(pkgs, (key, packageName) => { | 
					
						
							|  |  |  |       const searchResults = applyPackageScope(packageName, [ | 
					
						
							|  |  |  |         ...fcs.searchString(`id: '${key}'`), | 
					
						
							|  |  |  |         ...fcs.searchString(`id: getTrad('${key}')`), | 
					
						
							|  |  |  |       ]); | 
					
						
							|  |  |  |       const resultsCount = searchResults.reduce((acc, cur) => cur.matches.length + acc, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       dups.push({ | 
					
						
							|  |  |  |         key, | 
					
						
							|  |  |  |         value, | 
					
						
							|  |  |  |         packageName, | 
					
						
							|  |  |  |         resultsCount, | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |         replaceAll: (replaceValue) => | 
					
						
							|  |  |  |           searchResults.forEach((result) => result.replaceAll(replaceValue)), | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     keyUsage.push({ value, dups }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return keyUsage; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Handles the merging in translation files
 | 
					
						
							|  |  |  | // Removes duplicated translations + creates a new shared key in the core/admin en.json file
 | 
					
						
							|  |  |  | const updateTranslationFiles = (keyGroup, targetKey) => { | 
					
						
							|  |  |  |   const translationFiles = {}; | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |   readAllTranslationFiles().forEach((file) => { | 
					
						
							|  |  |  |     translationFiles[file.packageName] = file; | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (translationFiles[keyGroup.packageName].fileContent[keyGroup.key] === keyGroup.value) { | 
					
						
							|  |  |  |     delete translationFiles[keyGroup.packageName].fileContent[keyGroup.key]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   translationFiles['core/admin'].fileContent[targetKey] = keyGroup.value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   writeAllTranslationFiles(Object.values(translationFiles)); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Displays and prompt for every detected duplications
 | 
					
						
							|  |  |  | // Triggers the merge if necessary
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const merge = async (valuesToMerge) => { | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |   let current = 1; | 
					
						
							|  |  |  |   let mergedCount = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 15:50:34 +02:00
										 |  |  |   for (const valueGroup of valuesToMerge) { | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |     // Display
 | 
					
						
							|  |  |  |     console.clear(); | 
					
						
							|  |  |  |     console.log(`${current}/${valuesToMerge.length}`); | 
					
						
							|  |  |  |     printToMerge(valueGroup); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Prompt and merge
 | 
					
						
							|  |  |  |     if (await promptShouldMerge()) { | 
					
						
							|  |  |  |       const targetKey = await promptTargetKey(valueGroup); | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |       valueGroup.forEach((keyGroup) => { | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |         updateTranslationFiles(keyGroup, targetKey); | 
					
						
							|  |  |  |         keyGroup.replaceAll(`id: '${targetKey}'`); | 
					
						
							| 
									
										
										
										
											2022-09-05 15:04:28 +02:00
										 |  |  |         mergedCount += 1; | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-05 15:04:28 +02:00
										 |  |  |     current += 1; | 
					
						
							| 
									
										
										
										
											2022-02-22 11:15:34 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   console.log(`Merged ${mergedCount} keys`); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | (async () => { | 
					
						
							|  |  |  |   await fcs.loadFiles(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const duplicates = findDuplicatedTranslations(); | 
					
						
							|  |  |  |   const keyUsage = getKeysUsage(duplicates); | 
					
						
							|  |  |  |   const valuesToMerge = getValuesToMerge(keyUsage); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   await merge(valuesToMerge); | 
					
						
							|  |  |  | })(); |