2024-08-03 12:46:12 +08:00
|
|
|
|
import { GeneralResponse } from "../../../model/generalResponse";
|
|
|
|
|
|
import { TranslateModel } from "../../../model/translate";
|
|
|
|
|
|
import { errorMessage, successMessage } from "../../Public/generalTools";
|
|
|
|
|
|
import { Translate } from "./Translate";
|
|
|
|
|
|
import { DEFINE_STRING } from "../../../define/define_string"
|
|
|
|
|
|
import { TranslateAPIType, TranslateType } from "../../../define/enum/translate";
|
|
|
|
|
|
import { BookTaskDetailService } from "../../../define/db/service/Book/bookTaskDetailService";
|
|
|
|
|
|
import { Book } from "../../../model/book";
|
|
|
|
|
|
import { ResponseMessageType } from "../../../define/enum/softwareEnum";
|
|
|
|
|
|
import { SoftwareService } from '../../../define/db/service/SoftWare/softwareService'
|
|
|
|
|
|
import { isEmpty } from "lodash";
|
|
|
|
|
|
import { ValidateJson } from "../../../define/Tools/validate";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 翻译实现服务
|
|
|
|
|
|
*/
|
|
|
|
|
|
export class TranslateService {
|
|
|
|
|
|
translate: Translate
|
|
|
|
|
|
bookTaskDetail: BookTaskDetailService;
|
|
|
|
|
|
softwareService: SoftwareService
|
|
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async InitService() {
|
|
|
|
|
|
if (!this.bookTaskDetail) {
|
|
|
|
|
|
this.bookTaskDetail = await BookTaskDetailService.getInstance()
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!this.softwareService) {
|
|
|
|
|
|
this.softwareService = await SoftwareService.getInstance()
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!this.translate) {
|
|
|
|
|
|
this.translate = new Translate()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 返回翻译结果。用于前端修改
|
|
|
|
|
|
private sendTranslateReturn(windowId: number, data: GeneralResponse.MessageResponse): void {
|
|
|
|
|
|
let win = global.newWindow[0]
|
|
|
|
|
|
if (windowId) {
|
|
|
|
|
|
win = global.newWindow.filter(item => item.id == windowId)[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
win.win.webContents.send(DEFINE_STRING.BOOK.MAIN_DATA_RETURN, data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#region 翻译设置
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化翻译设置
|
|
|
|
|
|
* @returns
|
|
|
|
|
|
*/
|
|
|
|
|
|
InitialTranslateSetting(): TranslateModel.TranslateModel {
|
|
|
|
|
|
return {
|
|
|
|
|
|
selectModel: TranslateAPIType.BAIDU,
|
2024-08-04 15:00:00 +08:00
|
|
|
|
translation_auto: true,
|
2024-08-03 12:46:12 +08:00
|
|
|
|
translates: [
|
2024-08-09 12:28:28 +08:00
|
|
|
|
{
|
|
|
|
|
|
name: TranslateAPIType.LAITOOL,
|
|
|
|
|
|
translation_business: "https://api.laitool.cc/v1/chat/completions",
|
|
|
|
|
|
translation_app_id: "gpt-4o-mini",
|
|
|
|
|
|
translation_secret: "LAI API 令牌"
|
|
|
|
|
|
},
|
2024-08-03 12:46:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
name: TranslateAPIType.BAIDU,
|
|
|
|
|
|
translation_business: "https://fanyi-api.baidu.com/api/trans/vip/translate",
|
2024-08-04 15:00:00 +08:00
|
|
|
|
translation_app_id: "百度翻译的APP ID",
|
|
|
|
|
|
translation_secret: "百度翻译的密钥"
|
2024-08-03 12:46:12 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: TranslateAPIType.TENCENT,
|
|
|
|
|
|
translation_business: "https://tmt.tencentcloudapi.com",
|
2024-08-04 15:00:00 +08:00
|
|
|
|
translation_app_id: '腾讯云的APP ID',
|
|
|
|
|
|
translation_secret: "腾讯云的密钥"
|
2024-08-03 12:46:12 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: TranslateAPIType.VOLCENGINE,
|
|
|
|
|
|
translation_business: "https://translate.volcengineapi.com?",
|
2024-08-04 15:00:00 +08:00
|
|
|
|
translation_app_id: '火山引擎的APP ID',
|
|
|
|
|
|
translation_secret: '火山引擎的密钥'
|
2024-08-03 12:46:12 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: TranslateAPIType.ALI,
|
|
|
|
|
|
translation_business: "https://mt.cn-hangzhou.aliyuncs.com",
|
2024-08-04 15:00:00 +08:00
|
|
|
|
translation_app_id: '阿里云的APP ID',
|
|
|
|
|
|
translation_secret: '阿里云的密钥'
|
2024-08-03 12:46:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取翻译设置
|
|
|
|
|
|
*/
|
|
|
|
|
|
async GetTranslateSetting(): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await this.InitService()
|
|
|
|
|
|
let translateSetting = undefined as TranslateModel.TranslateModel
|
|
|
|
|
|
let translateSettingString = this.softwareService.GetSoftWarePropertyData('translationSetting');
|
|
|
|
|
|
if (isEmpty(translateSettingString)) {
|
|
|
|
|
|
// 初始化
|
2024-08-04 15:00:00 +08:00
|
|
|
|
translateSetting = this.InitialTranslateSetting();
|
|
|
|
|
|
await this.ResetTranslateSetting();
|
|
|
|
|
|
translateSettingString = this.softwareService.GetSoftWarePropertyData('translationSetting');
|
|
|
|
|
|
translateSetting = JSON.parse(translateSettingString);
|
2024-08-03 12:46:12 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 解析
|
|
|
|
|
|
let tryParse = ValidateJson(translateSettingString)
|
|
|
|
|
|
if (!tryParse) {
|
|
|
|
|
|
throw new Error("翻译设置数据解析失败")
|
|
|
|
|
|
}
|
|
|
|
|
|
translateSetting = JSON.parse(translateSettingString);
|
|
|
|
|
|
}
|
2024-08-09 12:28:28 +08:00
|
|
|
|
|
|
|
|
|
|
// v3.0.1 preview 4 版本新增laitool gpt翻译,之前版本没有,这边要检测下是不是有配置,没有初始化
|
|
|
|
|
|
let index = translateSetting.translates.findIndex(item => item.name == TranslateAPIType.LAITOOL);
|
|
|
|
|
|
if (index < 0) {
|
|
|
|
|
|
// 初始化,将数据加在最前面
|
|
|
|
|
|
let laitool = {
|
|
|
|
|
|
name: TranslateAPIType.LAITOOL,
|
|
|
|
|
|
translation_business: "https://api.laitool.cc/v1/chat/completions",
|
|
|
|
|
|
translation_app_id: "gpt-4o-mini",
|
|
|
|
|
|
translation_secret: "LAI API 令牌"
|
|
|
|
|
|
}
|
|
|
|
|
|
translateSetting.translates.unshift(laitool)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-03 12:46:12 +08:00
|
|
|
|
return successMessage(translateSetting, "获取翻译设置成功", "TranslateService_GetTranslateSetting")
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("获取翻译设置失败,失败信息如下:" + error.toString(), "TranslateService_GetTranslateSetting")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 重置翻译设置
|
|
|
|
|
|
*/
|
|
|
|
|
|
async ResetTranslateSetting(): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let translateSetting = this.InitialTranslateSetting()
|
|
|
|
|
|
let res = this.softwareService.SaveSoftwarePropertyData('translationSetting', JSON.stringify(translateSetting))
|
|
|
|
|
|
return successMessage(translateSetting, "重置翻译设置成功", "TranslateService_ResetTranslateSetting")
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("重置翻译设置失败,失败信息如下:" + error.toString(), "TranslateService_ResetTranslateSetting")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 保存翻译设置
|
|
|
|
|
|
* @param value 保存的数据
|
|
|
|
|
|
* @returns
|
|
|
|
|
|
*/
|
|
|
|
|
|
async SaveTranslateSetting(value: TranslateModel.TranslateModel): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let res = this.softwareService.SaveSoftwarePropertyData('translationSetting', JSON.stringify(value))
|
2024-08-09 12:28:28 +08:00
|
|
|
|
// 这边要判断是不是用的laitool
|
|
|
|
|
|
let laitool = value.translates.filter(item => item.name == TranslateAPIType.LAITOOL)
|
|
|
|
|
|
if (laitool.length > 0) {
|
|
|
|
|
|
let laitoolData = laitool[0]
|
|
|
|
|
|
if (!laitoolData.translation_business.includes('laitool')) {
|
|
|
|
|
|
throw new Error("不允许修改laitool的地址为其他外站地址")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-08-03 12:46:12 +08:00
|
|
|
|
return successMessage(value, "保存翻译设置成功", "TranslateService_SaveTranslateSetting")
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("保存翻译设置失败,失败信息如下:" + error.toString(), "TranslateService_SaveTranslateSetting")
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 反推翻译提示词处理
|
|
|
|
|
|
* @param bookTaskDetailId 对应的分镜ID
|
|
|
|
|
|
* @param reversePromptId 对应的反推提示词数据ID
|
|
|
|
|
|
* @param to 目标语言
|
|
|
|
|
|
* @param dstString 翻译后的字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
private async TranslateProcessReversePrompt(bookTaskDetailId: string, reversePromptId: string, to: string, dstString: string): Promise<void> {
|
|
|
|
|
|
// 开始修改翻译后的数据
|
|
|
|
|
|
let updateData = {} as Book.ReversePrompt
|
|
|
|
|
|
if (to == "zh") {
|
|
|
|
|
|
updateData.promptCN = dstString
|
|
|
|
|
|
} else if (to == "en") {
|
|
|
|
|
|
updateData.prompt = dstString
|
|
|
|
|
|
updateData.promptCN = dstString
|
|
|
|
|
|
}
|
|
|
|
|
|
// 修改数据
|
|
|
|
|
|
this.bookTaskDetail.UpdateBookTaskDetailReversePrompt(bookTaskDetailId, reversePromptId, updateData)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理返回的数据
|
|
|
|
|
|
async TranslateReturnProcess(value: TranslateModel.TranslateNowIPCParams, to: string, dstString: string) {
|
|
|
|
|
|
switch (value.type) {
|
|
|
|
|
|
case TranslateType.REVERSE_PROMPT_TRANSLATE:
|
|
|
|
|
|
await this.TranslateProcessReversePrompt(value.bookTaskDetailId, value.reversePromptId, to, dstString)
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
throw new Error("未知的翻译类型");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 翻译
|
|
|
|
|
|
async TranslateNowReturn(value: TranslateModel.TranslateNowIPCParams[]): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await this.InitService()
|
|
|
|
|
|
// 循环所有的数据,返回翻译结果
|
|
|
|
|
|
for (let i = 0; i < value.length; i++) {
|
|
|
|
|
|
const element = value[i];
|
|
|
|
|
|
let res = await this.translate.TranslateReturnNow(element)
|
|
|
|
|
|
// 单个翻译,将返回的数据写入到原数据中
|
|
|
|
|
|
|
|
|
|
|
|
// 添加一个对返回信息进行处理的函数
|
|
|
|
|
|
let data = res.data
|
|
|
|
|
|
// 先将数据进行拼接
|
|
|
|
|
|
let srcString = ""
|
|
|
|
|
|
if (element.isSplit) {
|
|
|
|
|
|
let dstStrs = []
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 没有拆分的,只有一句
|
|
|
|
|
|
srcString = data.data[0].dst
|
|
|
|
|
|
}
|
|
|
|
|
|
// 写回数据库
|
|
|
|
|
|
await this.TranslateReturnProcess(element, data.to, srcString);
|
|
|
|
|
|
|
|
|
|
|
|
// 做个返回数据
|
|
|
|
|
|
this.sendTranslateReturn(element.windowId, {
|
|
|
|
|
|
code: 1,
|
|
|
|
|
|
id: element.bookTaskDetailId,
|
|
|
|
|
|
type: ResponseMessageType.PROMPT_TRANSLATE,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
progress: i + 1,
|
|
|
|
|
|
total: value.length,
|
|
|
|
|
|
from: element.from,
|
|
|
|
|
|
to: data.to,
|
|
|
|
|
|
bookTaskDetailId: element.bookTaskDetailId,
|
|
|
|
|
|
reversePromptId: element.reversePromptId,
|
|
|
|
|
|
prompt: srcString,
|
|
|
|
|
|
promptCN: srcString
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return successMessage(null, "全部翻译完成", "TranslateService_TranslateNowReturn")
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return errorMessage("翻译失败,失败信息如下:" + error.toString(), "TranslateService_TranslateNowReturn")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|