UNPKG

crowdin-auto-translation

Version:

automatic translating by crowdin and your specific config file

315 lines (272 loc) 8.15 kB
const path = require("path"); const fs = require("fs"); const crowdin = require("@crowdin/crowdin-api-client"); const downloadZip = require("./downloadZip"); const unzip = require("./unzip"); const convertJson2Js = require("./convertJson2Js"); const clearOutput = require("./clearOutput"); async function getFileId( sourceFilesApi, projectId, filePath, branchId = undefined, directoryId = undefined ) { const listParams = directoryId ? { directoryId } : { branchId }; const filesList = await sourceFilesApi.listProjectFiles( projectId, listParams ); const file = filesList.data.find((f) => f.data.path === filePath); console.log(file, filesList.data, filePath); return file ? file.data.id : null; } async function getOrCreateDirectory( sourceFilesApi, projectId, branchId, directoryPath ) { const directoriesRes = await sourceFilesApi.listProjectDirectories( projectId, { branchId, } ); let directory = directoriesRes.data.find( (dir) => dir.data.name === directoryPath ); if (!directory) { console.log(`Creating remote directory: ${directoryPath}`); directory = await sourceFilesApi.createDirectory(projectId, { name: directoryPath, branchId, }); } return directory.data.id; } async function createDirectoriesRecursively( sourceFilesApi, projectId, branchId, directoryPath ) { const pathParts = directoryPath.split("/"); let currentPath = ""; let currentDirectoryId; for (const pathPart of pathParts) { currentPath = path.join(currentPath, pathPart); currentDirectoryId = await getOrCreateDirectory( sourceFilesApi, projectId, branchId, currentPath ); } return currentDirectoryId; } module.exports = async (configPath) => { try { // 获取配置 const configAbsolutePath = path.resolve(configPath); if (!fs.existsSync(configAbsolutePath)) { throw new Error("config file does not exist"); } const config = require(configAbsolutePath); const { token, engineId, projectId, targetLanguageIds, branch, file, sourceFilePath, outputPath, outputFilePrefix, isOutputFullName, directory, } = config; // 获取配置文件所在路径 const prefixPath = path.dirname(configAbsolutePath); // 检查语言包源文件是否存在 const sourceFileAbsolutePath = path.join(prefixPath, sourceFilePath); if (!fs.existsSync(sourceFileAbsolutePath)) { throw new Error("source lang file does not exist"); } // 检查输出文件目录是否存在 const outputAbsolutePath = path.join(prefixPath, outputPath); if (!fs.existsSync(outputAbsolutePath)) { fs.mkdirSync(outputAbsolutePath); } // 创建crowdin sdk实例 const { translationsApi, sourceFilesApi, uploadStorageApi } = new crowdin.default({ token }); // 获取分支id和文件id let branchId, fileId; // 检查是否创建远程分支 console.log("check if a individual branch has been created..."); const branchListRes = await sourceFilesApi.listProjectBranches(projectId, { name: branch.name, }); if (branchListRes.data.length > 0) { branchId = branchListRes.data[0].data.id; } else { // create branch console.log("create individual branch..."); const createBranchRes = await sourceFilesApi.createBranch(projectId, { name: branch.name, title: branch.title, }); branchId = createBranchRes.data.id; } // 创建或获取目录 const directoryId = await createDirectoriesRecursively( sourceFilesApi, projectId, branchId, directory ); // 获取或创建文件 fileId = await getFileId( sourceFilesApi, projectId, `/${branch.name}/${directory}/${file.name}.js`, branchId, directoryId ); console.log("getFileId:", fileId); // 读取文件 const sourceFile = fs.readFileSync(sourceFileAbsolutePath); const sourceStr = sourceFile.toString(); const addStorageRes = await uploadStorageApi.addStorage( file.name, sourceStr ); const storageId = addStorageRes.data.id; if (fileId === null) { // 创建文件 console.log("create remote file"); const createFileRes = await sourceFilesApi.createFile(projectId, { branchId, directoryId, name: `${file.name}.js`, title: file.title || undefined, storageId: storageId, type: "js", }); fileId = createFileRes.data.id; } else { // 更新文件 console.log("update remote file..."); await sourceFilesApi.updateOrRestoreFile(projectId, fileId, { storageId, }); } // 预翻译 console.log("start translating..."); let { data: { identifier: preTransId, progress: preTransProgress }, } = await translationsApi.applyPreTranslation(projectId, { languageIds: targetLanguageIds, fileIds: [fileId], method: "mt", engineId: engineId, }); // 循环检查预翻译状态 while (preTransProgress < 100) { const preTransStatusRes = await translationsApi.preTranslationStatus( projectId, preTransId ); preTransProgress = preTransStatusRes.data.progress; console.log(`pre-translation progress: ${preTransProgress}%`); } // 构建 console.log("start building..."); let { data: { id: buildId, progress: buildProgress }, } = await translationsApi.buildProject(projectId, { branchId, targetLanguageIds: targetLanguageIds, }); // 循环检查构建状态 while (buildProgress < 100) { const buildStatusRes = await translationsApi.checkBuildStatus( projectId, buildId ); buildProgress = buildStatusRes.data.progress; console.log(`building progress: ${buildProgress}%`); } // 获取翻译文件的URL console.log("fetch url of translated zip..."); const { data: { url }, } = await translationsApi.downloadTranslations(projectId, buildId); // 下载翻译文件 console.log("download translated zip..."); await downloadZip(url, outputAbsolutePath); // 解压翻译文件 console.log("unzip..."); await unzip(outputAbsolutePath); // 将翻译文件从JSON转换为JS console.log("convert js to js..."); await convertJson2Js( directory, outputAbsolutePath, outputFilePrefix, targetLanguageIds, isOutputFullName ); // 清理输出文件夹 console.log("clear download file..."); clearOutput(outputAbsolutePath); console.log("done."); } catch (error) { console.error("An error occurred:", error); } }; // 优化后的代码模块 async function createDirectoriesRecursively( sourceFilesApi, projectId, branchId, directoryPath ) { const pathParts = directoryPath.split("/"); let currentPath = ""; let parentDirectoryId; for (const pathPart of pathParts) { currentPath = path.join(currentPath, pathPart); console.log("branchId:", branchId, "parentDirectoryId:", parentDirectoryId); const listParams = parentDirectoryId ? { directoryId: parentDirectoryId } : { branchId }; const directoriesList = await sourceFilesApi.listProjectDirectories( projectId, listParams ); const existingDirectory = directoriesList.data.find( (dir) => dir.data.name === pathPart ); if (existingDirectory) { parentDirectoryId = existingDirectory.data.id; } else { console.log(`Creating remote directory: ${currentPath}`); const directoryData = { name: pathPart, }; if (parentDirectoryId) { directoryData.directoryId = parentDirectoryId; } else { directoryData.branchId = branchId; } const newDirectory = await sourceFilesApi.createDirectory( projectId, directoryData ); parentDirectoryId = newDirectory.data.id; } } return parentDirectoryId; }