update & cleanup flake #13
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: POEditor Diff & Sync | |
| on: | |
| push: | |
| branches: [ master ] | |
| workflow_dispatch: {} | |
| concurrency: | |
| group: poeditor-sync | |
| cancel-in-progress: false | |
| jobs: | |
| sync-translations: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.x' | |
| - name: Install jq | |
| run: sudo apt-get update && sudo apt-get install -y jq | |
| - name: Extract source strings from codebase | |
| env: | |
| API_TOKEN: ${{ secrets.POEDITOR_API_TOKEN }} | |
| PROJECT_ID: ${{ secrets.POEDITOR_PROJECT_ID }} | |
| run: | | |
| set -euo pipefail | |
| echo "::group::Extracting strings from QML files" | |
| python3 translations/extract_translations.py | |
| echo "::endgroup::" | |
| echo "::group::Checking for changes in en.json" | |
| if [[ -f "translations/en.json" ]]; then | |
| jq -S . "translations/en.json" > /tmp/en_new.json | |
| if [[ -f "translations/en.json.orig" ]]; then | |
| jq -S . "translations/en.json.orig" > /tmp/en_old.json | |
| else | |
| git show HEAD:translations/en.json > /tmp/en_old.json 2>/dev/null || echo "[]" > /tmp/en_old.json | |
| jq -S . /tmp/en_old.json > /tmp/en_old.json.tmp && mv /tmp/en_old.json.tmp /tmp/en_old.json | |
| fi | |
| if diff -q /tmp/en_new.json /tmp/en_old.json >/dev/null 2>&1; then | |
| echo "No changes in source strings" | |
| echo "source_changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "Detected changes in source strings" | |
| echo "source_changed=true" >> "$GITHUB_OUTPUT" | |
| echo "::group::Uploading source strings to POEditor" | |
| RESP=$(curl -sS -X POST https://api.poeditor.com/v2/projects/upload \ | |
| -F api_token="$API_TOKEN" \ | |
| -F id="$PROJECT_ID" \ | |
| -F updating="terms" \ | |
| -F file=@"translations/en.json") | |
| STATUS=$(echo "$RESP" | jq -r '.response.status') | |
| if [[ "$STATUS" != "success" ]]; then | |
| echo "::warning::POEditor upload failed: $RESP" | |
| else | |
| TERMS_ADDED=$(echo "$RESP" | jq -r '.result.terms.added // 0') | |
| TERMS_UPDATED=$(echo "$RESP" | jq -r '.result.terms.updated // 0') | |
| TERMS_DELETED=$(echo "$RESP" | jq -r '.result.terms.deleted // 0') | |
| echo "Terms added: $TERMS_ADDED, updated: $TERMS_UPDATED, deleted: $TERMS_DELETED" | |
| fi | |
| echo "::endgroup::" | |
| fi | |
| else | |
| echo "::warning::translations/en.json not found" | |
| echo "source_changed=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "::endgroup::" | |
| id: extract | |
| - name: Commit and push source strings | |
| if: steps.extract.outputs.source_changed == 'true' | |
| run: | | |
| set -euo pipefail | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add translations/en.json translations/template.json | |
| git commit -m "i18n: update source strings from codebase" | |
| for attempt in 1 2 3; do | |
| if git push; then | |
| echo "Successfully pushed source string updates" | |
| exit 0 | |
| fi | |
| echo "Push attempt $attempt failed, pulling and retrying..." | |
| git pull --rebase | |
| sleep $((attempt*2)) | |
| done | |
| echo "Failed to push after retries" >&2 | |
| exit 1 | |
| - name: Export and update translations from POEditor | |
| env: | |
| API_TOKEN: ${{ secrets.POEDITOR_API_TOKEN }} | |
| PROJECT_ID: ${{ secrets.POEDITOR_PROJECT_ID }} | |
| run: | | |
| set -euo pipefail | |
| LANGUAGES=( | |
| "ja:translations/poexports/ja.json" | |
| "zh-Hans:translations/poexports/zh_CN.json" | |
| "pt-br:translations/poexports/pt.json" | |
| ) | |
| ANY_CHANGED=false | |
| for lang_pair in "${LANGUAGES[@]}"; do | |
| IFS=':' read -r PO_LANG REPO_FILE <<< "$lang_pair" | |
| echo "::group::Processing $PO_LANG" | |
| RESP=$(curl -sS -X POST https://api.poeditor.com/v2/projects/export \ | |
| -d api_token="$API_TOKEN" \ | |
| -d id="$PROJECT_ID" \ | |
| -d language="$PO_LANG" \ | |
| -d type="key_value_json") | |
| STATUS=$(echo "$RESP" | jq -r '.response.status') | |
| if [[ "$STATUS" != "success" ]]; then | |
| echo "POEditor export request failed for $PO_LANG: $RESP" >&2 | |
| continue | |
| fi | |
| URL=$(echo "$RESP" | jq -r '.result.url') | |
| if [[ -z "$URL" || "$URL" == "null" ]]; then | |
| echo "No export URL returned for $PO_LANG" >&2 | |
| continue | |
| fi | |
| curl -sS -L "$URL" -o "/tmp/po_export_${PO_LANG}.json" | |
| jq -S . "/tmp/po_export_${PO_LANG}.json" > "/tmp/po_export_${PO_LANG}.norm.json" | |
| if [[ -f "$REPO_FILE" ]]; then | |
| jq -S . "$REPO_FILE" > "/tmp/repo_${PO_LANG}.norm.json" || echo "{}" > "/tmp/repo_${PO_LANG}.norm.json" | |
| else | |
| echo "{}" > "/tmp/repo_${PO_LANG}.norm.json" | |
| fi | |
| if diff -q "/tmp/po_export_${PO_LANG}.norm.json" "/tmp/repo_${PO_LANG}.norm.json" >/dev/null; then | |
| echo "No changes for $PO_LANG" | |
| else | |
| echo "Detected changes for $PO_LANG" | |
| mkdir -p "$(dirname "$REPO_FILE")" | |
| cp "/tmp/po_export_${PO_LANG}.norm.json" "$REPO_FILE" | |
| ANY_CHANGED=true | |
| fi | |
| echo "::endgroup::" | |
| done | |
| echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT" | |
| id: export | |
| - name: Commit and push translation updates | |
| if: steps.export.outputs.any_changed == 'true' | |
| run: | | |
| set -euo pipefail | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add translations/poexports/*.json | |
| git commit -m "i18n: update translations" | |
| for attempt in 1 2 3; do | |
| if git push; then | |
| echo "Successfully pushed translation updates" | |
| exit 0 | |
| fi | |
| echo "Push attempt $attempt failed, pulling and retrying..." | |
| git pull --rebase | |
| sleep $((attempt*2)) | |
| done | |
| echo "Failed to push after retries" >&2 | |
| exit 1 |