From 8af7d7a377ccb2e705b702706a764dde5764e7a6 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:18:29 +0100 Subject: [PATCH 01/14] feat: crowdin --- .github/workflows/i18n-pull.yml | 124 +++++++++++++++++++++++++ .github/workflows/i18n-push.yml | 156 ++++++++++++++++++++++++++++++++ apps/frontend/crowdin.yml | 8 -- crowdin.yml | 31 +++++++ packages/ui/crowdin.yml | 8 -- 5 files changed, 311 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/i18n-pull.yml create mode 100644 .github/workflows/i18n-push.yml delete mode 100644 apps/frontend/crowdin.yml create mode 100644 crowdin.yml delete mode 100644 packages/ui/crowdin.yml diff --git a/.github/workflows/i18n-pull.yml b/.github/workflows/i18n-pull.yml new file mode 100644 index 000000000..07c56ca37 --- /dev/null +++ b/.github/workflows/i18n-pull.yml @@ -0,0 +1,124 @@ +name: Crowdin (pull) + +on: + schedule: + - cron: '0 7 * * MON' # every monday at 7 am + workflow_dispatch: {} + +concurrency: + group: i18n-management + +jobs: + preflight_check: + name: 'Pre-flight check' + runs-on: ubuntu-22.04 + if: github.ref == 'refs/heads/cal/crowdin' + concurrency: + group: i18n-pull:${{ github.ref }} + cancel-in-progress: true + steps: + - name: Preflight check + id: check + run: | + PREFLIGHT_CHECK_RESULT=true + + function flight_failure () { + if [ "$PREFLIGHT_CHECK_RESULT" = true ]; then + echo "One or more pre-flight checks failed!" + echo "" + PREFLIGHT_CHECK_RESULT=false + fi + echo "- $1" + } + + if [ "$CROWDIN_PROJECT_ID_DEFINED" != true ]; then + flight_failure "CROWDIN_PROJECT_ID variable is not defined (required to push)" + fi + + if [ "$CROWDIN_PERSONAL_TOKEN_DEFINED" != true ]; then + flight_failure "CROWDIN_PERSONAL_TOKEN secret is not defined (required to push)" + fi + + if [ "$CROWDIN_GH_TOKEN_DEFINED" != true ]; then + flight_failure "CROWDIN_GH_TOKEN secret is not defined (required to make pull requests)" + fi + + echo "flight_ok=$PREFLIGHT_CHECK_RESULT" >> "$GITHUB_OUTPUT" + env: + CROWDIN_PROJECT_ID_DEFINED: ${{ vars.CROWDIN_PROJECT_ID != '' }} + CROWDIN_PERSONAL_TOKEN_DEFINED: ${{ secrets.CROWDIN_PERSONAL_TOKEN != '' }} + CROWDIN_GH_TOKEN_DEFINED: ${{ secrets.CROWDIN_GH_TOKEN != '' }} + outputs: + ready: ${{ steps.check.outputs.flight_ok == 'true' }} + + pull_translations: + name: 'Pull translations from Crowdin' + needs: preflight_check + if: needs.preflight_check.outputs.ready == 'true' + runs-on: ubuntu-22.04 + concurrency: + group: i18n-pull:${{ github.ref }} + cancel-in-progress: true + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + token: ${{ secrets.CROWDIN_GH_TOKEN }} + + - name: Configure Git author + id: git-author + uses: MarcoIeni/git-config@v0.1 + env: + GITHUB_TOKEN: ${{ secrets.CROWDIN_GH_TOKEN }} + + # Because --all flag of Crowdin CLI is currently broken we need to create a fake source file + # so that the CLI won't omit translations for it. See https://github.com/crowdin/crowdin-cli/issues/724 + - name: Write fake sources + shell: bash + run: echo "{}" > locales/en-US/index.json + + - name: Query branch name + id: branch-name + shell: bash + run: | + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD) + SAFE_BRANCH_NAME=$(echo "$BRANCH_NAME" | sed -e "s/[\\\\/\\:*?\"<>|]/_/g") + echo "Branch name is $BRANCH_NAME (escaped as $SAFE_BRANCH_NAME)" + echo "branch_name=$BRANCH_NAME" >> "$GITHUB_OUTPUT" + echo "safe_branch_name=$SAFE_BRANCH_NAME" >> "$GITHUB_OUTPUT" + + - name: Download translations from Crowdin + uses: crowdin/github-action@v1 + with: + upload_sources: false + upload_translations: false + download_translations: true + push_translations: false + create_pull_request: false + crowdin_branch_name: '[${{ github.repository_owner }}.${{ github.event.repository.name }}] ${{ steps.branch-name.outputs.safe_branch_name }}' + env: + CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} + + - name: Fix broken permissions + shell: bash + run: sudo chown -R $USER:$USER locales + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + title: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})' + body: |- + Here is your automated pull request with updated translations from [our Crowdin](https://crowdin.com/project/modrinth) for the `${{ steps.branch-name.outputs.branch_name }}` branch. Merge whenever you ready. + + This pull request is created according to the `.github/workflows/i18n-pull.yml` file. + + Want to update this pull request? [Dispatch this workflow again](https://github.com/${{ github.repository }}/actions/workflows/i18n-pull.yml). + commit-message: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})' + branch: crowdin-pull/${{ steps.branch-name.outputs.branch_name }} + add-paths: locales + author: '${{ steps.git-author.outputs.name }} <${{ steps.git-author.outputs.email }}>' + committer: '${{ steps.git-author.outputs.name }} <${{ steps.git-author.outputs.email }}>' + token: ${{ secrets.CROWDIN_GH_TOKEN }} + git-token: ${{ secrets.CROWDIN_GH_TOKEN }} diff --git a/.github/workflows/i18n-push.yml b/.github/workflows/i18n-push.yml new file mode 100644 index 000000000..bd6b86977 --- /dev/null +++ b/.github/workflows/i18n-push.yml @@ -0,0 +1,156 @@ +name: Crowdin (push) + +on: + push: + branches: ['cal/crowdin'] + paths: + - 'apps/*/src/locales/en-US/**' + - 'apps/*/locales/en-US/**' + - 'packages/*/src/locales/en-US/**' + - 'packages/*/locales/en-US/**' + - 'crowdin.yml' + workflow_dispatch: {} + +concurrency: + group: i18n-management + +jobs: + preflight_check: + name: 'Pre-flight check' + runs-on: ubuntu-22.04 + concurrency: + group: i18n-push:${{ github.ref }} + cancel-in-progress: true + steps: + - name: Preflight check + id: check + run: | + PREFLIGHT_CHECK_RESULT=true + + function flight_failure () { + if [ "$PREFLIGHT_CHECK_RESULT" = true ]; then + echo "One or more pre-flight checks failed!" + echo "" + PREFLIGHT_CHECK_RESULT=false + fi + echo "- $1" + } + + if [ "$CROWDIN_PROJECT_ID_DEFINED" != true ]; then + flight_failure "CROWDIN_PROJECT_ID variable is not defined (required to push)" + fi + + if [ "$CROWDIN_PERSONAL_TOKEN_DEFINED" != true ]; then + flight_failure "CROWDIN_PERSONAL_TOKEN secret is not defined (required to push)" + fi + + echo "flight_ok=$PREFLIGHT_CHECK_RESULT" >> "$GITHUB_OUTPUT" + env: + CROWDIN_PROJECT_ID_DEFINED: ${{ vars.CROWDIN_PROJECT_ID != '' }} + CROWDIN_PERSONAL_TOKEN_DEFINED: ${{ secrets.CROWDIN_PERSONAL_TOKEN != '' }} + + - name: Check that Crowdin branch exists + if: github.event_name != 'workflow_dispatch' && github.ref_name != github.event.repository.default_branch + id: crowdin-branch-exists + uses: GuillaumeFalourd/branch-exists@v1 + with: + branch: ${{ format('crowdin-pull/{0}', github.ref_name) }} + + - name: Checkout + id: checkout + if: github.event_name != 'workflow_dispatch' && steps.check.outputs.flight_ok == 'true' && (steps.crowdin-branch-exists.outcome == 'skipped' || steps.crowdin-branch-exists.outputs.exists == 'true') + uses: actions/checkout@v4 + + - name: Confirm push necessity + id: changed-files + if: steps.checkout.outcome != 'skipped' + uses: tj-actions/changed-files@v42 + with: + negation_patterns_first: true + files: | + ** + locales/en-US/** + crowdin.yml + files_ignore: | + .{github,vscode,idea}/** + {assets,patches,types,public,locales}/** + .{editorconfig,gitignore,npmrc,prettierignore} + .*.{js,json} + *.{md,yml,yaml,json} + LICENSE + + - name: Output result + if: steps.changed-files.outcome != 'skipped' + run: | + cat << EOF + Changed files are ${{ steps.changed-files.outputs.all_changed_files }} + EOF + outputs: + ready: ${{ steps.check.outputs.flight_ok == 'true' && (github.event_name == 'workflow_dispatch' || steps.changed-files.outputs.any_changed == 'true') }} + + push_translations: + name: Push sources to Crowdin + needs: preflight_check + if: needs.preflight_check.outputs.ready == 'true' + concurrency: + group: i18n-push:${{ github.ref }} + cancel-in-progress: true + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: 18.x + + - name: Install pnpm via corepack + shell: bash + run: | + corepack enable + corepack prepare --activate + + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + + - name: Setup pnpm cache + uses: actions/cache@v4 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Extract translations + run: pnpm intl:extract + + - name: Query branch name + id: branch-name + shell: bash + run: | + BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD) + SAFE_BRANCH_NAME=$(echo "$BRANCH_NAME" | sed -e "s/[\\\\/\\:*?\"<>|]/_/g") + echo "Branch name is $BRANCH_NAME (escaped as $SAFE_BRANCH_NAME)" + echo "branch_name=$BRANCH_NAME" >> "$GITHUB_OUTPUT" + echo "safe_branch_name=$SAFE_BRANCH_NAME" >> "$GITHUB_OUTPUT" + + - name: Upload translations to Crowdin + uses: crowdin/github-action@v1 + with: + upload_sources: true + upload_translations: false + download_translations: false + push_translations: false + create_pull_request: false + crowdin_branch_name: '[${{ github.repository_owner }}.${{ github.event.repository.name }}] ${{ steps.branch-name.outputs.safe_branch_name }}' + env: + CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} diff --git a/apps/frontend/crowdin.yml b/apps/frontend/crowdin.yml deleted file mode 100644 index e7c47c7da..000000000 --- a/apps/frontend/crowdin.yml +++ /dev/null @@ -1,8 +0,0 @@ -project_id: 518556 -preserve_hierarchy: true -commit_message: "[ci skip]" - -files: - - source: /locales/en-US/* - dest: /%original_file_name% - translation: /locales/%locale%/%original_file_name% diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..7a7c46cc4 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,31 @@ +preserve_hierarchy: true +commit_message: '[ci skip]' + +files: + # apps where locales is in src + - source: /apps/*/src/locales/en-US/*.json + dest: /%original_file_name% + translation: /apps/%original_path%/%locale%/%original_file_name% + skip_untranslated_strings: true + + # apps where locales is in root + - source: /apps/*/locales/en-US/*.json + dest: /%original_file_name% + translation: /apps/%original_path%/%locale%/%original_file_name% + skip_untranslated_strings: true + + # packages where locales is in src + - source: /packages/*/src/locales/en-US/*.json + dest: /%original_file_name% + translation: /packages/%original_path%/%locale%/%original_file_name% + skip_untranslated_strings: true + + # packages where locales in root + # todo: make sure all are in src folder, not huge priority tho + - source: /packages/*/locales/en-US/*.json + dest: /%original_file_name% + translation: /packages/%original_path%/%locale%/%original_file_name% + skip_untranslated_strings: true + +project_id_env: CROWDIN_PROJECT_ID +api_token_env: CROWDIN_PERSONAL_TOKEN \ No newline at end of file diff --git a/packages/ui/crowdin.yml b/packages/ui/crowdin.yml deleted file mode 100644 index 2817cde42..000000000 --- a/packages/ui/crowdin.yml +++ /dev/null @@ -1,8 +0,0 @@ -project_id: 518556 -preserve_hierarchy: true -commit_message: '[ci skip]' - -files: - - source: /locales/en-US/* - dest: /%original_file_name% - translation: /locales/%locale%/%original_file_name% From 036dbad104887ae67c7e413906b62a788eedc5bb Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:22:29 +0100 Subject: [PATCH 02/14] fix: preflight check --- .github/workflows/i18n-push.yml | 40 ++------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/.github/workflows/i18n-push.yml b/.github/workflows/i18n-push.yml index bd6b86977..8ca7ce9dd 100644 --- a/.github/workflows/i18n-push.yml +++ b/.github/workflows/i18n-push.yml @@ -18,6 +18,7 @@ jobs: preflight_check: name: 'Pre-flight check' runs-on: ubuntu-22.04 + if: github.ref == 'refs/heads/cal/crowdin' concurrency: group: i18n-push:${{ github.ref }} cancel-in-progress: true @@ -48,45 +49,8 @@ jobs: env: CROWDIN_PROJECT_ID_DEFINED: ${{ vars.CROWDIN_PROJECT_ID != '' }} CROWDIN_PERSONAL_TOKEN_DEFINED: ${{ secrets.CROWDIN_PERSONAL_TOKEN != '' }} - - - name: Check that Crowdin branch exists - if: github.event_name != 'workflow_dispatch' && github.ref_name != github.event.repository.default_branch - id: crowdin-branch-exists - uses: GuillaumeFalourd/branch-exists@v1 - with: - branch: ${{ format('crowdin-pull/{0}', github.ref_name) }} - - - name: Checkout - id: checkout - if: github.event_name != 'workflow_dispatch' && steps.check.outputs.flight_ok == 'true' && (steps.crowdin-branch-exists.outcome == 'skipped' || steps.crowdin-branch-exists.outputs.exists == 'true') - uses: actions/checkout@v4 - - - name: Confirm push necessity - id: changed-files - if: steps.checkout.outcome != 'skipped' - uses: tj-actions/changed-files@v42 - with: - negation_patterns_first: true - files: | - ** - locales/en-US/** - crowdin.yml - files_ignore: | - .{github,vscode,idea}/** - {assets,patches,types,public,locales}/** - .{editorconfig,gitignore,npmrc,prettierignore} - .*.{js,json} - *.{md,yml,yaml,json} - LICENSE - - - name: Output result - if: steps.changed-files.outcome != 'skipped' - run: | - cat << EOF - Changed files are ${{ steps.changed-files.outputs.all_changed_files }} - EOF outputs: - ready: ${{ steps.check.outputs.flight_ok == 'true' && (github.event_name == 'workflow_dispatch' || steps.changed-files.outputs.any_changed == 'true') }} + ready: ${{ steps.check.outputs.flight_ok == 'true' }} push_translations: name: Push sources to Crowdin From 4fb2ccb22cbcaa93367f29b9b4727ce0fbac66f0 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:24:24 +0100 Subject: [PATCH 03/14] fix: workflow --- .github/workflows/i18n-push.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/i18n-push.yml b/.github/workflows/i18n-push.yml index 8ca7ce9dd..0f4a7247b 100644 --- a/.github/workflows/i18n-push.yml +++ b/.github/workflows/i18n-push.yml @@ -18,7 +18,6 @@ jobs: preflight_check: name: 'Pre-flight check' runs-on: ubuntu-22.04 - if: github.ref == 'refs/heads/cal/crowdin' concurrency: group: i18n-push:${{ github.ref }} cancel-in-progress: true From 146b17a72ebef38fa495df5bcaee7f5878f6f5e6 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:26:09 +0100 Subject: [PATCH 04/14] fix: workflow --- .github/workflows/i18n-pull.yml | 2 +- .github/workflows/i18n-push.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/i18n-pull.yml b/.github/workflows/i18n-pull.yml index 07c56ca37..7a8e27c38 100644 --- a/.github/workflows/i18n-pull.yml +++ b/.github/workflows/i18n-pull.yml @@ -12,7 +12,7 @@ jobs: preflight_check: name: 'Pre-flight check' runs-on: ubuntu-22.04 - if: github.ref == 'refs/heads/cal/crowdin' + if: github.ref == 'refs/heads/main' concurrency: group: i18n-pull:${{ github.ref }} cancel-in-progress: true diff --git a/.github/workflows/i18n-push.yml b/.github/workflows/i18n-push.yml index 0f4a7247b..8b69ff5af 100644 --- a/.github/workflows/i18n-push.yml +++ b/.github/workflows/i18n-push.yml @@ -2,7 +2,7 @@ name: Crowdin (push) on: push: - branches: ['cal/crowdin'] + branches: ['main'] paths: - 'apps/*/src/locales/en-US/**' - 'apps/*/locales/en-US/**' @@ -18,6 +18,7 @@ jobs: preflight_check: name: 'Pre-flight check' runs-on: ubuntu-22.04 + if: github.ref == 'refs/heads/main' concurrency: group: i18n-push:${{ github.ref }} cancel-in-progress: true From 14ab15612017f6a225b58744cdd8c9b3431629c7 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:29:00 +0100 Subject: [PATCH 05/14] fix: fail on preflight failure --- .github/workflows/i18n-push.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/i18n-push.yml b/.github/workflows/i18n-push.yml index 8b69ff5af..25d7b4b28 100644 --- a/.github/workflows/i18n-push.yml +++ b/.github/workflows/i18n-push.yml @@ -45,6 +45,10 @@ jobs: flight_failure "CROWDIN_PERSONAL_TOKEN secret is not defined (required to push)" fi + if [ "$PREFLIGHT_CHECK_RESULT" = false ]; then + exit 1 + fi + echo "flight_ok=$PREFLIGHT_CHECK_RESULT" >> "$GITHUB_OUTPUT" env: CROWDIN_PROJECT_ID_DEFINED: ${{ vars.CROWDIN_PROJECT_ID != '' }} From b87636fb77f9d4dea5597c6695e79dd5939244ca Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:36:19 +0100 Subject: [PATCH 06/14] fix: crowdin config --- crowdin.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/crowdin.yml b/crowdin.yml index 7a7c46cc4..e2e1ce7e5 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -8,24 +8,11 @@ files: translation: /apps/%original_path%/%locale%/%original_file_name% skip_untranslated_strings: true - # apps where locales is in root - - source: /apps/*/locales/en-US/*.json - dest: /%original_file_name% - translation: /apps/%original_path%/%locale%/%original_file_name% - skip_untranslated_strings: true - # packages where locales is in src - source: /packages/*/src/locales/en-US/*.json dest: /%original_file_name% translation: /packages/%original_path%/%locale%/%original_file_name% skip_untranslated_strings: true - # packages where locales in root - # todo: make sure all are in src folder, not huge priority tho - - source: /packages/*/locales/en-US/*.json - dest: /%original_file_name% - translation: /packages/%original_path%/%locale%/%original_file_name% - skip_untranslated_strings: true - project_id_env: CROWDIN_PROJECT_ID api_token_env: CROWDIN_PERSONAL_TOKEN \ No newline at end of file From 553a28d6e1bfaaf4ae51a95a7c4b4d454fe66b3a Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:42:49 +0100 Subject: [PATCH 07/14] fix: ci --- .github/workflows/i18n-pull.yml | 22 ++++---------- .github/workflows/i18n-push.yml | 51 +++------------------------------ 2 files changed, 10 insertions(+), 63 deletions(-) diff --git a/.github/workflows/i18n-pull.yml b/.github/workflows/i18n-pull.yml index 7a8e27c38..e0007bb5f 100644 --- a/.github/workflows/i18n-pull.yml +++ b/.github/workflows/i18n-pull.yml @@ -3,14 +3,14 @@ name: Crowdin (pull) on: schedule: - cron: '0 7 * * MON' # every monday at 7 am - workflow_dispatch: {} + workflow_dispatch: concurrency: group: i18n-management jobs: - preflight_check: - name: 'Pre-flight check' + pull_translations: + name: 'Pull translations from Crowdin' runs-on: ubuntu-22.04 if: github.ref == 'refs/heads/main' concurrency: @@ -18,7 +18,6 @@ jobs: cancel-in-progress: true steps: - name: Preflight check - id: check run: | PREFLIGHT_CHECK_RESULT=true @@ -43,23 +42,14 @@ jobs: flight_failure "CROWDIN_GH_TOKEN secret is not defined (required to make pull requests)" fi - echo "flight_ok=$PREFLIGHT_CHECK_RESULT" >> "$GITHUB_OUTPUT" + if [ "$PREFLIGHT_CHECK_RESULT" = false ]; then + exit 1 + fi env: CROWDIN_PROJECT_ID_DEFINED: ${{ vars.CROWDIN_PROJECT_ID != '' }} CROWDIN_PERSONAL_TOKEN_DEFINED: ${{ secrets.CROWDIN_PERSONAL_TOKEN != '' }} CROWDIN_GH_TOKEN_DEFINED: ${{ secrets.CROWDIN_GH_TOKEN != '' }} - outputs: - ready: ${{ steps.check.outputs.flight_ok == 'true' }} - pull_translations: - name: 'Pull translations from Crowdin' - needs: preflight_check - if: needs.preflight_check.outputs.ready == 'true' - runs-on: ubuntu-22.04 - concurrency: - group: i18n-pull:${{ github.ref }} - cancel-in-progress: true - steps: - name: Checkout uses: actions/checkout@v4 with: diff --git a/.github/workflows/i18n-push.yml b/.github/workflows/i18n-push.yml index 25d7b4b28..812b6e0d1 100644 --- a/.github/workflows/i18n-push.yml +++ b/.github/workflows/i18n-push.yml @@ -4,19 +4,20 @@ on: push: branches: ['main'] paths: + - '.github/workflows/i18n.push.yml' - 'apps/*/src/locales/en-US/**' - 'apps/*/locales/en-US/**' - 'packages/*/src/locales/en-US/**' - 'packages/*/locales/en-US/**' - 'crowdin.yml' - workflow_dispatch: {} + workflow_dispatch: concurrency: group: i18n-management jobs: - preflight_check: - name: 'Pre-flight check' + push_translations: + name: Push sources to Crowdin runs-on: ubuntu-22.04 if: github.ref == 'refs/heads/main' concurrency: @@ -24,7 +25,6 @@ jobs: cancel-in-progress: true steps: - name: Preflight check - id: check run: | PREFLIGHT_CHECK_RESULT=true @@ -48,58 +48,15 @@ jobs: if [ "$PREFLIGHT_CHECK_RESULT" = false ]; then exit 1 fi - - echo "flight_ok=$PREFLIGHT_CHECK_RESULT" >> "$GITHUB_OUTPUT" env: CROWDIN_PROJECT_ID_DEFINED: ${{ vars.CROWDIN_PROJECT_ID != '' }} CROWDIN_PERSONAL_TOKEN_DEFINED: ${{ secrets.CROWDIN_PERSONAL_TOKEN != '' }} - outputs: - ready: ${{ steps.check.outputs.flight_ok == 'true' }} - push_translations: - name: Push sources to Crowdin - needs: preflight_check - if: needs.preflight_check.outputs.ready == 'true' - concurrency: - group: i18n-push:${{ github.ref }} - cancel-in-progress: true - runs-on: ubuntu-22.04 - steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ github.ref }} - - name: Use Node.js - uses: actions/setup-node@v4 - with: - node-version: 18.x - - - name: Install pnpm via corepack - shell: bash - run: | - corepack enable - corepack prepare --activate - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - name: Setup pnpm cache - uses: actions/cache@v4 - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install - - - name: Extract translations - run: pnpm intl:extract - - name: Query branch name id: branch-name shell: bash From 18cf2d774b91bb39c883e36029e403f87618719f Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:47:41 +0100 Subject: [PATCH 08/14] fix: crowdin sources --- crowdin.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/crowdin.yml b/crowdin.yml index e2e1ce7e5..37db0d332 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -2,16 +2,19 @@ preserve_hierarchy: true commit_message: '[ci skip]' files: - # apps where locales is in src - - source: /apps/*/src/locales/en-US/*.json + - source: /apps/app-frontend/src/locales/en-US/*.json dest: /%original_file_name% - translation: /apps/%original_path%/%locale%/%original_file_name% + translation: /apps/app-frontend/src/locales/%locale%/%original_file_name% skip_untranslated_strings: true - # packages where locales is in src - - source: /packages/*/src/locales/en-US/*.json + - source: /apps/frontend/src/locales/en-US/*.json dest: /%original_file_name% - translation: /packages/%original_path%/%locale%/%original_file_name% + translation: /apps/frontend/src/locales/%locale%/%original_file_name% + skip_untranslated_strings: true + + - source: /packages/ui/src/locales/en-US/*.json + dest: /%original_file_name% + translation: /packages/ui/src/locales/%locale%/%original_file_name% skip_untranslated_strings: true project_id_env: CROWDIN_PROJECT_ID From 4ee54742f5b53664cdc49675f13bdef02cd5d226 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 15:49:55 +0100 Subject: [PATCH 09/14] fix: crowdin config --- crowdin.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crowdin.yml b/crowdin.yml index 37db0d332..abc0e5672 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -3,17 +3,17 @@ commit_message: '[ci skip]' files: - source: /apps/app-frontend/src/locales/en-US/*.json - dest: /%original_file_name% + dest: /app/%original_file_name% translation: /apps/app-frontend/src/locales/%locale%/%original_file_name% skip_untranslated_strings: true - source: /apps/frontend/src/locales/en-US/*.json - dest: /%original_file_name% + dest: /web/%original_file_name% translation: /apps/frontend/src/locales/%locale%/%original_file_name% skip_untranslated_strings: true - source: /packages/ui/src/locales/en-US/*.json - dest: /%original_file_name% + dest: /ui/%original_file_name% translation: /packages/ui/src/locales/%locale%/%original_file_name% skip_untranslated_strings: true From 4607ce98f48cf4110f2208eca7c4f20de9cf2877 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 16:03:30 +0100 Subject: [PATCH 10/14] fix: crowdin pull --- .github/workflows/i18n-pull.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/i18n-pull.yml b/.github/workflows/i18n-pull.yml index e0007bb5f..9bb696fa5 100644 --- a/.github/workflows/i18n-pull.yml +++ b/.github/workflows/i18n-pull.yml @@ -62,11 +62,11 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.CROWDIN_GH_TOKEN }} - # Because --all flag of Crowdin CLI is currently broken we need to create a fake source file - # so that the CLI won't omit translations for it. See https://github.com/crowdin/crowdin-cli/issues/724 - - name: Write fake sources - shell: bash - run: echo "{}" > locales/en-US/index.json + # # Because --all flag of Crowdin CLI is currently broken we need to create a fake source file + # # so that the CLI won't omit translations for it. See https://github.com/crowdin/crowdin-cli/issues/724 + # - name: Write fake sources + # shell: bash + # run: echo "{}" > locales/en-US/index.json - name: Query branch name id: branch-name @@ -79,7 +79,7 @@ jobs: echo "safe_branch_name=$SAFE_BRANCH_NAME" >> "$GITHUB_OUTPUT" - name: Download translations from Crowdin - uses: crowdin/github-action@v1 + uses: crowdin/github-action@v2 with: upload_sources: false upload_translations: false @@ -91,9 +91,9 @@ jobs: CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} - - name: Fix broken permissions - shell: bash - run: sudo chown -R $USER:$USER locales + # - name: Fix broken permissions + # shell: bash + # run: sudo chown -R $USER:$USER locales - name: Create Pull Request uses: peter-evans/create-pull-request@v6 From 8f66e8c03d52b3c1e6638c7edb6f9b10e32983de Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 16:06:17 +0100 Subject: [PATCH 11/14] fix: crowdin --- .github/workflows/i18n-pull.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/i18n-pull.yml b/.github/workflows/i18n-pull.yml index 9bb696fa5..f7173bfc8 100644 --- a/.github/workflows/i18n-pull.yml +++ b/.github/workflows/i18n-pull.yml @@ -91,9 +91,9 @@ jobs: CROWDIN_PROJECT_ID: ${{ vars.CROWDIN_PROJECT_ID }} CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} - # - name: Fix broken permissions - # shell: bash - # run: sudo chown -R $USER:$USER locales + - name: Fix broken permissions + shell: bash + run: sudo chown -R $USER:$USER . - name: Create Pull Request uses: peter-evans/create-pull-request@v6 From f2a331449f8847167e2cb48f56092e85b3f6747e Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 16:09:25 +0100 Subject: [PATCH 12/14] fix: crowdin issues --- .github/workflows/i18n-pull.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/i18n-pull.yml b/.github/workflows/i18n-pull.yml index f7173bfc8..6214fd65f 100644 --- a/.github/workflows/i18n-pull.yml +++ b/.github/workflows/i18n-pull.yml @@ -107,7 +107,9 @@ jobs: Want to update this pull request? [Dispatch this workflow again](https://github.com/${{ github.repository }}/actions/workflows/i18n-pull.yml). commit-message: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})' branch: crowdin-pull/${{ steps.branch-name.outputs.branch_name }} - add-paths: locales + add-paths: | + apps/*/src/locales + packages/*/src/locales author: '${{ steps.git-author.outputs.name }} <${{ steps.git-author.outputs.email }}>' committer: '${{ steps.git-author.outputs.name }} <${{ steps.git-author.outputs.email }}>' token: ${{ secrets.CROWDIN_GH_TOKEN }} From e3d39151ffd3abaca0c69bb660453046f0b50963 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 16:12:53 +0100 Subject: [PATCH 13/14] fix: add-paths --- .github/workflows/i18n-pull.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/i18n-pull.yml b/.github/workflows/i18n-pull.yml index 6214fd65f..581ce120f 100644 --- a/.github/workflows/i18n-pull.yml +++ b/.github/workflows/i18n-pull.yml @@ -96,7 +96,7 @@ jobs: run: sudo chown -R $USER:$USER . - name: Create Pull Request - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: title: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})' body: |- @@ -107,10 +107,6 @@ jobs: Want to update this pull request? [Dispatch this workflow again](https://github.com/${{ github.repository }}/actions/workflows/i18n-pull.yml). commit-message: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})' branch: crowdin-pull/${{ steps.branch-name.outputs.branch_name }} - add-paths: | - apps/*/src/locales - packages/*/src/locales author: '${{ steps.git-author.outputs.name }} <${{ steps.git-author.outputs.email }}>' committer: '${{ steps.git-author.outputs.name }} <${{ steps.git-author.outputs.email }}>' token: ${{ secrets.CROWDIN_GH_TOKEN }} - git-token: ${{ secrets.CROWDIN_GH_TOKEN }} From 1a55e0f3ed2e3e84c3258824f1fed6a95fdc94b2 Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Tue, 5 Aug 2025 16:23:01 +0100 Subject: [PATCH 14/14] fix: move pr body to markdown template --- .github/templates/crowdin-pr.md | 4 ++++ .github/workflows/i18n-pull.yml | 8 ++------ 2 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 .github/templates/crowdin-pr.md diff --git a/.github/templates/crowdin-pr.md b/.github/templates/crowdin-pr.md new file mode 100644 index 000000000..a8f898067 --- /dev/null +++ b/.github/templates/crowdin-pr.md @@ -0,0 +1,4 @@ +This pull request is created according to the `.github/workflows/i18n-pull.yml` file. + +- 🌐 [Contribute to translations on Crowdin](https://crowdin.com/project/modrinth) +- 🔄 [Dispatch this workflow again to update this PR](https://github.com/Modrinth/code/actions/workflows/i18n-pull.yml) \ No newline at end of file diff --git a/.github/workflows/i18n-pull.yml b/.github/workflows/i18n-pull.yml index 581ce120f..14a1c814c 100644 --- a/.github/workflows/i18n-pull.yml +++ b/.github/workflows/i18n-pull.yml @@ -99,14 +99,10 @@ jobs: uses: peter-evans/create-pull-request@v7 with: title: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})' - body: |- - Here is your automated pull request with updated translations from [our Crowdin](https://crowdin.com/project/modrinth) for the `${{ steps.branch-name.outputs.branch_name }}` branch. Merge whenever you ready. - - This pull request is created according to the `.github/workflows/i18n-pull.yml` file. - - Want to update this pull request? [Dispatch this workflow again](https://github.com/${{ github.repository }}/actions/workflows/i18n-pull.yml). + body-path: .github/templates/crowdin-pr.md commit-message: 'New translations from Crowdin (${{ steps.branch-name.outputs.branch_name }})' branch: crowdin-pull/${{ steps.branch-name.outputs.branch_name }} author: '${{ steps.git-author.outputs.name }} <${{ steps.git-author.outputs.email }}>' committer: '${{ steps.git-author.outputs.name }} <${{ steps.git-author.outputs.email }}>' + labels: sync token: ${{ secrets.CROWDIN_GH_TOKEN }}