# Pull down translations from Crowdin every two hours or when triggered manually. # When force_pull input is true, translations will be pulled regardless of compilation status. name: 'Pull translations from Crowdin' permissions: contents: write pull-requests: write on: schedule: - cron: '0 */2 * * *' # Every two hours. workflow_dispatch: inputs: force_pull: description: 'Force pull translations regardless of compilation status' required: false type: boolean default: false workflow_call: inputs: force_pull: description: 'Force pull translations regardless of compilation status' required: false type: boolean default: false concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: pull_translations: name: Pull translations runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: token: ${{ github.token }} ref: ${{ github.head_ref || github.ref_name }} - name: Setup i18n branch run: | git fetch origin i18n || true git checkout -B i18n origin/i18n || git checkout -b i18n - name: Install dependencies uses: ./.github/actions/yarn-install - name: Build twenty-shared run: npx nx build twenty-shared # Strict mode fails if there are missing translations. - name: Compile translations id: compile_translations_strict run: | npx nx run twenty-server:lingui:compile --strict npx nx run twenty-emails:lingui:compile --strict npx nx run twenty-front:lingui:compile --strict continue-on-error: true - name: Stash any changes before pulling translations run: | git config --global user.name 'github-actions' git config --global user.email 'github-actions@twenty.com' git add . git stash - name: Pull translations from Crowdin if: inputs.force_pull || steps.compile_translations_strict.outcome == 'failure' uses: crowdin/github-action@v2 with: upload_sources: false upload_translations: false download_translations: true source: '**/en.po' translation: '%original_path%/%locale%.po' export_only_approved: false localization_branch_name: i18n base_url: 'https://twenty.api.crowdin.com' auto_approve_imported: false import_eq_suggestions: false download_sources: false push_sources: false skip_untranslated_strings: false skip_untranslated_files: false push_translations: false create_pull_request: false skip_ref_checkout: true dryrun_action: false config: '.github/crowdin-app.yml' env: GITHUB_TOKEN: ${{ github.token }} # App translations project CROWDIN_PROJECT_ID: '1' CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} # As the files are extracted from a Docker container, they belong to root:root # We need to fix this before the next steps - name: Fix file permissions run: sudo chown -R runner:docker . # Fix encoding issues (escaped Unicode like \u62db -> 招) and push fixes back to Crowdin - name: Fix translation encoding and sync to Crowdin run: npx ts-node packages/twenty-utils/fix-crowdin-translations.ts env: CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} - name: Compile translations id: compile_translations # Because we have set English as a fallback locale, this condition does not work anymore # if: inputs.force_pull || steps.compile_translations_strict.outcome == 'failure' run: | npx nx run twenty-server:lingui:compile npx nx run twenty-emails:lingui:compile npx nx run twenty-front:lingui:compile git status git add . if ! git diff --staged --quiet --exit-code; then git commit -m "chore: compile translations" echo "changes_detected=true" >> $GITHUB_OUTPUT else echo "changes_detected=false" >> $GITHUB_OUTPUT fi - name: Push changes if: steps.compile_translations.outputs.changes_detected == 'true' run: git push origin HEAD:i18n - name: Create pull request if: steps.compile_translations.outputs.changes_detected == 'true' run: | if git diff --name-only origin/main..HEAD | grep -q .; then gh pr create -B main -H i18n --title 'i18n - translations' --body 'Created by Github action' || true else echo "No file differences between branches, skipping PR creation" fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Trigger i18n automerge if: steps.compile_translations.outputs.changes_detected == 'true' uses: peter-evans/repository-dispatch@v2 with: token: ${{ secrets.TWENTY_INFRA_TOKEN }} repository: twentyhq/twenty-infra event-type: i18n-pr-ready