From ffebb3ffa89c5595af5e440a76051ef995cd21c6 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Tue, 31 Dec 2024 21:53:46 +0800 Subject: [PATCH] Support auto translate to english --- .github/workflows/docs-translate.yaml | 35 ++++++++++++- bin/doc-translate.github-model.js | 52 +++++++++++++++++++ bin/doc-translate.js | 73 +++++++++++++-------------- 3 files changed, 121 insertions(+), 39 deletions(-) create mode 100644 bin/doc-translate.github-model.js diff --git a/.github/workflows/docs-translate.yaml b/.github/workflows/docs-translate.yaml index a3d66a61b..2fe802f94 100644 --- a/.github/workflows/docs-translate.yaml +++ b/.github/workflows/docs-translate.yaml @@ -6,7 +6,7 @@ on: - 'docs/**' jobs: - translate: + translate-zh: runs-on: ubuntu-latest steps: - name: Checkout @@ -48,3 +48,36 @@ jobs: uses: stefanzweifel/git-auto-commit-action@v4 with: commit_message: Update docs and translate + + translate-en: + runs-on: ubuntu-latest + env: + DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + name: Install pnpm + with: + version: 9 + run_install: false + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Start Translate + run: | + cp docs/index.md docs/en/index.md + pnpm run doc-translate + + - name: Commit Updated + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Update docs and translate \ No newline at end of file diff --git a/bin/doc-translate.github-model.js b/bin/doc-translate.github-model.js new file mode 100644 index 000000000..bc0f12968 --- /dev/null +++ b/bin/doc-translate.github-model.js @@ -0,0 +1,52 @@ +import OpenAI from "openai"; +import { promises as fs } from 'fs'; +import path from 'path'; + +const token = process.env["GITHUB_TOKEN"]; +const endpoint = "https://models.inference.ai.azure.com"; +const modelName = "o1-mini"; + +async function translateFiles() { + const client = new OpenAI({ + baseURL: endpoint, + apiKey: token, + dangerouslyAllowBrowser: true + }); + + const docsPath = path.join(process.cwd(), 'docs/zh-cn'); + + async function translateFile(filePath) { + const content = await fs.readFile(filePath, 'utf8'); + const response = await client.chat.completions.create({ + messages: [ + { role: "user", content: "You are a professional translator. Translate the following Markdown content from Chinese to English. Preserve all Markdown formatting." }, + { role: "user", content: content } + ], + model: modelName + }); + + const translatedContent = response.choices[0].message.content; + const englishPath = filePath.replace('/zh-cn/', '/en/'); + await fs.mkdir(path.dirname(englishPath), { recursive: true }); + await fs.writeFile(englishPath, translatedContent); + console.log(`Translated: ${filePath} -> ${englishPath}`); + } + + async function processDirectory(dirPath) { + const files = await fs.readdir(dirPath, { withFileTypes: true }); + + for (const file of files) { + const fullPath = path.join(dirPath, file.name); + + if (file.isDirectory()) { + await processDirectory(fullPath); + } else if (file.name.endsWith('.md')) { + await translateFile(fullPath); + } + } + } + + await processDirectory(docsPath); +} + +translateFiles().catch(console.error); diff --git a/bin/doc-translate.js b/bin/doc-translate.js index bc0f12968..f9ea1272e 100644 --- a/bin/doc-translate.js +++ b/bin/doc-translate.js @@ -1,52 +1,49 @@ import OpenAI from "openai"; -import { promises as fs } from 'fs'; +import { readdir, readFile, writeFile, mkdir } from 'fs/promises'; import path from 'path'; -const token = process.env["GITHUB_TOKEN"]; -const endpoint = "https://models.inference.ai.azure.com"; -const modelName = "o1-mini"; +const endpoint = "https://api.deepseek.com"; +const token = process.env["DEEPSEEK_API_KEY"]; -async function translateFiles() { - const client = new OpenAI({ +const openai = new OpenAI({ baseURL: endpoint, apiKey: token, - dangerouslyAllowBrowser: true - }); - - const docsPath = path.join(process.cwd(), 'docs/zh-cn'); - - async function translateFile(filePath) { - const content = await fs.readFile(filePath, 'utf8'); - const response = await client.chat.completions.create({ - messages: [ - { role: "user", content: "You are a professional translator. Translate the following Markdown content from Chinese to English. Preserve all Markdown formatting." }, - { role: "user", content: content } - ], - model: modelName +}); + +async function translateContent(content) { + const completion = await openai.chat.completions.create({ + messages: [ + { role: "system", content: "You are a professional translator. Translate the following Chinese markdown content to English. Keep all markdown formatting intact." }, + { role: "user", content: content } + ], + model: "deepseek-chat", }); + return completion.choices[0].message.content; +} - const translatedContent = response.choices[0].message.content; - const englishPath = filePath.replace('/zh-cn/', '/en/'); - await fs.mkdir(path.dirname(englishPath), { recursive: true }); - await fs.writeFile(englishPath, translatedContent); - console.log(`Translated: ${filePath} -> ${englishPath}`); - } +async function translateFiles(srcDir, destDir) { + try { + const files = await readdir(srcDir, { recursive: true }); - async function processDirectory(dirPath) { - const files = await fs.readdir(dirPath, { withFileTypes: true }); + for (const file of files) { + if (!file.endsWith('.md')) continue; - for (const file of files) { - const fullPath = path.join(dirPath, file.name); + const srcPath = path.join(srcDir, file); + const destPath = path.join(destDir, file); + const destFolder = path.dirname(destPath); - if (file.isDirectory()) { - await processDirectory(fullPath); - } else if (file.name.endsWith('.md')) { - await translateFile(fullPath); - } - } - } + await mkdir(destFolder, { recursive: true }); - await processDirectory(docsPath); + const content = await readFile(srcPath, 'utf8'); + const translatedContent = await translateContent(content); + const finalContent = translatedContent.replace(/\/zh-cn\//g, '/en/'); + await writeFile(destPath, finalContent); + + console.log(`Translated: ${file}`); + } + } catch (error) { + console.error('Translation error:', error); + } } -translateFiles().catch(console.error); +translateFiles('docs/zh-cn', 'docs/en'); \ No newline at end of file