diff --git a/.github/workflows/sync-translations-poeditor.yml b/.github/workflows/sync-translations-poeditor.yml new file mode 100644 index 0000000000..24bb50da45 --- /dev/null +++ b/.github/workflows/sync-translations-poeditor.yml @@ -0,0 +1,202 @@ +name: Sync Translations with POEditor + +on: + push: + branches: + - feat/translation-poeditor-integration + +permissions: + contents: write + pull-requests: write + +jobs: + sync-translations: + runs-on: ubuntu-latest + env: + BASE_BRANCH: "master" + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + + - name: Install dependencies + run: npm ci + + - name: Configure Git + run: | + git config user.name ${{ secrets.GIT_BOT_USERNAME }} + git config user.email ${{ secrets.GIT_BOT_EMAIL }} + git remote set-url origin https://${{ secrets.GIT_BOT_ACCESS_TOKEN }}@github.com/Aam-Digital/ndb-core.git + + - name: Create or update branch for translations + run: | + branch_name="chore/update-poeditor-translations" + + # Check if branch exists on remote + if git ls-remote --exit-code origin $branch_name; then + echo "Branch $branch_name already exists. Fetching it..." + git fetch origin $branch_name:$branch_name + + git checkout $branch_name + git pull origin $branch_name + else + echo "Creating new branch $branch_name..." + git checkout -b $branch_name + fi + + - name: Extract i18n keys + run: npm run extract-i18n + + - name: Check if any files changed + run: | + if git diff --quiet; then + echo "No changes detected." + echo "changed=false" >> $GITHUB_ENV + else + echo "Changes detected." + echo "changed=true" >> $GITHUB_ENV + fi + + - name: Commit file changes + if: env.changed == 'true' + run: | + git add src/assets/locale/*.xlf + git commit -m "Update translations: Extracted i18n keys" + + - name: Push changes to master + if: env.changed == 'true' + run: git push origin HEAD + + - name: Upload translations to POEditor + if: env.changed == 'true' + run: | + declare -A files + + # Populate file mappings dynamically + files["en"]="src/assets/locale/messages.xlf" + files["de"]="src/assets/locale/messages.de.xlf" + files["it"]="src/assets/locale/messages.it.xlf" + files["fr"]="src/assets/locale/messages.fr.xlf" + + for lang in "${!files[@]}"; do + echo "Uploading ${files[$lang]} for language $lang" + response=$(curl -s -X POST https://api.poeditor.com/v2/projects/upload \ + -F "api_token=${{ secrets.POEDITOR_API_TOKEN }}" \ + -F "id=${{ secrets.POEDITOR_PROJECT_ID }}" \ + -F "language=$lang" \ + -F "updating=terms_translations" \ + -F "overwrite=1" \ + -F "sync_terms=1" \ + -F "file=@${files[$lang]}") + status=$(echo $response | jq -r '.response.status') + if [ "$status" != "success" ]; then + echo "Error uploading file for $lang: $response" + exit 1 + fi + echo "Waiting for 30 seconds to respect rate limits..." + sleep 30 + done + + - name: Export translations from POEditor + if: env.changed == 'true' + run: | + languages=("en" "fr" "it" "de") + for lang in "${languages[@]}"; do + echo "Exporting translations for language $lang" + response=$(curl -s -X POST https://api.poeditor.com/v2/projects/export \ + -F "api_token=${{ secrets.POEDITOR_API_TOKEN }}" \ + -F "id=${{ secrets.POEDITOR_PROJECT_ID }}" \ + -F "language=$lang" \ + -F "type=xlf") + status=$(echo $response | jq -r '.response.status') + if [ "$status" == "success" ]; then + url=$(echo $response | jq -r '.result.url') + if [ -n "$url" ]; then + echo "Downloading translations for $lang from $url" + if [ "$lang" == "en" ]; then + curl -s -o src/assets/locale/messages.xlf $url + else + curl -s -o src/assets/locale/messages.$lang.xlf $url + fi + else + echo "No URL found for downloading translations for $lang" + exit 1 + fi + else + echo "Error exporting translations for $lang: $response" + exit 1 + fi + echo "Waiting for 30 seconds to respect rate limits..." + sleep 30 + done + + - name: Commit updated translations + if: env.changed == 'true' + run: | + git add src/assets/locale/*.xlf + git commit -m "translations: load latest translations from POEditor" + + - name: Push changes + if: env.changed == 'true' + run: | + git push origin HEAD + + - name: Create Pull Request + if: env.changed == 'true' + uses: actions/github-script@v6 + with: + script: | + const { repo, owner } = context.repo; + const headBranch = 'chore/update-poeditor-translations'; + const baseBranch = process.env.BASE_BRANCH; + + const pulls = await github.rest.pulls.list({ + owner, + repo, + state: 'open', + head: `${owner}:${headBranch}`, + }); + + if (pulls.data.length < 1) { + const diff = await github.rest.repos.compareCommits({ + owner, + repo, + base: baseBranch, + head: headBranch, + }); + + if (diff.data.commits.length === 0) { + return; + } + const result = await github.rest.pulls.create({ + title: 'Update POEditor translations messages', + owner, + repo, + head: headBranch, + base: baseBranch, + body: [ + 'This PR updates translations from POEditor.', + 'Generated by GitHub Actions.' + ].join('\n'), + }); + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: result.data.number, + labels: ['automated pr'], + }); + } else { + const existingPR = pulls.data[0]; + await github.rest.pulls.update({ + owner: owner, + repo: repo, + pull_number: existingPR.number, + body: [ + existingPR.body, + `Updated by Job ${context.job}`, + ].join('\n'), + }); + }