You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
3.3 KiB
80 lines
3.3 KiB
package user
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"yunyan/comm"
|
|
"yunyan/lego/sys/log"
|
|
"yunyan/pb"
|
|
)
|
|
|
|
// @Summary 实时机器翻译
|
|
// @Description 同声传译/面对面翻译用;服务端调用后台「第三方服务配置」里启用的 MT 服务
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Security BearerAuth
|
|
// @Param user body pb.UserTranslateReq true "翻译请求"
|
|
// @Success 200 {object} comm.HttpResult{data=pb.UserTranslateResp} "成功返回"
|
|
// @Router /api/home/user_translate [post]
|
|
//
|
|
// 语言码:客户端传 BCP-47(zh-CN/en-US),这里统一归一成服务商要的短码。
|
|
// 阿里云对语言码传错不会报错,只会返回空或原文,所以归一放服务端收口。
|
|
func (this *apiComp) Translate(session comm.IUserSession, req *pb.UserTranslateReq) (resp *pb.UserTranslateResp, errdata *pb.ErrorData) {
|
|
text := strings.TrimSpace(req.Text)
|
|
to := comm.BCP47ToShortLang(req.To)
|
|
from := comm.BCP47ToShortLang(req.From)
|
|
|
|
if text == "" || to == "" {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_TranslateParamInvalid, Message: "原文或目标语言为空"}
|
|
return
|
|
}
|
|
// 同语种直接回原文,别浪费一次调用(同传里源=目标的情况很常见)
|
|
if from != "" && from == to {
|
|
resp = &pb.UserTranslateResp{Text: req.Text}
|
|
return
|
|
}
|
|
|
|
svcId, provider, tr, err := this.module.translatemodel.resolveTranslator()
|
|
if err != nil {
|
|
this.module.Error("Translate: 翻译服务解析失败",
|
|
log.Field{Key: "svc", Value: svcId}, log.Field{Key: "provider", Value: provider},
|
|
log.Field{Key: "err", Value: err.Error()})
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_TranslateNotConfigured, Message: "翻译服务不可用"}
|
|
return
|
|
}
|
|
if tr == nil {
|
|
// 没配,或者配的是还没接的服务商
|
|
this.module.Warn("Translate: 无可用翻译服务",
|
|
log.Field{Key: "svc", Value: svcId}, log.Field{Key: "provider", Value: provider})
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_TranslateNotConfigured, Message: "未配置机器翻译服务"}
|
|
return
|
|
}
|
|
|
|
// from 为空即自动检测:交给服务商识别,省掉一次单独的语种识别调用,
|
|
// 检测出的短码随响应回带,客户端据此把「自动检测」显示成具体语种。
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
translated, detected, err := tr.TranslateDetect(ctx, from, to, text)
|
|
if err != nil {
|
|
this.module.Error("Translate: 服务商调用失败",
|
|
log.Field{Key: "uid", Value: session.GetUserId()}, log.Field{Key: "svc", Value: svcId},
|
|
log.Field{Key: "from", Value: from}, log.Field{Key: "to", Value: to},
|
|
log.Field{Key: "err", Value: err.Error()})
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_TranslateProviderError, Message: "翻译失败,请稍后再试"}
|
|
return
|
|
}
|
|
if strings.TrimSpace(translated) == "" {
|
|
// 返回空通常意味着语言码不被支持——报错比悄悄返回空串强,
|
|
// 否则客户端会显示一片空白,谁也不知道发生了什么。
|
|
this.module.Warn("Translate: 服务商返回空结果",
|
|
log.Field{Key: "svc", Value: svcId}, log.Field{Key: "from", Value: from}, log.Field{Key: "to", Value: to})
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_TranslateProviderError, Message: "翻译结果为空"}
|
|
return
|
|
}
|
|
|
|
resp = &pb.UserTranslateResp{Text: translated, Provider: provider, Svcid: svcId, DetectedFrom: detected}
|
|
return
|
|
}
|
|
|