|
| 1 | +#!/usr/bin/env node |
| 2 | + |
| 3 | +const scriptHelpDocument = ` |
| 4 | +NAME |
| 5 | + generateSupportedLangs.js — Script to generate the 'src/i18n/messages/currentlySupportedLangs.jsx' file which contains static import for react-intl data. |
| 6 | +
|
| 7 | +SYNOPSIS |
| 8 | + generateSupportedLangs.js [comma separated list of languages] |
| 9 | + |
| 10 | +
|
| 11 | +
|
| 12 | +DESCRIPTION |
| 13 | +
|
| 14 | + Run this script after 'atlas' has pulled the files in the following structure: |
| 15 | + |
| 16 | + $ generateSupportedLangs.js ar,es_419,fr_CA |
| 17 | +
|
| 18 | + This script is intended as a temporary solution until the studio-frontend can dynamically load the languages from the react-intl data like the other micro-frontends. |
| 19 | +`; |
| 20 | + |
| 21 | +const fs = require('fs'); |
| 22 | +const path = require('path'); |
| 23 | + |
| 24 | +const loggingPrefix = path.basename(`${__filename}`); // the name of this JS file |
| 25 | + |
| 26 | +// Header note for generated src/i18n/index.js file |
| 27 | +const filesCodeGeneratorNoticeHeader = '// This file is generated by the "i18n/scripts/generateSupportedLangs.js" script.'; |
| 28 | + |
| 29 | +/** |
| 30 | + * Create main `src/i18n/index.js` messages import file. |
| 31 | + * |
| 32 | + * |
| 33 | + * @param languages - List of directories with a boolean flag whether its "index.js" file is written |
| 34 | + * The format is "[\{ directory: "frontend-component-example", isWritten: false \}, ...]" |
| 35 | + * @param log - Mockable process.stdout.write |
| 36 | + * @param writeFileSync - Mockable fs.writeFileSync |
| 37 | + * @param i18nDir` - Path to `src/i18n` directory |
| 38 | + */ |
| 39 | +function generateSupportedLangsFile({ |
| 40 | + languages, |
| 41 | + log, |
| 42 | + writeFileSync, |
| 43 | + i18nDir, |
| 44 | +}) { |
| 45 | + const importLines = []; |
| 46 | + const exportLines = []; |
| 47 | + |
| 48 | + languages.forEach(language => { |
| 49 | + const [languageFamilyCode] = language.split('_'); // Get `es` from `es-419` |
| 50 | + |
| 51 | + const importVariableName = `${languageFamilyCode.toLowerCase()}Data`; |
| 52 | + const dashLanguageCode = language.toLowerCase().replace(/_/g, '-'); |
| 53 | + importLines.push(`import ${importVariableName} from 'react-intl/locale-data/${languageFamilyCode}';`); |
| 54 | + |
| 55 | + // Note: These imports are not directly consumed by the studio-frontend React app. They're imported to ensure that |
| 56 | + // the messages/*.json files exists and they can be loaded via the load_sfe_i18n_messages() function in |
| 57 | + // the `edx-platform`. |
| 58 | + // |
| 59 | + // This pattern should probably be refactored to pull the translations directly within the `edx-platform`. |
| 60 | + const jsonFilename = `${language}.json`; |
| 61 | + if (fs.existsSync(`${i18nDir}/messages/${jsonFilename}`)) { |
| 62 | + importLines.push(`import './${jsonFilename}';`); |
| 63 | + log(`${loggingPrefix}: Notice: Not importing 'messages/${jsonFilename}' because the file wasn't found.\n`); |
| 64 | + } |
| 65 | + |
| 66 | + exportLines.push(` '${dashLanguageCode}': ${importVariableName},`); |
| 67 | + }); |
| 68 | + |
| 69 | + // See the help message above for sample output. |
| 70 | + const indexFileContent = [ |
| 71 | + filesCodeGeneratorNoticeHeader, |
| 72 | + importLines.join('\n'), |
| 73 | + '\nexport default {', |
| 74 | + exportLines.join('\n'), |
| 75 | + '};\n', |
| 76 | + ].join('\n'); |
| 77 | + |
| 78 | + writeFileSync(`${i18nDir}/messages/currentlySupportedLangs.jsx`, indexFileContent); |
| 79 | +} |
| 80 | + |
| 81 | +/* |
| 82 | + * Main function of the file. |
| 83 | + */ |
| 84 | +function main({ |
| 85 | + parameters, |
| 86 | + log, |
| 87 | + writeFileSync, |
| 88 | + pwd, |
| 89 | +}) { |
| 90 | + const i18nDir = `${pwd}/src/i18n`; // The Micro-frontend i18n root directory |
| 91 | + const [languagesString] = parameters; |
| 92 | + |
| 93 | + if (parameters.includes('--help') || parameters.includes('-h')) { |
| 94 | + log(scriptHelpDocument); |
| 95 | + } else if (!parameters.length) { |
| 96 | + log(scriptHelpDocument); |
| 97 | + log(`${loggingPrefix}: Error: A comma separated list of languages is required.\n`); |
| 98 | + } else { |
| 99 | + generateSupportedLangsFile({ |
| 100 | + languages: languagesString.split(','), |
| 101 | + log, |
| 102 | + writeFileSync, |
| 103 | + i18nDir, |
| 104 | + }); |
| 105 | + log(`${loggingPrefix}: Finished generating the 'currentlySupportedLangs.jsx' file.`); |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +if (require.main === module) { |
| 110 | + // Run the main() function if called from the command line. |
| 111 | + main({ |
| 112 | + parameters: process.argv.slice(2), |
| 113 | + log: text => process.stdout.write(text), |
| 114 | + writeFileSync: fs.writeFileSync, |
| 115 | + pwd: process.env.PWD, |
| 116 | + }); |
| 117 | +} |
| 118 | + |
| 119 | +module.exports.main = main; // Allow tests to use the main function. |
0 commit comments