From 049ff73fff59b3ea618729d3f1a5e2a9e3932015 Mon Sep 17 00:00:00 2001 From: webadderall <131426131+webadderall@users.noreply.github.com> Date: Sun, 15 Mar 2026 22:01:51 +1100 Subject: [PATCH] ci(docs): auto-translate README to zh-CN via GitHub Models --- .github/workflows/readme-translation.yml | 46 +++++++++++++++ scripts/translate-readme-zh.mjs | 73 ++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 .github/workflows/readme-translation.yml create mode 100644 scripts/translate-readme-zh.mjs diff --git a/.github/workflows/readme-translation.yml b/.github/workflows/readme-translation.yml new file mode 100644 index 00000000..8de7ec04 --- /dev/null +++ b/.github/workflows/readme-translation.yml @@ -0,0 +1,46 @@ +name: Auto Translate README (zh-CN) + +on: + push: + branches: [main] + paths: + - README.md + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + translate-readme: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Translate README.md to Simplified Chinese + id: translate + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + README_TRANSLATION_MODEL: openai/gpt-4.1-mini + GITHUB_MODELS_API_URL: https://models.inference.ai.azure.com/chat/completions + run: node scripts/translate-readme-zh.mjs + + - name: Create PR with translation update + if: steps.translate.outputs.changed == 'true' + uses: peter-evans/create-pull-request@v7 + with: + commit-message: "docs(readme): auto-update Simplified Chinese translation" + title: "docs(readme): auto-update Simplified Chinese translation" + body: | + Automated update of README Simplified Chinese translation based on latest README.md changes. + branch: chore/auto-update-readme-zh + delete-branch: true + add-paths: | + README.zh-CN.md diff --git a/scripts/translate-readme-zh.mjs b/scripts/translate-readme-zh.mjs new file mode 100644 index 00000000..3b6016a8 --- /dev/null +++ b/scripts/translate-readme-zh.mjs @@ -0,0 +1,73 @@ +import fs from "node:fs/promises"; +import path from "node:path"; + +const MODEL = process.env["README_TRANSLATION_MODEL"] || "openai/gpt-4.1-mini"; +const API_URL = process.env["GITHUB_MODELS_API_URL"] || "https://models.inference.ai.azure.com/chat/completions"; +const token = process.env["GITHUB_TOKEN"]; + +if (!token) { + throw new Error("GITHUB_TOKEN is required for README translation workflow."); +} + +const repoRoot = process.cwd(); +const sourcePath = path.join(repoRoot, "README.md"); +const targetPath = path.join(repoRoot, "README.zh-CN.md"); + +const source = await fs.readFile(sourcePath, "utf8"); +const currentTarget = await fs.readFile(targetPath, "utf8").catch(() => ""); + +const systemPrompt = [ + "You are a technical translator for GitHub README files.", + "Translate English Markdown content into Simplified Chinese.", + "Requirements:", + "- Keep all Markdown structure, links, image URLs, and code blocks intact.", + "- Translate only human-readable prose.", + "- Keep product names, file names, commands, and technical tokens unchanged.", + "- Output only the translated Markdown document, no explanation.", +].join("\n"); + +const userPrompt = [ + "Translate the following README.md into Simplified Chinese.", + "Return only the final Markdown content.", + "\n--- BEGIN README ---\n", + source, + "\n--- END README ---", +].join("\n"); + +const response = await fetch(API_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ + model: MODEL, + temperature: 0.1, + messages: [ + { role: "system", content: systemPrompt }, + { role: "user", content: userPrompt }, + ], + }), +}); + +if (!response.ok) { + const body = await response.text(); + throw new Error(`Translation request failed (${response.status}): ${body}`); +} + +const data = await response.json(); +const translated = data?.choices?.[0]?.message?.content?.trim(); + +if (!translated) { + throw new Error("No translated content returned by model."); +} + +await fs.writeFile(targetPath, `${translated}\n`, "utf8"); + +const changed = currentTarget !== `${translated}\n`; +const outputPath = process.env["GITHUB_OUTPUT"]; +if (outputPath) { + await fs.appendFile(outputPath, `changed=${changed}\n`, "utf8"); +} + +console.log(`[translate-readme-zh] README.zh-CN.md ${changed ? "updated" : "unchanged"}.`);