From cf6d30eeee27aad152bd78c0e636d8f8d86bc348 Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Mon, 31 Jul 2023 18:16:45 +0200 Subject: [PATCH] feqt(backend): Ported to site prebuild system --- config/scripts.yaml | 8 +- sites/backend/package.json | 4 +- sites/backend/prebuild.mjs | 14 +++ sites/backend/public/locales/de/.gitkeep | 0 sites/backend/public/locales/en/.gitkeep | 0 sites/backend/public/locales/es/.gitkeep | 0 sites/backend/public/locales/fr/.gitkeep | 0 sites/backend/public/locales/nl/.gitkeep | 0 sites/backend/scripts/prebuild-i18n.mjs | 142 ----------------------- sites/backend/scripts/prebuild.mjs | 3 - sites/shared/prebuild/i18n.mjs | 18 ++- 11 files changed, 33 insertions(+), 156 deletions(-) create mode 100644 sites/backend/prebuild.mjs delete mode 100644 sites/backend/public/locales/de/.gitkeep delete mode 100644 sites/backend/public/locales/en/.gitkeep delete mode 100644 sites/backend/public/locales/es/.gitkeep delete mode 100644 sites/backend/public/locales/fr/.gitkeep delete mode 100644 sites/backend/public/locales/nl/.gitkeep delete mode 100644 sites/backend/scripts/prebuild-i18n.mjs delete mode 100644 sites/backend/scripts/prebuild.mjs diff --git a/config/scripts.yaml b/config/scripts.yaml index c29fb1c0c6f..d26cbd7e176 100644 --- a/config/scripts.yaml +++ b/config/scripts.yaml @@ -61,7 +61,7 @@ backend: rmdb: 'node ./scripts/rmdb.mjs' test: 'npx mocha --require mocha-steps tests/index.mjs' vbuild: *vbuild - prebuild: 'node scripts/prebuild.mjs' + prebuild: &sitePrebuild 'node --conditions=internal --experimental-json-modules ./prebuild.mjs' dev: build: &nextBuild 'next build' @@ -71,7 +71,7 @@ dev: develop: *nextDev i18n: "SITE=dev node --conditions=internal ../shared/prebuild/i18n-only.mjs" lint: &nextLint 'next lint' - prebuild: &nextPrebuild 'node --conditions=internal --experimental-json-modules ./prebuild.mjs' + prebuild: *sitePrebuild serve: "pm2 start npm --name 'dev' -- run start" start: &nextStart 'yarn prebuild && yarn dev' @@ -87,7 +87,7 @@ lab: i18n: 'SITE=lab node --conditions=internal ../shared/prebuild/i18n-only.mjs' e2e: &e2e 'yarn playwright test' lint: *nextLint - prebuild: *nextPrebuild + prebuild: *sitePrebuild start: *nextStart org: @@ -98,7 +98,7 @@ org: develop: *nextDev i18n: 'SITE=org node --conditions=internal ../shared/prebuild/i18n-only.mjs' lint: *nextLint - prebuild: *nextPrebuild + prebuild: *sitePrebuild start: *nextStart sanity: diff --git a/sites/backend/package.json b/sites/backend/package.json index c528b33ab4f..66517b85ede 100644 --- a/sites/backend/package.json +++ b/sites/backend/package.json @@ -24,9 +24,9 @@ "rmdb": "node ./scripts/rmdb.mjs", "test": "npx mocha --require mocha-steps tests/index.mjs", "vbuild": "VERBOSE=1 node build.mjs", - "prebuild": "node scripts/prebuild.mjs", + "prebuild": "node --conditions=internal --experimental-json-modules ./prebuild.mjs", "wbuild": "node build.mjs", - "prewbuild": "node scripts/prebuild.mjs" + "prewbuild": "node --conditions=internal --experimental-json-modules ./prebuild.mjs" }, "peerDependencies": {}, "dependencies": { diff --git a/sites/backend/prebuild.mjs b/sites/backend/prebuild.mjs new file mode 100644 index 00000000000..bddd11c3d97 --- /dev/null +++ b/sites/backend/prebuild.mjs @@ -0,0 +1,14 @@ +import { prebuildRunner } from '../shared/prebuild/runner.mjs' + +/* + * This handles the prebuild step for the FreeSewing backend + * It runs via an NPM run script, so in a pure NodeJS context + * + * See `sites/org/prebuild.mjs` for an example with inline comments + */ +prebuildRunner({ + site: 'backend', + prebuild: { + i18n: true, + }, +}) diff --git a/sites/backend/public/locales/de/.gitkeep b/sites/backend/public/locales/de/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sites/backend/public/locales/en/.gitkeep b/sites/backend/public/locales/en/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sites/backend/public/locales/es/.gitkeep b/sites/backend/public/locales/es/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sites/backend/public/locales/fr/.gitkeep b/sites/backend/public/locales/fr/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sites/backend/public/locales/nl/.gitkeep b/sites/backend/public/locales/nl/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/sites/backend/scripts/prebuild-i18n.mjs b/sites/backend/scripts/prebuild-i18n.mjs deleted file mode 100644 index 369f6b1a5d1..00000000000 --- a/sites/backend/scripts/prebuild-i18n.mjs +++ /dev/null @@ -1,142 +0,0 @@ -import fs from 'fs' -import path from 'path' -import rdir from 'recursive-readdir' -import yaml from 'js-yaml' - -/* - * List of supported languages - */ -const locales = ['en', 'es', 'de', 'fr', 'nl'] - -/* - * This is where we configure what folders we should check for - * code-adjacent translation source files - */ -const folders = [path.resolve(path.join('.', 'src'))] - -/* - * Helper method to write out JSON files for translation sources - */ -const writeJson = async (locale, namespace, content) => - fs.writeFileSync( - path.resolve('.', 'public', 'locales', locale, `${namespace}.json`), - JSON.stringify(content) - ) - -/* - * Helper method to get a list of code-adjecent translation files in a folder. - * Will traverse recursively to get all files from a given root folder. - */ -const getI18nFileList = async () => { - const allFiles = [] - for (const dir of folders) { - try { - const dirFiles = await rdir(dir) - allFiles.push(...dirFiles) - } catch (err) { - console.log(err) - return false - } - } - - // Filter out the language files - return allFiles - .filter((file) => locales.map((loc) => `.${loc}.yaml`).includes(file.slice(-8))) - .sort() -} - -/* - * Helper method to get language and namespace from the filename - * - * Parameters: - * - * - filename: The filename or full path + filename - */ -const languageAndNamespaceFromFilename = (file) => { - const chunks = path.basename(file).split('.') - chunks.pop() - - return chunks -} - -/* - * Helper method to load a YAML file from disk - */ -const loadYaml = (file) => { - let data - try { - data = yaml.load(fs.readFileSync(file, 'utf-8')) - } catch (err) { - console.log(err) - } - - return data -} - -/* - * Helper method to build an object of namespaces and their values. - * Includes providing an EN fallback if something is not available in a language. - * - * Parameters: - * - * - files: List of files to process - */ -const filesAsNamespaces = (files) => { - // First build the object - const translations = {} - for (const file of files) { - const [namespace, lang] = languageAndNamespaceFromFilename(file) - if (typeof translations[namespace] === 'undefined') { - translations[namespace] = {} - } - translations[namespace][lang] = loadYaml(file) - } - - return translations -} - -/* - * Helper method to ensure all translations all available in the data - * - * Parameter: - * - * - data: The raw data based on loaded YAML files - */ -const fixData = (rawData) => { - const data = {} - for (const [namespace, nsdata] of Object.entries(rawData)) { - if (typeof nsdata.en === 'undefined') { - throw `No English data for namespace ${namespace}. Bailing out` - } - data[namespace] = { en: nsdata.en } - // Complete other locales - for (const lang of locales.filter((loc) => loc !== 'en')) { - if (typeof nsdata[lang] === 'undefined') data[namespace][lang] = nsdata.en - else { - for (const key of Object.keys(data[namespace].en)) { - if (typeof nsdata[lang][key] === 'undefined') nsdata[lang][key] = nsdata.en[key] - } - data[namespace][lang] = nsdata[lang] - } - } - } - - return data -} - -/* - * The method that does the actual work - */ -export const prebuildI18n = async () => { - // Handle new code-adjacent translations - const files = await getI18nFileList() - const data = filesAsNamespaces(files) - const namespaces = fixData(data) - // Write out code-adjacent source files - for (const locale of locales) { - // Fan out into namespaces - for (const namespace in namespaces) { - writeJson(locale, namespace, namespaces[namespace][locale]) - } - } -} diff --git a/sites/backend/scripts/prebuild.mjs b/sites/backend/scripts/prebuild.mjs deleted file mode 100644 index 72611282cd2..00000000000 --- a/sites/backend/scripts/prebuild.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import { prebuildI18n } from './prebuild-i18n.mjs' - -prebuildI18n() diff --git a/sites/shared/prebuild/i18n.mjs b/sites/shared/prebuild/i18n.mjs index e8f5e99330d..5d4d5fedf30 100644 --- a/sites/shared/prebuild/i18n.mjs +++ b/sites/shared/prebuild/i18n.mjs @@ -12,6 +12,7 @@ import { designs } from '../i18n/designs.mjs' */ const sitesFolder = path.join(fileURLToPath(import.meta.url), '..', '..', '..') export const folders = { + backend: [path.join(sitesFolder, 'backend', 'src', 'templates', 'email')], org: [path.join(sitesFolder, 'org', 'pages'), path.join(sitesFolder, 'org', 'components')], dev: [path.join(sitesFolder, 'dev', 'pages'), path.join(sitesFolder, 'dev', 'components')], lab: [path.join(sitesFolder, 'lab', 'pages'), path.join(sitesFolder, 'lab', 'components')], @@ -42,10 +43,11 @@ const writeJson = async (site, locale, namespace, content) => { * */ const getI18nFileList = async (site, languages) => { - const dirs = [...folders.shared] - if (site === 'org') dirs.push(...folders.org) - if (site === 'dev') dirs.push(...folders.dev) - if (site === 'lab') dirs.push(...folders.lab) + const dirs = [] + if (site === 'org') dirs.push(...folders.org, ...folders.shared) + else if (site === 'dev') dirs.push(...folders.dev, ...folder.shared) + else if (site === 'lab') dirs.push(...folders.lab, ...folders.shared) + else if (site === 'backend') dirs.push(...folders.backend) const allFiles = [] for (const dir of dirs) { @@ -181,10 +183,16 @@ export const prebuildI18n = async (store) => { // Write out code-adjacent source files for (const language of languages) { // Fan out into namespaces - for (const namespace in namespaces) + for (const namespace in namespaces) { writeJson(store.site, language, namespace, namespaces[namespace][language]) + } } + /* + * For backend, this is all we need + */ + if (store.site === 'backend') return (store.i18n = { namespaces }) + /* * Handle design translations */