🌐 Sync Translations #3
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 🌐 Sync Translations | |
| on: | |
| workflow_dispatch: | |
| concurrency: | |
| group: sync-translations | |
| cancel-in-progress: true | |
| # We use a machine account PAT from secrets so workflows are triggered | |
| # the default token is not needed and should be fully restricted | |
| permissions: {} | |
| jobs: | |
| sync_translations: | |
| name: 'Sync Translations with Crowdin' | |
| timeout-minutes: 50 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| ref: 'main' | |
| fetch-depth: 0 | |
| - name: Credential Prep | |
| run: | | |
| echo "CROWDIN_APIv2_PAT=${{ secrets.CROWDIN_APIv2_PAT }}" >> $GITHUB_ENV | |
| shell: bash | |
| - name: GIT Setup | |
| run: | | |
| git config --global user.name 'AnkiDroid Translations' | |
| git config --global user.email 'ankidroid@ankidroid.org' | |
| git checkout -b i18n_sync | |
| git reset --hard origin/main | |
| shell: bash | |
| - name: Get second to latest run time | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| OUTPUT=$(gh run list --workflow sync_translations.yml --json updatedAt | jq -r '.[1].updatedAt') | |
| echo "LATEST_RUN=$OUTPUT" >> $GITHUB_ENV | |
| - name: Calculate seconds passed | |
| id: calc_time | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| const lastRun = new Date(process.env.LATEST_RUN); | |
| const secondsPassed = Math.floor((Date.now() - lastRun.getTime()) / 1000); | |
| const timeLeft = 1800 - secondsPassed > 0 ? 1800 - secondsPassed: 0; | |
| console.log('Seconds to sleep for: ' + timeLeft); | |
| core.setOutput('time_left', timeLeft); | |
| - name: Await CrowdIn API Cooldown If Needed | |
| if: steps.calc_time.outputs.time_left > 0 | |
| run: sleep ${{ steps.calc_time.outputs.time_left }} | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| - name: Install dependencies and build | |
| run: | | |
| cd ./tools/localization | |
| yarn | |
| yarn build | |
| - name: Push translation sources to crowdin | |
| # run: | | |
| # cd ./tools/localization | |
| # yarn start upload | |
| run : echo "Skipping update for testing" | |
| - name: Pull translation updates from crowdin | |
| # run: | | |
| # cd ./tools/localization | |
| # yarn start download | |
| run : echo "Skipping update for testing" | |
| - name: Extract downloaded ankidroid.zip file | |
| # run: | | |
| # cd ./tools/localization | |
| # yarn start extract | |
| run : echo "Skipping update for testing" | |
| - name: Update translation to AnkiDroid res | |
| # run: | | |
| # cd ./tools/localization | |
| # yarn start update | |
| run : echo "Skipping update for testing" | |
| - name: Check for changes and handle Neutral result | |
| id: tr_check | |
| if: always() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { execSync } = require('child_process'); | |
| execSync('git add docs/marketing/localized_description AnkiDroid/src/main/res'); | |
| const status = execSync('git diff --cached --name-only').toString().trim(); | |
| if(!status) { | |
| console.log("No changes detected. Setting status to neutral."); | |
| await github.rest.checks.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| name: 'Sync Translations with Crowdin', | |
| head_sha: context.sha, | |
| status: 'completed', | |
| conclusion: 'neutral', | |
| output: { | |
| title: 'Translation Sync', | |
| summary: 'No translation changes were found on Crowdin to sync' | |
| } | |
| }); | |
| core.setOutput('HAS_CHANGES', 'false'); | |
| } else { | |
| core.setOutput('HAS_CHANGES', 'true'); | |
| execSync("git commit -m 'Updated strings from Crowdin'"); | |
| execSync("git push --set-upstream origin +i18n_sync"); | |
| console.log("Changes pushed to i18n_sync branch"); | |
| } | |
| - name: Create PR for strings changes if needed | |
| if: steps.tr_check.outputs.HAS_CHANGES == 'true' | |
| uses: actions/github-script@v9 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const now = new Date(); | |
| // Date format used: YYYY/MM/DD HH:MM , UTC time(ex: 2023/01/13 08:38) | |
| const formattedDate = | |
| now.getUTCFullYear() + "/" + | |
| ("0" + (now.getUTCMonth() + 1)).slice(-2) + "/" + | |
| ("0" + now.getUTCDate()).slice(-2) + " " + | |
| ("0" + now.getUTCHours()).slice(-2) + ":" + | |
| ("0" + now.getUTCMinutes()).slice(-2); | |
| try { | |
| await github.rest.pulls.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: "Updated strings from Crowdin " + formattedDate, | |
| head: "i18n_sync", | |
| base: "main", | |
| body: "Contains the newest strings changes from Crowdin.\n\nhttps://crowdin.com/project/ankidroid/activity-stream\n\n[Re-sync translations](https://github.com/ankidroid/Anki-Android/actions/workflows/sync_translations.yml)", | |
| maintainer_can_modify: true | |
| }); | |
| } catch(err) { | |
| if (err.status === 422) { | |
| console.log("A PR containing translations sync already exists!"); | |
| } else { | |
| console.log("Unexpected error creating pull request: " + err); | |
| throw err; | |
| } | |
| } |