|
|
|
@ -1,6 +1,7 @@ |
|
|
|
package translate |
|
|
|
|
|
|
|
import ( |
|
|
|
"bytes" |
|
|
|
"context" |
|
|
|
"encoding/json" |
|
|
|
"fmt" |
|
|
|
@ -41,13 +42,45 @@ func newSys(options Options) (sys *AliTranslate, err error) { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// flexStr 兼容阿里同一个字段的两种形状:字符串或数字。
|
|
|
|
//
|
|
|
|
// ⚠️ 这不是洁癖,是一次真实事故(2026-09-19):TranslateGeneral 正常响应里
|
|
|
|
// `Code` 是字符串 "200",而**鉴权层**的错误(产品未开通)回的是**数字**:
|
|
|
|
//
|
|
|
|
// {"Message":"Auth check failed! ... service:[alimt] is not activated.","Code":10009}
|
|
|
|
//
|
|
|
|
// 字段声明成 string 时这里直接 unmarshal 失败,错误变成
|
|
|
|
// 「cannot unmarshal number into Go struct field ... of type string」——
|
|
|
|
// 真正的原因(产品没开通)被盖住,而且 comm.IsLangUnsupportedErr 那套靠匹配
|
|
|
|
// `code=10005` 分流的逻辑也一并失效,所有阿里翻译错误都退化成「请稍后再试」,
|
|
|
|
// 用户只会一直点重试。
|
|
|
|
type flexStr string |
|
|
|
|
|
|
|
func (f *flexStr) UnmarshalJSON(b []byte) error { |
|
|
|
b = bytes.TrimSpace(b) |
|
|
|
if len(b) == 0 || string(b) == "null" { |
|
|
|
*f = "" |
|
|
|
return nil |
|
|
|
} |
|
|
|
if b[0] == '"' { |
|
|
|
var s string |
|
|
|
if err := json.Unmarshal(b, &s); err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
*f = flexStr(s) |
|
|
|
return nil |
|
|
|
} |
|
|
|
*f = flexStr(b) // 数字/布尔等,原样按字面量取
|
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
// translateGeneralResponse Aliyun MT TranslateGeneral 响应
|
|
|
|
type translateGeneralResponse struct { |
|
|
|
RequestId string `json:"RequestId"` |
|
|
|
Code string `json:"Code"` |
|
|
|
Code flexStr `json:"Code"` |
|
|
|
Message string `json:"Message,omitempty"` |
|
|
|
Data struct { |
|
|
|
WordCount string `json:"WordCount"` |
|
|
|
WordCount flexStr `json:"WordCount"` |
|
|
|
Translated string `json:"Translated"` |
|
|
|
// SourceLanguage 传 auto 时,阿里会在这里回填它检测出的源语种(短码)。
|
|
|
|
// 文本翻译的「自动检测」靠它把语种显示回界面。
|
|
|
|
@ -78,6 +111,11 @@ func (this *AliTranslate) translateOne(from, to, text string) (translated, detec |
|
|
|
return "", "", fmt.Errorf("unmarshal response: %w body=%s", err, body) |
|
|
|
} |
|
|
|
if out.Code != "" && out.Code != "200" { |
|
|
|
// 「产品没开通」是配置问题,重试一万次也没用,单独把话说明白,
|
|
|
|
// 免得只看到「翻译失败,请稍后再试」而一直等它自己好。
|
|
|
|
if out.Code == "10009" || strings.Contains(out.Message, "is not activated") { |
|
|
|
return "", "", fmt.Errorf("translate failed: code=%s msg=%s(阿里云机器翻译 alimt 未开通:去阿里云控制台开通,或把后台 MT 服务换成别家)", out.Code, out.Message) |
|
|
|
} |
|
|
|
return "", "", fmt.Errorf("translate failed: code=%s msg=%s", out.Code, out.Message) |
|
|
|
} |
|
|
|
return out.Data.Translated, out.Data.DetectedLanguage, nil |
|
|
|
|