From ecbe8d433ab407a5f8f5940fe6b9aa7351d7f0ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=87=AA=E7=94=B1=E7=9A=84=E4=B8=96=E7=95=8C=E4=BA=BA?= <3196812536@qq.com> Date: Fri, 5 Sep 2025 19:28:05 +0800 Subject: [PATCH] try with cc --- .github/workflows/translator.yml | 63 ++++------ scripts/github-translator.js | 208 ------------------------------- 2 files changed, 21 insertions(+), 250 deletions(-) delete mode 100644 scripts/github-translator.js diff --git a/.github/workflows/translator.yml b/.github/workflows/translator.yml index 54e1e96a53..740719e470 100644 --- a/.github/workflows/translator.yml +++ b/.github/workflows/translator.yml @@ -1,57 +1,36 @@ -name: GitHub Issue Translator - -env: - API_KEY: ${{ secrets.TRANSLATE_API_KEY}} - MODEL: ${{ vars.MODEL || 'deepseek/deepseek-v3.1'}} - BASE_URL: ${{ vars.BASE_URL || 'https://api.ppinfra.com/openai'}} +name: Use Claude To Translate on: issues: types: [opened, edited] issue_comment: types: [created, edited] - discussion: - types: [created, edited] - discussion_comment: - types: [created, edited] - pull_request_target: - types: [opened, edited] - pull_request_review_comment: - types: [created, edited] - workflow_dispatch: jobs: - translate: + claude-response: + if: | + (github.event_name == 'issue_comment')||(github.event_name == 'issues') runs-on: ubuntu-latest - if: github.repository == 'CherryHQ/cherry-studio' - name: Auto Translate GitHub Content permissions: - issues: write - discussions: write - pull-requests: write contents: read - + pull-requests: read + issues: read + id-token: write + actions: read # Required for Claude to read CI results on PRs steps: - - name: 🐈‍⬛ Checkout - uses: actions/checkout@v5 - - - name: 📦 Setting Node.js - uses: actions/setup-node@v4 + - name: Checkout repository + uses: actions/checkout@v4 with: - node-version: 20 + fetch-depth: 1 - - name: 📦 Install translation dependencies - run: | - mkdir -p /tmp/translation-deps - cd /tmp/translation-deps - echo '{"dependencies": {"openai": "^5.12.2", "@octokit/rest": "^21.0.0"}}' > package.json - npm install --no-package-lock - echo "NODE_PATH=/tmp/translation-deps/node_modules" >> $GITHUB_ENV + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - - name: 🌐 Run Translation Script - run: node scripts/github-translator.js - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_REPOSITORY: ${{ github.repository }} - GITHUB_EVENT_NAME: ${{ github.event_name }} - GITHUB_CONTEXT: ${{ toJSON(github) }} + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read + + prompt: "Replace the issue with its English translation and substitute the original language." diff --git a/scripts/github-translator.js b/scripts/github-translator.js deleted file mode 100644 index 3ddf23df2e..0000000000 --- a/scripts/github-translator.js +++ /dev/null @@ -1,208 +0,0 @@ -const { Octokit } = require('@octokit/rest') -const OpenAI = require('openai') - -class GitHubTranslator { - constructor() { - this.octokit = new Octokit({ - auth: process.env.GITHUB_TOKEN - }) - - this.openai = new OpenAI({ - apiKey: process.env.API_KEY, - baseURL: process.env.BASE_URL - }) - - this.model = process.env.MODEL || 'deepseek/deepseek-v3.1' - this.repo = process.env.GITHUB_REPOSITORY.split('/') - this.context = JSON.parse(process.env.GITHUB_CONTEXT) - } - - async translateText(text, targetLang = 'English') { - if (!text || this.isAlreadyTranslated(text) || this.isPrimarylyEnglish(text)) { - return null - } - - try { - const response = await this.openai.chat.completions.create({ - model: this.model, - messages: [ - { - role: 'system', - content: `You are a professional translator. Translate the following text to ${targetLang}. Keep the original formatting (markdown, code blocks, links) intact. If the text is already primarily in ${targetLang}, respond with "NO_TRANSLATION_NEEDED".` - }, - { - role: 'user', - content: text - } - ], - temperature: 0.3 - }) - - const translation = response.choices[0].message.content.trim() - return translation === 'NO_TRANSLATION_NEEDED' ? null : translation - } catch (error) { - console.error('Translation error:', error) - return null - } - } - - isAlreadyTranslated(text) { - return ( - text.includes('**🌐 Translation**') || - text.includes('**English Translation**') || - text.includes('') - ) - } - - isPrimarylyEnglish(text) { - // Simple heuristic: if text contains mostly English characters - const englishChars = text.match(/[a-zA-Z\s]/g) || [] - const totalChars = text.replace(/\s/g, '') - return englishChars.length / totalChars.length > 0.7 - } - - formatTranslation(originalText, translation) { - return `${originalText} - ---- - -**🌐 English Translation:** - -${translation} - -` - } - - async handleIssue() { - const issue = this.context.event.issue - if (!issue) return - - let updates = {} - - // Translate title - if (issue.title) { - const translatedTitle = await this.translateText(issue.title) - if (translatedTitle) { - updates.title = `${issue.title} / ${translatedTitle}` - } - } - - // Translate body - if (issue.body) { - const translatedBody = await this.translateText(issue.body) - if (translatedBody) { - updates.body = this.formatTranslation(issue.body, translatedBody) - } - } - - // Update issue if we have translations - if (Object.keys(updates).length > 0) { - await this.octokit.issues.update({ - owner: this.repo[0], - repo: this.repo[1], - issue_number: issue.number, - ...updates - }) - - console.log(`✅ Translated issue #${issue.number}`) - } - } - - async handleComment() { - const comment = this.context.event.comment - if (!comment) return - - const translatedBody = await this.translateText(comment.body) - if (translatedBody) { - await this.octokit.issues.updateComment({ - owner: this.repo[0], - repo: this.repo[1], - comment_id: comment.id, - body: this.formatTranslation(comment.body, translatedBody) - }) - - console.log(`✅ Translated comment #${comment.id}`) - } - } - - async handlePullRequest() { - const pr = this.context.event.pull_request - if (!pr) return - - let updates = {} - - // Translate title - if (pr.title) { - const translatedTitle = await this.translateText(pr.title) - if (translatedTitle) { - updates.title = `${pr.title} / ${translatedTitle}` - } - } - - // Translate body - if (pr.body) { - const translatedBody = await this.translateText(pr.body) - if (translatedBody) { - updates.body = this.formatTranslation(pr.body, translatedBody) - } - } - - // Update PR if we have translations - if (Object.keys(updates).length > 0) { - await this.octokit.pulls.update({ - owner: this.repo[0], - repo: this.repo[1], - pull_number: pr.number, - ...updates - }) - - console.log(`✅ Translated PR #${pr.number}`) - } - } - - async handleDiscussion() { - // Note: GitHub's GraphQL API would be needed for full discussion support - console.log('Discussion translation not implemented yet') - } - - async run() { - try { - const eventName = process.env.GITHUB_EVENT_NAME - - console.log(`🌐 Processing ${eventName} event...`) - - switch (eventName) { - case 'issues': - await this.handleIssue() - break - case 'issue_comment': - await this.handleComment() - break - case 'pull_request': - case 'pull_request_target': - await this.handlePullRequest() - break - case 'pull_request_review_comment': - await this.handleComment() - break - case 'discussion': - case 'discussion_comment': - await this.handleDiscussion() - break - default: - console.log(`Event ${eventName} not supported`) - } - } catch (error) { - console.error('Translation workflow error:', error) - process.exit(1) - } - } -} - -// Run the translator -if (require.main === module) { - const translator = new GitHubTranslator() - translator.run() -} - -module.exports = GitHubTranslator