diff --git a/package.json b/package.json index f6d162c..624bbaa 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "build": "ng build", "test": "ng test", "lint": "ng lint", - "supportedBrowsers": "(echo module.exports = && browserslist-useragent-regexp --allowHigherVersions) > src/assets/supportedBrowsers.js" + "supportedBrowsers": "(echo module.exports = && browserslist-useragent-regexp --allowHigherVersions) > src/assets/supportedBrowsers.js", + "tx": "node scripts/tx.js" }, "dependencies": { "@angular/animations": "^17.3.5", @@ -53,11 +54,13 @@ "@angular/compiler-cli": "^17.3.5", "@angular/language-service": "^17.3.5", "@chiragrupani/karma-chromium-edge-launcher": "^2.3.1", + "@transifex/api": "^7.1.0", "@types/jasmine": "~5.1.4", "@types/jasminewd2": "~2.0.13", "@types/node": "~20.12.7", "@typescript-eslint/eslint-plugin": "7.7.0", "@typescript-eslint/parser": "7.7.0", + "axios": "^1.6.8", "browserslist": "^4.23.0", "browserslist-useragent-regexp": "^4.1.3", "eslint": "^8.57.0", diff --git a/scripts/tx.js b/scripts/tx.js new file mode 100644 index 0000000..b665a68 --- /dev/null +++ b/scripts/tx.js @@ -0,0 +1,87 @@ +const fs = require('fs'); +const process = require('process'); +const path = require('path'); +const { transifexApi } = require('@transifex/api'); +const axios = require('axios'); + +// Exit early if the auth token is not set +if (!process.env.TX_TOKEN) { + console.log("TX_TOKEN is not set"); + process.exit(1); +} + +// Check if there is an argument +if (process.argv.length < 3 || (process.argv[2] != 'upload' && process.argv[2] != 'download')) { + console.log("Action is not valid, please use either 'upload' or 'download'"); + process.exit(1); +} + +// Set up the Transifex API +transifexApi.setup({auth: process.env.TX_TOKEN}); + + +function getPercentage(attributes) { + return (parseFloat(attributes.translated_strings) / parseFloat(attributes.total_strings)) * 100; +} + + +async function uploadFiles(resource, languages) { + for (const lang of languages) { + const filename = path.join('src', 'assets', 'i18n', `${lang.attributes.code}.json`) + if (!fs.existsSync(filename)) { + continue; + } + 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) { + for (const lang of languages) { + 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() { + 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 (process.argv[2] == 'upload') { + await uploadFiles(resource, languages.data); + } + else if (process.argv[2] == 'download') { + await downloadFiles(org, proj, resource, languages.data); + } +} + +main(); diff --git a/yarn.lock b/yarn.lock index 09cf550..304e488 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2840,6 +2840,13 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.1.tgz#621270c02c0a5d4f4669eb1caa9723c91cf201de" integrity sha512-dzJtaDAAoXx4GCOJpbB2eG/Qj8VDpdwkLsWGzGm+0L7E8/434RyMbAHmk9ubXWVAb9nXmc44jUf8GKqVDiKezg== +"@transifex/api@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@transifex/api/-/api-7.1.0.tgz#aa0f3f3fb1764bad6d46c44ec04d8f41c3cb3b7a" + integrity sha512-qXH1H8+7nDj4KcNlcxzpU9DGj6WSfap4EgSEQnF2ALRsyHAdfg49ne1+I7aBFaqdnR3tsFK6KTr/lVUCybUmLQ== + dependencies: + core-js "^3.35.0" + "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" @@ -3665,7 +3672,7 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -axios@^1.6.0: +axios@^1.6.0, axios@^1.6.8: version "1.6.8" resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==