diff --git a/package-lock.json b/package-lock.json index f2340b16..7edd5f07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,8 +28,7 @@ "make-fetch-happen": "^8.0.7", "sync-version": "^1.0.1", "tiny-glob": "^0.2.6", - "web-ext": "^5.5.0", - "webext-tx-fix": "^0.3.3" + "web-ext": "^5.5.0" }, "engines": { "node": ">=10.0.0" @@ -3214,12 +3213,6 @@ "dev": true, "peer": true }, - "node_modules/detect-indent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", - "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", - "dev": true - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -7269,21 +7262,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/neodoc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/neodoc/-/neodoc-2.0.2.tgz", - "integrity": "sha512-NAppJ0YecKWdhSXFYCHbo6RutiX8vOt/Jo3l46mUg6pQlpJNaqc5cGxdrW2jITQm5JIYySbFVPDl3RrREXNyPw==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - } - }, - "node_modules/neodoc/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -7742,21 +7720,6 @@ "word-wrap": "^1.2.3" } }, - "node_modules/ordered-json": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ordered-json/-/ordered-json-0.1.1.tgz", - "integrity": "sha512-qw4OYAxofa+WAZAP90eoXftAErUCjs8OII5ddDzKAZBsPMpQvWEIvuKCmUgGV22Cyd3/bT6i12KeuBBZixThDg==", - "dev": true, - "dependencies": { - "ordered-object": "^0.2.0" - } - }, - "node_modules/ordered-object": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/ordered-object/-/ordered-object-0.2.3.tgz", - "integrity": "sha512-UKBtJiO7PsKqAAenewZ/moHQIRbcjZ4HE0J/+RyzgnpCTIn5ZLe3N2izno1kViTCXtHB4xuewjPgYLEiuS6t5A==", - "dev": true - }, "node_modules/os-locale": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", @@ -11683,17 +11646,6 @@ "resolved": "https://registry.npmjs.org/webext-launch-web-auth-flow/-/webext-launch-web-auth-flow-0.1.1.tgz", "integrity": "sha512-e8G0W+Js6P1i/aD0XoSkWfodhdTf01fiqDQk+wcSkVPkzmqDxhzKkBpJ1Y2dz3pR4Ocve7z/yx+mMI8jsRAiPg==" }, - "node_modules/webext-tx-fix": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/webext-tx-fix/-/webext-tx-fix-0.3.3.tgz", - "integrity": "sha512-qNWk8y5NwFDdNR4cdwc001PVPsgOmG1hfH1n4u2AQhpTs08C9TH2KXw68gGA3Pvros9YFEogn2fk9C6vGbTcgw==", - "dev": true, - "dependencies": { - "detect-indent": "^6.0.0", - "neodoc": "^2.0.2", - "ordered-json": "^0.1.1" - } - }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -14703,12 +14655,6 @@ "dev": true, "peer": true }, - "detect-indent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", - "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", - "dev": true - }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -18057,23 +18003,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "neodoc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/neodoc/-/neodoc-2.0.2.tgz", - "integrity": "sha512-NAppJ0YecKWdhSXFYCHbo6RutiX8vOt/Jo3l46mUg6pQlpJNaqc5cGxdrW2jITQm5JIYySbFVPDl3RrREXNyPw==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, "next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -18440,21 +18369,6 @@ "word-wrap": "^1.2.3" } }, - "ordered-json": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ordered-json/-/ordered-json-0.1.1.tgz", - "integrity": "sha512-qw4OYAxofa+WAZAP90eoXftAErUCjs8OII5ddDzKAZBsPMpQvWEIvuKCmUgGV22Cyd3/bT6i12KeuBBZixThDg==", - "dev": true, - "requires": { - "ordered-object": "^0.2.0" - } - }, - "ordered-object": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/ordered-object/-/ordered-object-0.2.3.tgz", - "integrity": "sha512-UKBtJiO7PsKqAAenewZ/moHQIRbcjZ4HE0J/+RyzgnpCTIn5ZLe3N2izno1kViTCXtHB4xuewjPgYLEiuS6t5A==", - "dev": true - }, "os-locale": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", @@ -21643,17 +21557,6 @@ "resolved": "https://registry.npmjs.org/webext-launch-web-auth-flow/-/webext-launch-web-auth-flow-0.1.1.tgz", "integrity": "sha512-e8G0W+Js6P1i/aD0XoSkWfodhdTf01fiqDQk+wcSkVPkzmqDxhzKkBpJ1Y2dz3pR4Ocve7z/yx+mMI8jsRAiPg==" }, - "webext-tx-fix": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/webext-tx-fix/-/webext-tx-fix-0.3.3.tgz", - "integrity": "sha512-qNWk8y5NwFDdNR4cdwc001PVPsgOmG1hfH1n4u2AQhpTs08C9TH2KXw68gGA3Pvros9YFEogn2fk9C6vGbTcgw==", - "dev": true, - "requires": { - "detect-indent": "^6.0.0", - "neodoc": "^2.0.2", - "ordered-json": "^0.1.1" - } - }, "webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", diff --git a/package.json b/package.json index 92ea0126..81b05be9 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,12 @@ "make-fetch-happen": "^8.0.7", "sync-version": "^1.0.1", "tiny-glob": "^0.2.6", - "web-ext": "^5.5.0", - "webext-tx-fix": "^0.3.3" + "web-ext": "^5.5.0" }, "scripts": { "lint": "eslint \"**/*.js\" --cache", "test": "npm run lint", - "update-locales": "tx pull --all && webext-tx-fix", + "update-locales": "tx pull --all && node tools/fix-transifex.js", "update-transifex": "tx push -s", "build-vendor": "node tools/build-vendor", "zip": "node tools/zip.js", diff --git a/tools/fix-transifex.js b/tools/fix-transifex.js new file mode 100644 index 00000000..10700c7e --- /dev/null +++ b/tools/fix-transifex.js @@ -0,0 +1,76 @@ +'use strict'; + +const fs = require('fs'); +const fse = require('fs-extra'); + +const DIR = '_locales/'; +const RX_LNG_CODE = /^\w\w(_\w{2,3})?$/; // like `en` or `en_GB` + +const makeFileName = lng => `${DIR}${lng}/messages.json`; +const readLngJson = lng => fse.readJsonSync(makeFileName(lng)); +const sortAlpha = ([a], [b]) => a < b ? -1 : a > b; + +const src = readLngJson('en'); +for (const val of Object.values(src)) { + const {placeholders} = val; + if (placeholders) { + const sorted = {}; + for (const [k, v] of Object.entries(placeholders).sort(sortAlpha)) { + sorted[k] = v; + } + val.placeholders = sorted; + } +} + +let numTotal = 0; +let numFixed = 0; + +for (const /**@type Dirent*/ entry of fs.readdirSync(DIR, {withFileTypes: true})) { + const lng = entry.name; + if (lng !== 'en' && entry.isDirectory() && RX_LNG_CODE.test(lng)) { + numFixed += fixLngFile(lng) ? 1 : 0; + numTotal++; + } +} +console.log(`${numFixed} files fixed out of ${numTotal}`); + +function fixLngFile(lng) { + let numUnknown = 0; + let numUntranslated = 0; + let numVarsFixed = 0; + const json = readLngJson(lng); + const res = {}; + for (const [key, val] of Object.entries(json).sort(sortAlpha)) { + const {placeholders, message} = src[key] || {}; + if (!message) { + numUnknown++; + } else if (!val.message || val.message === message) { + numUntranslated++; + } else { + delete val.description; + if (placeholders && !val.placeholders) { + numVarsFixed++; + val.placeholders = placeholders; + } + res[key] = val; + } + } + const jsonStr = JSON.stringify(json, null, 2); + const resStr = JSON.stringify(res, null, 2); + if (resStr !== jsonStr) { + let err; + if (resStr === '{}') { + fs.rmdirSync(`${DIR}${lng}`, {recursive: true}); + err = 'no translations -> deleted'; + } else { + fse.outputFileSync(makeFileName(lng), resStr + '\n'); + err = [ + numUnknown && `${numUnknown} unknown (dropped)`, + numUntranslated && `${numUntranslated} untranslated (dropped)`, + numVarsFixed && `${numVarsFixed} missing placeholders (restored)`, + ].filter(Boolean).join(', '); + } + if (err) console.log(`${lng}: ${err}`); + return err; + } +}