diff --git a/Makefile b/Makefile index aefe2dce..fd7e1659 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,6 @@ transifex_langs = "ar,fr,es_419,zh_CN" i18n = ./src/i18n transifex_input = $(i18n)/transifex_input.json transifex_utils = ./node_modules/.bin/edx_reactifex -generate_supported_langs = src/i18n/scripts/generateSupportedLangs.js # This directory must match .babelrc . transifex_temp = ./temp/babel-plugin-react-intl @@ -102,8 +101,8 @@ else pull_translations: rm -rf src/i18n/messages cd src/i18n/ \ - && atlas pull --filter=$(transifex_langs) translations/studio-frontend/src/i18n/messages:messages - $(generate_supported_langs) $(transifex_langs) + && atlas pull $(ATLAS_OPTIONS) translations/studio-frontend/src/i18n/messages:messages + cd src/i18n/ && node ../../src/utils/i18n/scripts/generateSupportedLangs.js endif copy-dist: diff --git a/src/i18n/messages/currentlySupportedLangs.jsx b/src/i18n/messages/currentlySupportedLangs.jsx index e2debf9a..6cad5931 100644 --- a/src/i18n/messages/currentlySupportedLangs.jsx +++ b/src/i18n/messages/currentlySupportedLangs.jsx @@ -1,28 +1,16 @@ +// This file is generated by the "i18n/scripts/generateSupportedLangs.js" script. import arData from 'react-intl/locale-data/ar'; -import enData from 'react-intl/locale-data/en'; -import esData from 'react-intl/locale-data/es'; -import frData from 'react-intl/locale-data/fr'; -import zhData from 'react-intl/locale-data/zh'; - import './ar.json'; +import esData from 'react-intl/locale-data/es'; import './es_419.json'; +import frData from 'react-intl/locale-data/fr'; import './fr.json'; +import zhData from 'react-intl/locale-data/zh'; import './zh_CN.json'; -// Methodology: These languages (plus the default english) are the only ones that appear on edx.org -// This was determined by inspecting the 'released_languages' method in the following file: -// https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/lang_pref/api.py -// -// Further, I hit the read replica in order to confirm the live values, which are currently: -// en, fr, zh-cn, es-419, ar -// If these values change, please also update the pull_translations command in Makefile - -const localeDataMap = { +export default { 'ar': arData, - 'en': enData, 'es-419': esData, 'fr': frData, 'zh-cn': zhData, }; - -export default localeDataMap; diff --git a/src/i18n/scripts/generateSupportedLangs.js b/src/utils/i18n/scripts/generateSupportedLangs.js similarity index 78% rename from src/i18n/scripts/generateSupportedLangs.js rename to src/utils/i18n/scripts/generateSupportedLangs.js index fdb3ecd1..ca38ad08 100755 --- a/src/i18n/scripts/generateSupportedLangs.js +++ b/src/utils/i18n/scripts/generateSupportedLangs.js @@ -5,15 +5,17 @@ NAME generateSupportedLangs.js — Script to generate the 'src/i18n/messages/currentlySupportedLangs.jsx' file which contains static import for react-intl data. SYNOPSIS - generateSupportedLangs.js [comma separated list of languages] - + generateSupportedLangs.js DESCRIPTION Run this script after 'atlas' has pulled the files in the following structure: - - $ generateSupportedLangs.js ar,es_419,fr_CA + + $ cd src/i18n; node path/to/generateSupportedLangs.js + + This script will generate the 'src/i18n/messages/currentlySupportedLangs.jsx' file which contains static import for + react-intl data based on the JSON language files present in the 'src/i18n/messages' directory. 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. `; @@ -24,7 +26,7 @@ const path = require('path'); const loggingPrefix = path.basename(`${__filename}`); // the name of this JS file // Header note for generated src/i18n/index.js file -const filesCodeGeneratorNoticeHeader = '// This file is generated by the "i18n/scripts/generateSupportedLangs.js" script.'; +const filesCodeGeneratorNoticeHeader = '// This file is generated by the "generateSupportedLangs.js" script.'; /** * Create main `src/i18n/index.js` messages import file. @@ -32,13 +34,11 @@ const filesCodeGeneratorNoticeHeader = '// This file is generated by the "i18n/s * * @param languages - List of directories with a boolean flag whether its "index.js" file is written * The format is "[\{ directory: "frontend-component-example", isWritten: false \}, ...]" - * @param log - Mockable process.stdout.write * @param writeFileSync - Mockable fs.writeFileSync * @param i18nDir` - Path to `src/i18n` directory */ function generateSupportedLangsFile({ languages, - log, writeFileSync, i18nDir, }) { @@ -58,11 +58,7 @@ function generateSupportedLangsFile({ // // This pattern should probably be refactored to pull the translations directly within the `edx-platform`. const jsonFilename = `${language}.json`; - if (fs.existsSync(`${i18nDir}/messages/${jsonFilename}`)) { - importLines.push(`import './${jsonFilename}';`); - log(`${loggingPrefix}: Notice: Not importing 'messages/${jsonFilename}' because the file wasn't found.\n`); - } - + importLines.push(`import './${jsonFilename}';`); exportLines.push(` '${dashLanguageCode}': ${importVariableName},`); }); @@ -87,22 +83,23 @@ function main({ writeFileSync, pwd, }) { - const i18nDir = `${pwd}/src/i18n`; // The Micro-frontend i18n root directory - const [languagesString] = parameters; + const i18nDir = pwd; + const languageFiles = fs.readdirSync(`${i18nDir}/messages`).filter(file => file.endsWith('.json')); + const languages = languageFiles.map(file => file.replace('.json', '')); + languages.sort(); - if (parameters.includes('--help') || parameters.includes('-h')) { + if (parameters.includes('-h') || parameters.includes('--help')) { log(scriptHelpDocument); - } else if (!parameters.length) { + } else if (!languages.length) { log(scriptHelpDocument); - log(`${loggingPrefix}: Error: A comma separated list of languages is required.\n`); + log(`${loggingPrefix}: Error: No language files found in 'src/i18n/messages'.\n`); } else { generateSupportedLangsFile({ - languages: languagesString.split(','), - log, + languages, writeFileSync, i18nDir, }); - log(`${loggingPrefix}: Finished generating the 'currentlySupportedLangs.jsx' file.`); + log(`${loggingPrefix}: Finished generating the 'currentlySupportedLangs.jsx' file.\n`); } } diff --git a/src/i18n/scripts/generateSupportedLangs.test.js b/src/utils/i18n/scripts/generateSupportedLangs.test.js similarity index 87% rename from src/i18n/scripts/generateSupportedLangs.test.js rename to src/utils/i18n/scripts/generateSupportedLangs.test.js index 0f0afb08..1a6646d0 100755 --- a/src/i18n/scripts/generateSupportedLangs.test.js +++ b/src/utils/i18n/scripts/generateSupportedLangs.test.js @@ -3,7 +3,7 @@ import path from 'path'; import { main as realMain } from './generateSupportedLangs'; -const sempleAppDirectory = path.join(__dirname, '../../../test-app'); +const sempleAppDirectory = path.join(__dirname, '../../../../test-app'); // History for `process.stdout.write` mock calls. const logHistory = { @@ -35,7 +35,7 @@ const main = (...parameters) => realMain({ parameters, log, writeFileSync, - pwd: sempleAppDirectory, + pwd: `${sempleAppDirectory}/src/i18n`, }); // Clean up mock histories @@ -63,7 +63,7 @@ describe('help document', () => { }); describe('generate with three languages', () => { - main('ar,de,fr_CA'); // German doesn't have a messages file in the `test-app` + main(); expect(writeFileHistory.log.length).toBe(1); expect(writeFileHistory.latest.filename).toBe(`${sempleAppDirectory}/src/i18n/messages/currentlySupportedLangs.jsx`); @@ -74,17 +74,18 @@ describe('generate with three languages', () => { // test-app/src/i18n/messages directory // - import 'react-intl/locale-data/fr' and fr_CA.json messages // - export the imported locale-data - expect(writeFileHistory.latest.content).toMatch(`// This file is generated by the "i18n/scripts/generateSupportedLangs.js" script. + expect(writeFileHistory.latest.content).toMatch(`// This file is generated by the "generateSupportedLangs.js" script. import arData from 'react-intl/locale-data/ar'; import './ar.json'; -import deData from 'react-intl/locale-data/de'; import frData from 'react-intl/locale-data/fr'; import './fr_CA.json'; +import zhData from 'react-intl/locale-data/zh'; +import './zh_CN.json'; export default { 'ar': arData, - 'de': deData, 'fr-ca': frData, + 'zh-cn': zhData, }; `); });