From 9aaa1289ad2e871c57f6854afe887091a26d851f Mon Sep 17 00:00:00 2001 From: Paul Wackerow <54227730+wackerow@users.noreply.github.com> Date: Mon, 15 Apr 2024 09:32:52 -0700 Subject: [PATCH 1/7] feat: add wordsNeedingReview report script --- .gitignore | 3 + package.json | 1 + .../crowdin/reports/wordsNeedingReview.ts | 63 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 src/scripts/crowdin/reports/wordsNeedingReview.ts diff --git a/.gitignore b/.gitignore index 5672e0aff4c..41837deac4e 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ robots.txt # vscode workplace configuration .vscode + +# Crowdin report output +src/data/crowdin/report.csv \ No newline at end of file diff --git a/package.json b/package.json index 804e45613c6..ea974f22cc0 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "crowdin-clean": "rm -rf .crowdin && mkdir .crowdin", "crowdin-import": "ts-node src/scripts/crowdin-import.ts", "events-import": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/events-import.ts", + "crowdin-needs-review": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/crowdin/reports/wordsNeedingReview.ts", "markdown-checker": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/markdownChecker.ts" }, "dependencies": { diff --git a/src/scripts/crowdin/reports/wordsNeedingReview.ts b/src/scripts/crowdin/reports/wordsNeedingReview.ts new file mode 100644 index 00000000000..424c0e77496 --- /dev/null +++ b/src/scripts/crowdin/reports/wordsNeedingReview.ts @@ -0,0 +1,63 @@ +import fs from "fs" +import path from "path" + +import i18n from "../../../../i18n.config.json" +import dirs from "../../../data/crowdin/translation-buckets-dirs.json" +import { CROWDIN_API_MAX_LIMIT } from "../../../lib/constants" +import crowdinClient from "../api-client/crowdinClient" + +type SummaryItem = [code: string, bucket: string, needsReview: number] + +async function main() { + const projectId = Number(process.env.CROWDIN_PROJECT_ID) || 363359 + + const reportSummary = [] as SummaryItem[] + + const directories = dirs.sort((a, b) => a.name.localeCompare(b.name)) + + // Loop through list of content buckets (dirs) + for (const dir of directories) { + console.log(`Processing: ${dir.name}...`) + + // Get translation progress for bucket (dir.id) in all languages + const { data } = + await crowdinClient.translationStatusApi.getDirectoryProgress( + projectId, + dir.id, + { limit: CROWDIN_API_MAX_LIMIT } + ) + + // Loop through supported languages + i18n.forEach(({ crowdinCode }) => { + const match = data.find( + ({ data: { languageId } }) => languageId === crowdinCode + ) + if (!match) return + const { words, translationProgress } = match.data + if (translationProgress < 100) return + const needsReview = words.translated - words.approved + if (needsReview === 0) return + // If match, 100% translation progress, and not full reviewed, add to summary + reportSummary.push([crowdinCode, dir.name, needsReview]) + }) + } + + // Transform to çsv string + const csvArray = reportSummary.map((item) => item.join(",")) + // Insert header names at beginning of csv array + csvArray.unshift("Language,Bucket Name,Words needing review") + const csv = csvArray.join("\n") + + // Write csv to file to fs + const csvPath = path.resolve(process.cwd(), "src/data/crowdin/report.csv") + fs.writeFileSync(csvPath, csv) + + // Log summary + console.log("\nReport summary:\n") + console.log(csv) + console.log(`\n✅ Report saved to ${csvPath}`) +} + +main() + +export default main From 88050824183c7135913f0bedab72b18b90c2cf33 Mon Sep 17 00:00:00 2001 From: Paul Wackerow <54227730+wackerow@users.noreply.github.com> Date: Mon, 15 Apr 2024 09:58:57 -0700 Subject: [PATCH 2/7] feat: add instructions for use --- src/scripts/crowdin/reports/wordsNeedingReview.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/scripts/crowdin/reports/wordsNeedingReview.ts b/src/scripts/crowdin/reports/wordsNeedingReview.ts index 424c0e77496..bf8df307ec5 100644 --- a/src/scripts/crowdin/reports/wordsNeedingReview.ts +++ b/src/scripts/crowdin/reports/wordsNeedingReview.ts @@ -8,6 +8,15 @@ import crowdinClient from "../api-client/crowdinClient" type SummaryItem = [code: string, bucket: string, needsReview: number] +/** + * Generates a report of words needing review for each content bucket in all languages. + * Report in CSV format with columns: Language, Bucket Name, Words needing review. + * To run: + * - Ensure CROWDIN_API_KEY is set in the .env file (.env.local will not work) + * - Can be run with `yarn crowdin-needs-review` + * - Results are saved to src/data/crowdin/report.csv + * - Report is git ignored, and should not be committed + */ async function main() { const projectId = Number(process.env.CROWDIN_PROJECT_ID) || 363359 From aec408387abad986b3b9811fdf15bc3a3313f50a Mon Sep 17 00:00:00 2001 From: Paul Wackerow <54227730+wackerow@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:05:50 -0700 Subject: [PATCH 3/7] feat: add API key scoping instructions --- src/scripts/crowdin/reports/wordsNeedingReview.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/scripts/crowdin/reports/wordsNeedingReview.ts b/src/scripts/crowdin/reports/wordsNeedingReview.ts index bf8df307ec5..6e9b79a1c6c 100644 --- a/src/scripts/crowdin/reports/wordsNeedingReview.ts +++ b/src/scripts/crowdin/reports/wordsNeedingReview.ts @@ -13,6 +13,12 @@ type SummaryItem = [code: string, bucket: string, needsReview: number] * Report in CSV format with columns: Language, Bucket Name, Words needing review. * To run: * - Ensure CROWDIN_API_KEY is set in the .env file (.env.local will not work) + * 1. https://crowdin.com/settings#api-key + * 2. Click: "New token" + * 3. Give token a name + * 4. Select "Translation Status" under "Projects" for scope + * 5. Click: "Create" and authenticate + * 6. Copy the token to the .env file * - Can be run with `yarn crowdin-needs-review` * - Results are saved to src/data/crowdin/report.csv * - Report is git ignored, and should not be committed From 2df90e0b9bc0018de4be9d3aaec0b35f5c9fdbc6 Mon Sep 17 00:00:00 2001 From: Paul Wackerow <54227730+wackerow@users.noreply.github.com> Date: Mon, 15 Apr 2024 12:33:45 -0700 Subject: [PATCH 4/7] fix: sort csv before output --- src/scripts/crowdin/reports/wordsNeedingReview.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/scripts/crowdin/reports/wordsNeedingReview.ts b/src/scripts/crowdin/reports/wordsNeedingReview.ts index 6e9b79a1c6c..b4e3e2f179a 100644 --- a/src/scripts/crowdin/reports/wordsNeedingReview.ts +++ b/src/scripts/crowdin/reports/wordsNeedingReview.ts @@ -57,8 +57,12 @@ async function main() { }) } + // Sort first by language code, then by bucket name + const sorted = reportSummary.sort((a, b) => + a[0] === b[0] ? a[1].localeCompare(b[1]) : a[0].localeCompare(b[0]) + ) // Transform to çsv string - const csvArray = reportSummary.map((item) => item.join(",")) + const csvArray = sorted.map((item) => item.join(",")) // Insert header names at beginning of csv array csvArray.unshift("Language,Bucket Name,Words needing review") const csv = csvArray.join("\n") From cf64955321ea16bbd1bd72af354cdaae448b0dbd Mon Sep 17 00:00:00 2001 From: Paul Wackerow <54227730+wackerow@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:57:40 -0700 Subject: [PATCH 5/7] style: use semantic naming Co-Authored-By: Joshua <62268199+minimalsm@users.noreply.github.com> --- .gitignore | 2 +- package.json | 2 +- .../{wordsNeedingReview.ts => generateReviewReport.ts} | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) rename src/scripts/crowdin/reports/{wordsNeedingReview.ts => generateReviewReport.ts} (93%) diff --git a/.gitignore b/.gitignore index 41837deac4e..c40d12e72c2 100644 --- a/.gitignore +++ b/.gitignore @@ -54,4 +54,4 @@ robots.txt .vscode # Crowdin report output -src/data/crowdin/report.csv \ No newline at end of file +src/data/crowdin/bucketsAwaitingReviewReport.csv \ No newline at end of file diff --git a/package.json b/package.json index ea974f22cc0..90ec31d84a1 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "crowdin-clean": "rm -rf .crowdin && mkdir .crowdin", "crowdin-import": "ts-node src/scripts/crowdin-import.ts", "events-import": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/events-import.ts", - "crowdin-needs-review": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/crowdin/reports/wordsNeedingReview.ts", + "crowdin-needs-review": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/crowdin/reports/generateReviewReport.ts", "markdown-checker": "ts-node -O '{ \"module\": \"commonjs\" }' src/scripts/markdownChecker.ts" }, "dependencies": { diff --git a/src/scripts/crowdin/reports/wordsNeedingReview.ts b/src/scripts/crowdin/reports/generateReviewReport.ts similarity index 93% rename from src/scripts/crowdin/reports/wordsNeedingReview.ts rename to src/scripts/crowdin/reports/generateReviewReport.ts index b4e3e2f179a..e0cc443e265 100644 --- a/src/scripts/crowdin/reports/wordsNeedingReview.ts +++ b/src/scripts/crowdin/reports/generateReviewReport.ts @@ -20,7 +20,7 @@ type SummaryItem = [code: string, bucket: string, needsReview: number] * 5. Click: "Create" and authenticate * 6. Copy the token to the .env file * - Can be run with `yarn crowdin-needs-review` - * - Results are saved to src/data/crowdin/report.csv + * - Results are saved to src/data/crowdin/bucketsAwaitingReviewReport.csv * - Report is git ignored, and should not be committed */ async function main() { @@ -68,7 +68,10 @@ async function main() { const csv = csvArray.join("\n") // Write csv to file to fs - const csvPath = path.resolve(process.cwd(), "src/data/crowdin/report.csv") + const csvPath = path.resolve( + process.cwd(), + "src/data/crowdin/bucketsAwaitingReviewReport.csv" + ) fs.writeFileSync(csvPath, csv) // Log summary From 64981779112ac4323a6db37704ea51accb11a59c Mon Sep 17 00:00:00 2001 From: Paul Wackerow <54227730+wackerow@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:12:19 -0700 Subject: [PATCH 6/7] feat: add dispatchable workflow saves results as action artifact --- .github/workflows/generate-review-report.yml | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/generate-review-report.yml diff --git a/.github/workflows/generate-review-report.yml b/.github/workflows/generate-review-report.yml new file mode 100644 index 00000000000..ba05b71b659 --- /dev/null +++ b/.github/workflows/generate-review-report.yml @@ -0,0 +1,34 @@ +name: Generate Crowdin translation review report + +on: + workflow_dispatch: + +jobs: + generate_report: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Install dependencies + run: yarn install + + - name: Install ts-node + run: yarn global add ts-node + + - name: Run script + run: npx ts-node -O '{"module":"commonjs"}' ./src/scripts/crowdin/reports/generateReviewReport.ts + env: + CROWDIN_API_KEY: ${{ secrets.CROWDIN_TRANSLATION_STATUS_API_KEY }} + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + + - name: Upload output as artifact + uses: actions/upload-artifact@v2 + with: + name: output + path: ./src/data/crowdin/bucketsAwaitingReviewReport.csv \ No newline at end of file From b0e102bddb5eb88c407104d47d43af0193816f99 Mon Sep 17 00:00:00 2001 From: Paul Wackerow <54227730+wackerow@users.noreply.github.com> Date: Mon, 29 Apr 2024 08:13:03 -0700 Subject: [PATCH 7/7] chore: use common crowdin key --- .github/workflows/generate-review-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-review-report.yml b/.github/workflows/generate-review-report.yml index ba05b71b659..8b09e4a0d8c 100644 --- a/.github/workflows/generate-review-report.yml +++ b/.github/workflows/generate-review-report.yml @@ -24,7 +24,7 @@ jobs: - name: Run script run: npx ts-node -O '{"module":"commonjs"}' ./src/scripts/crowdin/reports/generateReviewReport.ts env: - CROWDIN_API_KEY: ${{ secrets.CROWDIN_TRANSLATION_STATUS_API_KEY }} + CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }} CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} - name: Upload output as artifact