Connecting Crowdin API to GitHub Pull Requests

The Core Synchronization Bottleneck

Engineering teams frequently experience localization drift when translation assets are manually exported from Crowdin and committed to GitHub. Without automated API orchestration, stale string files cause UI rendering failures, merge conflicts, and delayed release cycles. Implementing a robust pipeline for Crowdin Integration for Dev Teams resolves these friction points by replacing manual handoffs with deterministic, event-driven syncs.

Key Failure Modes to Eliminate:

  • Manual export/commit cycles introducing race conditions
  • Unvalidated JSON/YAML payloads breaking frontend parsers
  • Branch divergence between feature work and l10n updates
  • Lack of automated reviewer routing for translation PRs

Event-Driven API & PR Orchestration

The architecture relies on Crowdin’s REST API v2, GitHub Actions, and webhook listeners to create a closed-loop localization pipeline. A scheduled or webhook-triggered workflow authenticates via OAuth2, queries project translation status, and conditionally exports only approved language bundles. The CI runner commits these assets to an isolated l10n-sync branch, opens or updates a pull request, and attaches automated validation reports. This pattern ensures Translation Workflows & CI/CD Pipeline Sync remains deterministic and auditable across all environments.

Core Workflow Components:

  • Crowdin API v2 client with scoped project tokens
  • GitHub Actions runner utilizing actions/checkout and peter-evans/create-pull-request
  • Conditional export logic filtering by translationProgress >= 100
  • Pre-merge JSON schema validation and placeholder integrity checks

Production-Ready GitHub Actions Workflow

name: Crowdin l10n Sync & PR
on:
 schedule:
 - cron: '0 2 * * 1-5' # Run weekdays at 02:00 UTC
 workflow_dispatch:

jobs:
 sync-translations:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4
 with:
 fetch-depth: 0
 token: ${{ secrets.GH_PAT }}

 - name: Export Approved Translations via Crowdin API
 run: |
 curl -s -X POST "https://api.crowdin.com/api/v2/projects/${{ secrets.CROWDIN_PROJECT_ID }}/translations/exports" \
 -H "Authorization: Bearer ${{ secrets.CROWDIN_API_TOKEN }}" \
 -H "Content-Type: application/json" \
 -d '{"targetLanguageIds": ["es", "fr", "de"], "skipUntranslatedStrings": true}'

 - name: Download & Stage Assets
 run: |
 mkdir -p tmp_export
 # Use Crowdin CLI or direct API download here based on export ID
 # cp -r tmp_export/* ./locales/

 - name: Validate Payloads
 run: |
 for f in locales/**/*.json; do
 jq empty "$f" || { echo "Invalid JSON: $f"; exit 1; }
 done

 - name: Create/Update l10n PR
 uses: peter-evans/create-pull-request@v5
 with:
 token: ${{ secrets.GH_PAT }}
 branch: l10n-sync
 commit-message: "chore(l10n): sync approved translations"
 title: "Automated Localization Sync"
 body: "Generated by CI pipeline. Review translations before merge."
 labels: "l10n, automated"

Framework-Specific Path Mapping & Export Rules

Successful API integration requires precise alignment between Crowdin’s export paths and your framework’s i18n routing conventions. Configure your CI environment variables and Crowdin file mappings to match the exact directory structures below.

Next.js (next-i18next)

LOCALE_DIRECTORY: "/locales/{lang}/"
CROWDIN_FILE_MAPPING: "locales/{lang}/common.json"
EXPORT_FLAGS: "--skip-untranslated-strings --dest locales/{lang}"

React (i18next)

LOCALE_DIRECTORY: "/public/locales/{lang}/"
CROWDIN_FILE_MAPPING: "public/locales/{lang}/translation.json"
EXPORT_FLAGS: "--dest public/locales/{lang} --branch main"

Vue (vue-i18n)

LOCALE_DIRECTORY: "/src/locales/"
CROWDIN_FILE_MAPPING: "src/locales/{lang}.json"
EXPORT_FLAGS: "--dest src/locales --export-only-approved"

Edge Case Audit & Resolution Matrix

Production deployments encounter predictable failure states during API-to-PR synchronization. Use the following diagnostic steps to isolate and remediate pipeline errors.

Error State Diagnostic Trigger Production Resolution
HTTP 429 Too Many Requests on Crowdin API Concurrent language exports exceed rate limits. Implement exponential backoff in the workflow and stagger exports using --parallel 2 with a 30-second delay between language batches.
GitHub Action fails on JSON parse validation Translator injected unescaped characters or broken placeholders. Add a jq or ajv validation step in the workflow to reject malformed payloads before commit, and enable Crowdin’s ‘Tag validation’ in project settings.
Webhook HMAC signature mismatch Secret encoding mismatch or payload tampering. Ensure the webhook secret in Crowdin matches GitHub exactly, strip trailing whitespace, and verify UTF-8 encoding without BOM during signature generation.
Automated PR blocked by merge conflicts Developer modified i18n files concurrently with sync workflow. Configure the workflow to fetch origin/main, perform an automated rebase on the l10n-sync branch, and force-push only if the conflict resolution script exits cleanly.