const fs = require('fs'); const process = require('process'); const path = require('path'); const { parseArgs } = require('util'); const { transifexApi } = require('@transifex/api'); const axios = require('axios'); // Parse the command line arguments function parseCliArgs() { const options = { token: { type: 'string', short: 't' }, verbose: { type: 'boolean', short: 'v', default: false }, help: { type: 'boolean', short: 'h', default: false } }; const { values, positionals } = parseArgs({options: options, allowPositionals: true}); if (values.help) { console.log(`usage: tx [-h|--help] [-v|--verbose] [-t|--token TOKEN] positional arguments: action the action to perform, one of 'upload' or 'download' options: -h, --help show this help message and exit -e, --verbose show extra logging messages -t TOKEN, --token TOKEN specify a Transifex API token, can also use the TX_TOKEN environment variable `); process.exit(0); } if (!values.token && !process.env.TX_TOKEN) { console.error("ERROR: Neither --token nor TX_TOKEN was set"); process.exit(1); } else if (!values.token && process.env.TX_TOKEN) { values.token = process.env.TX_TOKEN; } if (positionals.length < 1 || (positionals[0] != 'upload' && positionals[0] != 'download')) { console.error("ERROR: Action is not valid, please use either 'upload' or 'download'"); process.exit(1); } return {token: values.token, action: positionals[0], verbose: values.verbose}; } function getPercentage(attributes) { return (parseFloat(attributes.translated_strings) / parseFloat(attributes.total_strings)) * 100; } async function uploadFiles(resource, languages, verbose) { for (const lang of languages) { const filename = path.join('src', 'assets', 'i18n', `${lang.attributes.code}.json`) if (!fs.existsSync(filename)) { continue; } if (verbose) { console.log(`Reading ${lang.attributes.code}.json...`); } const content = fs.readFileSync(filename); console.log(`Uploading ${lang.attributes.code}.json...`); await transifexApi.ResourceTranslationsAsyncUpload.upload({ resource: resource, language: lang, content: content.toString() }); } } async function downloadFiles(org, project, resource, languages, verbose) { for (const lang of languages) { if (verbose) { console.log(`Checking completeness of ${lang.attributes.code}.json...`); } const trs = await transifexApi.ResourceLanguageStats.get({ project: project, resource: resource, language: lang }); if (getPercentage(trs.attributes) < 50) { continue; } console.log(`Downloading ${lang.attributes.code}.json...`); const url = await transifexApi.ResourceTranslationsAsyncDownload.download({ resource: resource, language: lang }); const response = await axios.get(url); if (response.status == 200) { fs.writeFileSync(path.join('src', 'assets', 'i18n', `${lang.attributes.code}.json`), JSON.stringify(response.data, null, 2)); } else { console.log(`Error: ${response.statusText}`); } } } async function main() { // Parse the command line arguments const { token, action, verbose } = parseCliArgs(); // Set up the Transifex API transifexApi.setup({auth: token}); if (verbose) { console.log('Fetching organization, project and languages...'); } const org = await transifexApi.Organization.get({slug: 'openlp'}); const projects = await org.fetch('projects'); const proj = await projects.get({slug: 'web-remote'}); const resource = await transifexApi.Resource.get({project: proj, slug: 'i18n-strings'}); const languages = await proj.fetch('languages'); await languages.fetch(); if (action == 'upload') { await uploadFiles(resource, languages.data, verbose); } else if (action == 'download') { await downloadFiles(org, proj, resource, languages.data, verbose); } } main();