| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- /**
- * How to use it:
- * - cd apps/docs
- * - Add apps/docs/.env file, to set OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL
- * - Use `git add .` to add all changed docs to git staged changes
- * - Run `npm run translate:zh` to translate all zh files to en
- */
- import * as process from 'process';
- import path from 'path';
- import fs from 'fs';
- import { execSync } from 'child_process';
- import { ChatCompletionMessageParam } from 'openai/resources/chat';
- import OpenAI from 'openai';
- // eslint-disable-next-line import/no-extraneous-dependencies
- import 'dotenv/config';
- const languages = ['zh', 'en'];
- const __dirname = path.dirname(new URL(import.meta.url).pathname);
- const ai = new OpenAI({
- apiKey: process.env.OPENAI_API_KEY,
- baseURL: process.env.OPENAI_BASE_URL,
- });
- const model = process.env.OPENAI_MODEL!;
- const sourceLang = process.argv[2];
- if (!languages.includes(sourceLang)) {
- console.error(`Invalid language: ${sourceLang}`);
- process.exit(1);
- }
- const targetLangs = languages.filter((_lang) => _lang !== sourceLang);
- async function translateContent(
- content: string,
- targetLang: string,
- previousTargetContent?: string
- ) {
- let systemPrompts = `
- You are a translator.
- You will translate the following content from ${sourceLang} to ${targetLang}.\n
- `;
- if (previousTargetContent) {
- systemPrompts += `
- The target file is translated previously, here is the content:
- ${previousTargetContent}
- Only translate the content that is different in ${sourceLang}.\n
- `;
- }
- systemPrompts += `
- Constraint:
- - ONLY RETURN THE TRANSLATED CONTENT, NO OTHER TEXT.
- `;
- const messages: ChatCompletionMessageParam[] = [
- {
- role: 'system',
- content: systemPrompts,
- },
- { role: 'user', content },
- ];
- const response = await ai.chat.completions.create({
- model,
- messages,
- });
- return response.choices[0].message.content ?? '';
- }
- async function translateFiles() {
- // 1. Get Stage Changed Documentations for source language
- const gitDiffOutput = execSync('git diff --cached --name-only', {
- encoding: 'utf-8',
- });
- const allChangedFiles: string[] = gitDiffOutput.split('\n').filter(Boolean);
- console.log('Get Diff files:', allChangedFiles);
- const sourceLangFolder = path.join(__dirname, '../src', sourceLang);
- const sourceLangFolderAbs = path.join('apps/docs/src', sourceLang);
- // Find all *.md, *.mdx files in sourceLangFolder
- const diffMarkdownFiles: string[] = allChangedFiles
- .filter(
- (file) =>
- file.includes(sourceLangFolderAbs) && (file.endsWith('.md') || file.endsWith('.mdx'))
- )
- .map((file) => path.relative(sourceLangFolderAbs, file));
- console.log('Files to be translated:', diffMarkdownFiles);
- // 2. For each file, translate it to other language
- await Promise.all(
- diffMarkdownFiles.map(async (file) => {
- for (const targetLang of targetLangs) {
- const targetLangFolder = path.join(__dirname, '../src', targetLang);
- const sourceFile = path.join(sourceLangFolder, file);
- const targetFile = path.join(targetLangFolder, file);
- // 2.1. Read the file
- const sourceContent = fs.readFileSync(sourceFile, 'utf-8');
- console.log(`Translate ${sourceFile} to ${targetFile}`);
- console.log(sourceContent);
- console.log('\n\n\n\n\n');
- const previousTargetContent = fs.existsSync(targetFile)
- ? fs.readFileSync(targetFile, 'utf-8')
- : undefined;
- // 2.2. Translate the content
- const targetContent = await translateContent(
- sourceContent,
- targetLang,
- previousTargetContent
- );
- // 2.3. Write the translated file
- fs.writeFileSync(targetFile, targetContent);
- console.log(`Translated: ${targetFile}`);
- console.log(targetContent);
- console.log('\n\n\n\n\n');
- }
- })
- );
- }
- translateFiles().catch((err) => {
- console.error('Error generating docs:', err);
- });
|