# This workflow manages internationalization (i18n) with Crowdin # Triggers: # - Hourly schedule to sync translations # - Push with changes to translation files or config # Process: # 1. Extracts translatable strings from source code # 2. Uploads source strings to Crowdin # 3. Downloads translated strings from Crowdin # 4. Creates PR with updated translations # Note: Uses concurrency control to prevent overlapping runs name: Translation job on: schedule: # Run the workflow every hour - cron: '0 * * * *' push: branches: - develop paths: - 'web/i18n/en/translation.json' - 'web/**/*.tsx' - 'web/**/*.js' - 'crowdin.yml' - '.github/workflows/translations.yml' - 'web/i18next-parser.config.mjs' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: generate-translations: defaults: run: working-directory: ./web runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - name: Configure Git run: | git config --global user.name "Owncast" git config --global user.email "owncast@owncast.online" - name: Install dependencies run: npm install - name: Generate translation files run: npm run translate - name: Upload sources to Crowdin uses: crowdin/github-action@v2 with: upload_sources: true upload_translations: false download_translations: false config: crowdin.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} - name: Download translations from Crowdin uses: crowdin/github-action@v2 with: upload_sources: false upload_translations: false download_translations: true skip_untranslated_strings: true export_only_approved: false push_translations: false commit_message: 'chore(i18n): update translations from Crowdin' localization_branch_name: crowdin-translations create_pull_request: false config: crowdin.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} - name: Check for translation changes id: changes run: | cd .. git add web/i18n/ if git diff --cached --quiet; then echo "has_changes=false" >> $GITHUB_OUTPUT echo "No translation changes detected" else echo "has_changes=true" >> $GITHUB_OUTPUT echo "Translation changes detected" fi - name: Create Pull Request if: steps.changes.outputs.has_changes == 'true' id: create_pr uses: peter-evans/create-pull-request@v8 with: token: ${{ secrets.GITHUB_TOKEN }} branch: crowdin-translations base: develop title: 'chore(i18n): update translations from Crowdin' body: | This PR contains updated translations downloaded from Crowdin. **Changes include:** - Updated translation files in `web/i18n/` - Translations synchronized from Crowdin project Please review the changes and merge if they look correct. --- This PR was created automatically by the translation workflow. commit-message: 'chore(i18n): update translations from Crowdin' author: 'Owncast ' committer: 'Owncast ' add-paths: | web/i18n/** delete-branch: true - name: Log PR creation result if: steps.create_pr.outputs.pull-request-number run: | echo "Created PR #${{ steps.create_pr.outputs.pull-request-number }}" echo "PR URL: ${{ steps.create_pr.outputs.pull-request-url }}" - name: No changes detected if: steps.changes.outputs.has_changes == 'false' run: echo "No translation changes to commit"