name: Control UI Locale Refresh on: push: branches: - main paths: - ui/src/i18n/locales/en.ts - ui/src/i18n/locales/*.ts - ui/src/i18n/.i18n/* - ui/src/i18n/lib/types.ts - ui/src/i18n/lib/registry.ts - scripts/control-ui-i18n.ts - .github/workflows/control-ui-locale-refresh.yml release: types: - published schedule: - cron: "23 4 * * *" workflow_dispatch: permissions: contents: write concurrency: group: control-ui-locale-refresh cancel-in-progress: false jobs: plan: if: github.repository == 'openclaw/openclaw' && (github.event_name != 'push' || github.actor != 'github-actions[bot]') runs-on: ubuntu-latest outputs: has_locales: ${{ steps.plan.outputs.has_locales }} locales_json: ${{ steps.plan.outputs.locales_json }} steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 persist-credentials: false submodules: false - name: Plan locale matrix id: plan env: BEFORE_SHA: ${{ github.event.before }} EVENT_NAME: ${{ github.event_name }} run: | set -euo pipefail all_locales_json='["zh-CN","zh-TW","pt-BR","de","es","ja-JP","ko","fr","tr","uk","id","pl"]' if [ "$EVENT_NAME" != "push" ]; then echo "has_locales=true" >> "$GITHUB_OUTPUT" echo "locales_json=$all_locales_json" >> "$GITHUB_OUTPUT" exit 0 fi before_ref="$BEFORE_SHA" if [ -z "$before_ref" ] || [ "$before_ref" = "0000000000000000000000000000000000000000" ]; then before_ref="$(git rev-parse HEAD^)" fi changed_files="$(git diff --name-only "$before_ref" HEAD)" echo "changed files:" printf '%s\n' "$changed_files" if printf '%s\n' "$changed_files" | grep -Eq '^(ui/src/i18n/locales/en\.ts|ui/src/i18n/lib/types\.ts|ui/src/i18n/lib/registry\.ts|scripts/control-ui-i18n\.ts|\.github/workflows/control-ui-locale-refresh\.yml)$'; then echo "has_locales=true" >> "$GITHUB_OUTPUT" echo "locales_json=$all_locales_json" >> "$GITHUB_OUTPUT" exit 0 fi locales_json="$(printf '%s\n' "$changed_files" | node <<'EOF' const fs = require("node:fs"); const changed = fs.readFileSync(0, "utf8").split(/\r?\n/).filter(Boolean); const locales = new Set(); for (const file of changed) { let match = file.match(/^ui\/src\/i18n\/locales\/(.+)\.ts$/); if (match && match[1] !== "en") { locales.add(match[1]); continue; } match = file.match(/^ui\/src\/i18n\/\.i18n\/(.+)\.(?:meta\.json|tm\.jsonl)$/); if (match) { locales.add(match[1]); } } process.stdout.write(JSON.stringify([...locales])); EOF )" if [ "$locales_json" = "[]" ]; then echo "has_locales=false" >> "$GITHUB_OUTPUT" echo "locales_json=[]" >> "$GITHUB_OUTPUT" exit 0 fi echo "has_locales=true" >> "$GITHUB_OUTPUT" echo "locales_json=$locales_json" >> "$GITHUB_OUTPUT" refresh: needs: plan if: github.repository == 'openclaw/openclaw' && needs.plan.outputs.has_locales == 'true' strategy: fail-fast: false max-parallel: 4 matrix: locale: ${{ fromJson(needs.plan.outputs.locales_json) }} runs-on: ubuntu-latest name: Refresh ${{ matrix.locale }} steps: - name: Checkout uses: actions/checkout@v6 with: persist-credentials: true submodules: false - name: Setup Node environment uses: ./.github/actions/setup-node-env with: install-bun: "false" use-sticky-disk: "false" - name: Ensure translation provider secrets exist env: OPENAI_API_KEY: ${{ secrets.OPENCLAW_DOCS_I18N_OPENAI_API_KEY || secrets.OPENAI_API_KEY }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | set -euo pipefail if [ -z "${OPENAI_API_KEY:-}" ] && [ -z "${ANTHROPIC_API_KEY:-}" ]; then echo "Missing OPENCLAW_DOCS_I18N_OPENAI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY secret." exit 1 fi - name: Refresh control UI locale files env: OPENAI_API_KEY: ${{ secrets.OPENCLAW_DOCS_I18N_OPENAI_API_KEY || secrets.OPENAI_API_KEY }} ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} OPENCLAW_CONTROL_UI_I18N_MODEL: gpt-5.4 OPENCLAW_CONTROL_UI_I18N_THINKING: low run: node --import tsx scripts/control-ui-i18n.ts sync --locale "${{ matrix.locale }}" --write - name: Commit and push locale updates env: LOCALE: ${{ matrix.locale }} TARGET_BRANCH: ${{ github.event.repository.default_branch }} run: | set -euo pipefail if git diff --quiet -- ui/src/i18n; then echo "No control UI locale changes for ${LOCALE}." exit 0 fi git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add -A ui/src/i18n git commit --no-verify -m "chore(ui): refresh ${LOCALE} control ui locale" for attempt in 1 2 3 4 5; do git fetch origin "${TARGET_BRANCH}" git rebase --autostash "origin/${TARGET_BRANCH}" if git push origin HEAD:"${TARGET_BRANCH}"; then exit 0 fi echo "Push attempt ${attempt} for ${LOCALE} failed; retrying." sleep $((attempt * 2)) done echo "Failed to push ${LOCALE} locale update after retries." exit 1