From 9f21317a30ecf9fa9db1c14face983c6e23ef1e7 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Sat, 21 Sep 2019 13:31:33 -0300 Subject: [PATCH] Verify locales on CI (#7199) * Add '--quiet' flag to verify locales script The `--quiet` flag reduces the console output to just the essential information for running in a CI environment. For each locale, it will print the number of unused messages (if any). * Add `verify-locales` script to lint CI job The locales are now verified as part of the lint CI job. Any unused messages detected will result in the job failing. --- .circleci/config.yml | 5 +- development/verify-locale-strings.js | 70 ++++++++++++++-------------- package.json | 1 + 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 91a4c62b6..35fa2d9e4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -164,8 +164,11 @@ jobs: - attach_workspace: at: . - run: - name: Test + name: Lint command: yarn lint + - run: + name: Verify locales + command: yarn verify-locales --quiet test-deps: docker: diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index b9e8a90d4..aa0c4503f 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -4,7 +4,7 @@ // // usage: // -// node app/scripts/verify-locale-strings.js [] [--fix] +// node app/scripts/verify-locale-strings.js [] [--fix] [--quiet] // // This script will validate that locales have no unused messages. It will check // the English locale against string literals found under `ui/`, and it will check @@ -16,40 +16,44 @@ // The if the optional '--fix' parameter is given, locales will be automatically // updated to remove any unused messages. // +// The optional '--quiet' parameter reduces the verbosity of the output, printing +// just a single summary of results for each locale verified +// // ////////////////////////////////////////////////////////////////////////////// const fs = require('fs') const path = require('path') const { promisify } = require('util') +const log = require('loglevel') const matchAll = require('string.prototype.matchall').getPolyfill() const localeIndex = require('../app/_locales/index.json') const readdir = promisify(fs.readdir) const readFile = promisify(fs.readFile) const writeFile = promisify(fs.writeFile) -console.log('Locale Verification') +log.setDefaultLevel('info') let fix = false let specifiedLocale -if (process.argv[2] === '--fix') { - fix = true - specifiedLocale = process.argv[3] -} else { - specifiedLocale = process.argv[2] - if (process.argv[3] === '--fix') { +for (const arg of process.argv.slice(2)) { + if (arg === '--fix') { fix = true + } else if (arg === '--quiet') { + log.setLevel('error') + } else { + specifiedLocale = arg } } main(specifiedLocale, fix) .catch(error => { - console.error(error) + log.error(error) process.exit(1) }) async function main (specifiedLocale, fix) { if (specifiedLocale) { - console.log(`Verifying selected locale "${specifiedLocale}":\n\n`) + log.info(`Verifying selected locale "${specifiedLocale}":\n`) const locale = localeIndex.find(localeMeta => localeMeta.code === specifiedLocale) const failed = locale.code === 'en' ? await verifyEnglishLocale(fix) : @@ -58,16 +62,16 @@ async function main (specifiedLocale, fix) { process.exit(1) } } else { - console.log('Verifying all locales:\n\n') + log.info('Verifying all locales:\n') let failed = await verifyEnglishLocale(fix) const localeCodes = localeIndex .filter(localeMeta => localeMeta.code !== 'en') .map(localeMeta => localeMeta.code) for (const code of localeCodes) { + log.info() // Separate each locale report by a newline when not in '--quiet' mode const localeFailed = await verifyLocale(code, fix) failed = failed || localeFailed - console.log('\n') } if (failed) { @@ -87,9 +91,9 @@ async function getLocale (code) { return JSON.parse(fileContents) } catch (e) { if (e.code === 'ENOENT') { - console.log('Locale file not found') + log.error('Locale file not found') } else { - console.log(`Error opening your locale ("${code}") file: `, e) + log.error(`Error opening your locale ("${code}") file: `, e) } process.exit(1) } @@ -101,9 +105,9 @@ async function writeLocale (code, locale) { return writeFile(localeFilePath, JSON.stringify(locale, null, 2) + '\n', 'utf8') } catch (e) { if (e.code === 'ENOENT') { - console.log('Locale file not found') + log.error('Locale file not found') } else { - console.log(`Error writing your locale ("${code}") file: `, e) + log.error(`Error writing your locale ("${code}") file: `, e) } process.exit(1) } @@ -119,28 +123,26 @@ async function verifyLocale (code, fix = false) { const englishEntryCount = Object.keys(englishLocale).length const coveragePercent = 100 * (englishEntryCount - missingItems.length) / englishEntryCount - console.log(`Status of **${code}** ${coveragePercent.toFixed(2)}% coverage:`) - if (extraItems.length) { - console.log('\nExtra items that should not be localized:') + console.log(`**${code}**: ${extraItems.length} unused messages`) + log.info('Extra items that should not be localized:') extraItems.forEach(function (key) { - console.log(` - [ ] ${key}`) + log.info(` - [ ] ${key}`) }) } else { - // console.log(` all ${counter} strings declared in your locale ("${code}") were found in the english one`) + log.info(`**${code}**: ${extraItems.length} unused messages`) } + log.info(`${coveragePercent.toFixed(2)}% coverage`) if (missingItems.length) { - console.log(`\nMissing items not present in localized file:`) + log.info(`Missing items not present in localized file:`) missingItems.forEach(function (key) { - console.log(` - [ ] ${key}`) + log.info(` - [ ] ${key}`) }) - } else { - // console.log(` all ${counter} english strings were found in your locale ("${code}")!`) } if (!extraItems.length && !missingItems.length) { - console.log('Full coverage : )') + log.info('Full coverage : )') } if (extraItems.length > 0) { @@ -174,18 +176,18 @@ async function verifyEnglishLocale (fix = false) { const unusedMessages = englishMessages .filter(message => !messageExceptions.includes(message) && !usedMessages.has(message)) - console.log(`Status of **English (en)** ${unusedMessages.length} unused messages:`) - if (unusedMessages.length === 0) { - console.log('Full coverage : )') + if (unusedMessages.length) { + console.log(`**en**: ${unusedMessages.length} unused messages`) + log.info(`Messages not present in UI:`) + unusedMessages.forEach(function (key) { + log.info(` - [ ] ${key}`) + }) + } else { + log.info('Full coverage : )') return false } - console.log(`\nMessages not present in UI:`) - unusedMessages.forEach(function (key) { - console.log(` - [ ] ${key}`) - }) - if (unusedMessages.length > 0 && fix) { const newLocale = Object.assign({}, englishLocale) for (const key of unusedMessages) { diff --git a/package.json b/package.json index 74f6b3e4c..9334c1914 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "lint:fix": "eslint . --ext js,json --fix", "lint:changed": "{ git ls-files --others --exclude-standard ; git diff-index --name-only --diff-filter=d HEAD ; } | grep --regexp='[.]js$' --regexp='[.]json$' | tr '\\n' '\\0' | xargs -0 eslint", "lint:changed:fix": "{ git ls-files --others --exclude-standard ; git diff-index --name-only --diff-filter=d HEAD ; } | grep --regexp='[.]js$' --regexp='[.]json$' | tr '\\n' '\\0' | xargs -0 eslint --fix", + "verify-locales": "node ./development/verify-locale-strings.js", "mozilla-lint": "addons-linter dist/firefox", "watch": "cross-env METAMASK_ENV=test mocha --watch --require test/setup.js --reporter min --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\"", "devtools:react": "react-devtools",