From db7a2a4ca0e5fb55e097752a66087932a64c492e Mon Sep 17 00:00:00 2001 From: Cori Hudson Date: Wed, 5 Oct 2022 18:19:44 -0400 Subject: [PATCH 1/3] feat: migrate help utils to v3 api --- lib/transifex.js | 31 ++++++++++++++++++++++++++++++- scripts/help-utils.js | 35 +++++++++-------------------------- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/lib/transifex.js b/lib/transifex.js index 8ed28a33..271b6da7 100644 --- a/lib/transifex.js +++ b/lib/transifex.js @@ -103,6 +103,35 @@ const txResources = async function (project) { return slugs; }; +/** + * @param {string} project - project slug (for example) + * @returns {object[]} - array of resource objects + */ +const txResourcesObjects = async function (project) { + const resources = await transifexApi.Resource.filter({ + project: `o:${ORG_NAME}:p:${project}` + }); + + await resources.fetch(); + return resources.data; +}; + +/** + * Gets available languages for a project + * @param {string} slug - project slug (for example, "scratch-editor") + * @returns {Promise} - list of language codes + */ +const txAvailableLanguages = async function (slug) { + const project = await transifexApi.Project.get({ + organization: `o:${ORG_NAME}`, + slug: slug + }); + + const languages = await project.fetch('languages'); + return languages.data.map(l => l.code); + +}; + /** * Uploads English source strings to a resource in transifex * @param {string} project - project slug (for example, "scratch-editor") @@ -160,4 +189,4 @@ const txCreateResource = async function (project, {slug, name, i18nType, sourceS } }; -module.exports = {txPull, txPush, txResources, txCreateResource}; +module.exports = {txPull, txPush, txResources, txResourcesObjects, txCreateResource, txAvailableLanguages}; diff --git a/scripts/help-utils.js b/scripts/help-utils.js index 2921a354..800a42ad 100644 --- a/scripts/help-utils.js +++ b/scripts/help-utils.js @@ -5,19 +5,14 @@ * Helper functions for syncing Freshdesk knowledge base articles with Transifex */ -const transifex = require('transifex'); const FreshdeskApi = require('./freshdesk-api.js'); -const util = require('util'); const fs = require('fs'); const fsPromises = fs.promises; const mkdirp = require('mkdirp'); +const {txPull, txResourcesObjects, txAvailableLanguages} = require('../lib/transifex.js'); const FD = new FreshdeskApi('https://mitscratch.freshdesk.com', process.env.FRESHDESK_TOKEN); const TX_PROJECT = 'scratch-help'; -const TX = new transifex({ - project_slug: TX_PROJECT, - credential: 'api:' + process.env.TX_TOKEN -}); const freshdeskLocale = locale => { // map between Transifex locale and Freshdesk. Two letter codes are usually fine @@ -38,10 +33,6 @@ const freshdeskLocale = locale => { return localeMap[locale] || locale; }; -// Promisify Transifex async/callbacks to make them easier to use` -const getResources = util.promisify(TX.resourcesSetMethod.bind(TX)); -const getResourceInfo = util.promisify(TX.resourcesInstanceMethods.bind(TX)); -const getTranslation = util.promisify(TX.translationInstanceMethod.bind(TX)); /** * Pull metadata from Transifex for the scratch-help project @@ -51,17 +42,13 @@ const getTranslation = util.promisify(TX.translationInstanceMethod.bind(TX)); * names: array of tx resources corresponding to the Freshdesk metadata */ exports.getInputs = async () => { - const resources = await getResources(TX_PROJECT); + const resources = await txResourcesObjects(TX_PROJECT); + const languages = await txAvailableLanguages(TX_PROJECT); // there are three types of resources differentiated by the file type const folders = resources.filter(resource => resource.i18n_type === 'STRUCTURED_JSON'); const names = resources.filter(resource => resource.i18n_type === 'KEYVALUEJSON'); // ignore the yaml type because it's not possible to update via API - // Lookup available languages by getting metadata for a resource, they all have the - // same set of languages, so it doesn't matter which one you get - const resourceInfo = await getResourceInfo(TX_PROJECT, resources[0].slug, true); - const languages = resourceInfo.available_languages.map(l => l.code); - return Promise.all([languages, folders, names]); // eslint-disable-line no-undef }; @@ -139,11 +126,9 @@ const serializeFolderSave = async (json, locale) => { * @return {Promise} [description] */ exports.localizeFolder = async (folder, locale) => { - getTranslation(TX_PROJECT, folder.slug, locale, {mode: 'default'}) + txPull(TX_PROJECT, folder.slug, locale, {mode: 'default'}) .then(data => { - const json = JSON.parse(data); - - serializeFolderSave(json, locale); + serializeFolderSave(data, locale); }) .catch((e) => { process.stdout.write(`Error processing ${folder.slug}, ${locale}: ${e.message}\n`); @@ -159,12 +144,11 @@ exports.localizeFolder = async (folder, locale) => { */ exports.debugFolder = async (folder, locale) => { mkdirp.sync('tmpDebug'); - getTranslation(TX_PROJECT, folder.slug, locale, {mode: 'default'}) + txPull(TX_PROJECT, folder.slug, locale, {mode: 'default'}) .then(data => { - const json = JSON.parse(data); fsPromises.writeFile( `tmpDebug/${folder.slug}_${locale}.json`, - JSON.stringify(json, null, 2) + JSON.stringify(data, null, 2) ); }) .catch((e) => { @@ -181,10 +165,9 @@ exports.debugFolder = async (folder, locale) => { * @return {Promise} [description] */ exports.localizeNames = async (resource, locale) => { - getTranslation(TX_PROJECT, resource.slug, locale, {mode: 'default'}) + txPull(TX_PROJECT, resource.slug, locale, {mode: 'default'}) .then(data => { - const json = JSON.parse(data); - serializeNameSave(json, resource, locale); + serializeNameSave(data, resource, locale); }) .catch((e) => { process.stdout.write(`Error saving ${resource.slug}, ${locale}: ${e.message}\n`); From 2907601077cfa890984f905e0c591be42d3c0280 Mon Sep 17 00:00:00 2001 From: Cori Hudson Date: Thu, 6 Oct 2022 17:42:08 -0400 Subject: [PATCH 2/3] feat: migrate push help script --- scripts/tx-push-help.js | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/scripts/tx-push-help.js b/scripts/tx-push-help.js index a9d60d37..d167aaad 100755 --- a/scripts/tx-push-help.js +++ b/scripts/tx-push-help.js @@ -6,6 +6,7 @@ */ const args = process.argv.slice(2); +const {txPush, txCreateResource} = require('../lib/transifex.js'); const usage = ` Pull knowledge base articles from Freshdesk and push to scratch-help project on transifex. Usage: @@ -22,15 +23,10 @@ if (!process.env.TX_TOKEN || !process.env.FRESHDESK_TOKEN || args.length > 0) { process.exit(1); } -import transifex from 'transifex'; import FreshdeskApi from './freshdesk-api.js'; const FD = new FreshdeskApi('https://mitscratch.freshdesk.com', process.env.FRESHDESK_TOKEN); const TX_PROJECT = 'scratch-help'; -const TX = new transifex({ - project_slug: TX_PROJECT, - credential: 'api:' + process.env.TX_TOKEN -}); const categoryNames = {}; const folderNames = {}; @@ -46,33 +42,31 @@ const makeTxId = item => { return `${item.name.replace(/[ /]/g, '').slice(0, 30)}_${item.id}`; }; -const txPushResource = (name, articles, type) => { +const txPushResource = async (name, articles, type) => { const resourceData = { slug: name, name: name, - priority: 0, // default to normal priority i18n_type: type, - content: '{}' + priority: 0, // default to normal priority + content: articles }; - TX.resourceCreateMethod(TX_PROJECT, resourceData, (err) => { - // ignore already created error report others - if (err && err.response.statusCode !== 400) { + + try { + await txPush(TX_PROJECT, name, articles); + } catch (err) { + if (err.statusCode !== 404) { process.stdout.write(`Transifex Error: ${err.message}\n`); process.stdout.write( `Transifex Error ${err.response.statusCode.toString()}: ${err.response.body}\n`); process.exitCode = 1; return; } - // update Transifex with English source - TX.uploadSourceLanguageMethod(TX_PROJECT, name, - {content: JSON.stringify(articles, null, 2)}, (err1) => { - if (err1) { - process.stdout.write(`Transifex Error:${err1.name}, ${err1.message}\n`); - process.stdout.write(`Transifex Error:${err1.toString()}\n`); - process.exitCode = 1; - } - }); - }); + + // file not found - create it, but also give message + if (err.statusCode === 404) { + await txCreateResource(TX_PROJECT, resourceData); + } + } }; /** From 113c0c095e1e7a4a6f8a678d11d67f35221b23ca Mon Sep 17 00:00:00 2001 From: Cori Hudson Date: Fri, 21 Oct 2022 15:27:34 -0400 Subject: [PATCH 3/3] fix: add missing stdout --- scripts/tx-push-help.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/tx-push-help.js b/scripts/tx-push-help.js index d167aaad..7109b699 100755 --- a/scripts/tx-push-help.js +++ b/scripts/tx-push-help.js @@ -63,6 +63,7 @@ const txPushResource = async (name, articles, type) => { } // file not found - create it, but also give message + process.stdout.write(`Transifex Resource not found, creating: ${name}\n`); if (err.statusCode === 404) { await txCreateResource(TX_PROJECT, resourceData); }