1+ //https://github.com/sangyuxiaowu/Sang.Baidu.TranslateAPI/blob/main/Sang.Baidu.TranslateAPI/BaiduTranslator.cs
2+
3+ using System . Net . Http . Json ;
4+ using System . Text . Json ;
5+ using System . Text . Json . Serialization ;
6+ using System . Text ;
7+ using System . Security . Cryptography ;
8+
9+ namespace Pixeval . Extensions . Translators . Baidu . Client ;
10+ #nullable disable
11+ /// <summary>
12+ /// 文档:https://fanyi-api.baidu.com/doc/21
13+ /// </summary>
14+ public class BaiduTranslatorClient
15+ {
16+ /// <summary>
17+ /// APPID
18+ /// </summary>
19+ private string _appId ;
20+
21+ /// <summary>
22+ /// 密钥
23+ /// </summary>
24+ private string _secretKey ;
25+
26+ /// <summary>
27+ /// 翻译服务终结点
28+ /// </summary>
29+ private readonly string _endpoint ;
30+
31+ /// <summary>
32+ /// HttpClient
33+ /// </summary>
34+ private readonly HttpClient _httpClient ;
35+
36+
37+ /// <summary>
38+ /// 构造函数
39+ /// </summary>
40+ /// <param name="appId">APPID</param>
41+ /// <param name="secretKey">密钥</param>
42+ /// <param name="endpoint">翻译服务终结点</param>
43+ public BaiduTranslatorClient ( string appId , string secretKey , string endpoint = "https://fanyi-api.baidu.com/api/trans/vip/translate" )
44+ {
45+ _appId = appId ;
46+ _secretKey = secretKey ;
47+ _endpoint = endpoint ;
48+ _httpClient = new HttpClient { Timeout = TimeSpan . FromSeconds ( 10 ) } ; // 设置超时时间
49+ }
50+
51+ /// <summary>
52+ /// 构造函数
53+ /// </summary>
54+ /// <param name="appId">APPID</param>
55+ /// <param name="secretKey">密钥</param>
56+ /// <param name="httpClient">HttpClient</param>
57+ /// <param name="endpoint">翻译服务终结点</param>
58+ public BaiduTranslatorClient ( string appId , string secretKey , HttpClient httpClient , string endpoint = "https://fanyi-api.baidu.com/api/trans/vip/translate" )
59+ {
60+ _appId = appId ;
61+ _secretKey = secretKey ;
62+ _endpoint = endpoint ;
63+ _httpClient = httpClient ;
64+ }
65+
66+ /// <summary>
67+ /// 重新设置appId 和 secretKey
68+ /// </summary>
69+ /// <param name="appId">APPID</param>
70+ /// <param name="secretKey">密钥</param>
71+ public void SetAppIdAndSecretKey ( string appId , string secretKey )
72+ {
73+ _appId = appId ;
74+ _secretKey = secretKey ;
75+ }
76+
77+ /// <summary>
78+ /// 翻译
79+ /// </summary>
80+ /// <param name="text">请求翻译文本,长度控制在 6000 bytes以内(汉字约为输入参数 2000 个)</param>
81+ /// <param name="toLanguage">翻译目标语言</param>
82+ /// <returns></returns>
83+ public async Task < BaiduTranslateResult > Translate ( string text , string toLanguage )
84+ {
85+ return await Translate ( text , toLanguage , "auto" ) ;
86+ }
87+
88+ /// <summary>
89+ /// 翻译
90+ /// </summary>
91+ /// <param name="text">请求翻译文本,长度控制在 6000 bytes以内(汉字约为输入参数 2000 个)</param>
92+ /// <param name="toLanguage">翻译目标语言</param>
93+ /// <param name="fromLanguage">翻译源语言,可为auto,自动检测</param>
94+ /// <param name="salt">设置后将使用传入的随机数</param>
95+ /// <param name="sign">设置后将使用传入的签名结果</param>
96+ /// <returns></returns>
97+ public async Task < BaiduTranslateResult > Translate ( string text , string toLanguage , string fromLanguage = "auto" , string salt = "" , string sign = "" )
98+ {
99+ // 使用时间戳
100+ if ( string . IsNullOrWhiteSpace ( salt ) )
101+ {
102+ salt = DateTimeOffset . Now . ToUnixTimeSeconds ( ) . ToString ( ) ;
103+ }
104+ // 使用MD5加密
105+ if ( string . IsNullOrWhiteSpace ( sign ) )
106+ {
107+ sign = ( _appId + text + salt + _secretKey ) . MD5 ( ) ;
108+ }
109+ // 拼接URL
110+ string url = $ "{ _endpoint } ?q={ text } &from={ fromLanguage } &to={ toLanguage } &appid={ _appId } &salt={ salt } &sign={ sign } ";
111+ // 发送请求
112+ try
113+ {
114+ #if NET6_0_OR_GREATER
115+ //return await _httpClient.GetFromJsonAsync<BaiduTranslateResult>(url);
116+ var response = await _httpClient . GetAsync ( url ) ;
117+ var options = new JsonSerializerOptions
118+ {
119+ TypeInfoResolver = SourceGenerationContext . Default ,
120+ } ;
121+ if ( response . IsSuccessStatusCode )
122+ {
123+ var str = await response . Content . ReadAsStringAsync ( ) ;
124+ var result = JsonSerializer . Deserialize < BaiduTranslateResult > (
125+ str , SourceGenerationContext . Default . BaiduTranslateResult ) ;
126+ return result ;
127+ }
128+ return new BaiduTranslateResult { Error_Code = response . StatusCode . ToString ( ) , Error_Msg = response . ReasonPhrase } ;
129+ #else
130+ var response = await _httpClient . GetAsync ( url ) ;
131+ if ( response . IsSuccessStatusCode )
132+ {
133+ var result = await response . Content . ReadAsStringAsync ( ) ;
134+ var json = JsonDocument . Parse ( result ) ;
135+ var root = json . RootElement ;
136+
137+ // 是否存在错误码
138+ if ( root . TryGetProperty ( "error_code" , out var errorCode ) )
139+ {
140+ return new BaiduTranslateResult { Error_Code = errorCode . GetString ( ) , Error_Msg = root . GetProperty ( "error_msg" ) . GetString ( ) } ;
141+ }
142+
143+ var from = root . GetProperty ( "from" ) . GetString ( ) ;
144+ var to = root . GetProperty ( "to" ) . GetString ( ) ;
145+
146+ var transResult = new List < TransResult > ( ) ;
147+ for ( int i = 0 ; i < root . GetProperty ( "trans_result" ) . GetArrayLength ( ) ; i ++ )
148+ {
149+ var item = root . GetProperty ( "trans_result" ) [ i ] ;
150+ transResult . Add ( new TransResult
151+ {
152+ Src = item . GetProperty ( "src" ) . GetString ( ) ,
153+ Dst = item . GetProperty ( "dst" ) . GetString ( )
154+ } ) ;
155+ }
156+
157+ return new BaiduTranslateResult
158+ {
159+ From = from ,
160+ To = to ,
161+ Trans_Result = transResult
162+ } ;
163+ }
164+ return new BaiduTranslateResult { Error_Code = response . StatusCode . ToString ( ) , Error_Msg = response . ReasonPhrase } ;
165+ #endif
166+ }
167+ catch ( Exception ex )
168+ {
169+ return new BaiduTranslateResult { Error_Code = "Exception" , Error_Msg = ex . Message } ;
170+ }
171+ }
172+
173+ /// <summary>
174+ /// 释放资源
175+ /// </summary>
176+ public void Dispose ( )
177+ {
178+ _httpClient ? . Dispose ( ) ;
179+ }
180+
181+ }
182+ [ JsonSerializable ( typeof ( BaiduTranslateResult ) ) ]
183+ [ JsonSerializable ( typeof ( List < TransResult > ) ) ]
184+ [ JsonSerializable ( typeof ( TransResult ) ) ]
185+ [ JsonSerializable ( typeof ( bool ) ) ]
186+ [ JsonSerializable ( typeof ( string ) ) ]
187+ internal partial class SourceGenerationContext : JsonSerializerContext
188+ {
189+ }
190+
191+ public class BaiduTranslateResult
192+ {
193+ /// <summary>
194+ /// 是否成功
195+ /// </summary>
196+ public bool Success => Error_Code == null ;
197+ /// <summary>
198+ /// 翻译源语言
199+ /// </summary>
200+ [ JsonPropertyName ( "from" ) ]
201+ public string From { get ; set ; }
202+ /// <summary>
203+ /// 翻译目标语言
204+ /// </summary>
205+ [ JsonPropertyName ( "to" ) ]
206+ public string To { get ; set ; }
207+ /// <summary>
208+ /// 翻译结果
209+ /// </summary>
210+ [ JsonPropertyName ( "trans_result" ) ]
211+ public List < TransResult > Trans_Result { get ; set ; }
212+ /// <summary>
213+ /// 错误码
214+ /// </summary>
215+ [ JsonPropertyName ( "error_code" ) ]
216+ public string Error_Code { get ; set ; }
217+ /// <summary>
218+ /// 错误信息
219+ /// </summary>
220+
221+ [ JsonPropertyName ( "error_msg" ) ]
222+ public string Error_Msg { get ; set ; }
223+
224+ /// <summary>
225+ /// 获取翻译结果
226+ /// </summary>
227+ /// <returns></returns>
228+ public string GetResult ( )
229+ {
230+ return Trans_Result != null && Trans_Result . Count > 0 ? Trans_Result [ 0 ] . Dst : null ;
231+ }
232+
233+ }
234+
235+ /// <summary>
236+ /// 翻译结果
237+ /// </summary>
238+ public class TransResult
239+ {
240+ /// <summary>
241+ /// 原文
242+ /// </summary>
243+ [ JsonPropertyName ( "src" ) ]
244+ public string Src { get ; set ; }
245+ /// <summary>
246+ /// 译文
247+ /// </summary>
248+ [ JsonPropertyName ( "dst" ) ]
249+ public string Dst { get ; set ; }
250+ }
251+ public static class Cryptography
252+ {
253+
254+ /// <summary>
255+ /// MD5 计算
256+ /// </summary>
257+ /// <param name="str">待计算字符</param>
258+ /// <param name="isUpper">是否是大写</param>
259+ /// <param name="isBig">是否是32位,否则为16位</param>
260+ /// <returns>计算结果</returns>
261+ public static string MD5 ( this string str , bool isUpper = false , bool isBig = true )
262+ {
263+ using ( var md5 = System . Security . Cryptography . MD5 . Create ( ) )
264+ {
265+ var result = md5 . ComputeHash ( Encoding . UTF8 . GetBytes ( str ) ) ;
266+ var strResult = isBig ? BitConverter . ToString ( result ) : BitConverter . ToString ( result , 4 , 8 ) ;
267+ return isUpper ? strResult . Replace ( "-" , "" ) : strResult . Replace ( "-" , "" ) . ToLower ( ) ;
268+ }
269+ }
270+
271+ /// <summary>
272+ /// SHA1 计算
273+ /// </summary>
274+ /// <param name="str">待计算字符</param>
275+ /// <param name="isUpper">是否是大写</param>
276+ /// <returns>计算结果</returns>
277+ public static string SHA1 ( this string str , bool isUpper = false )
278+ {
279+ using ( var sha1 = System . Security . Cryptography . SHA1 . Create ( ) )
280+ {
281+ var result = sha1 . ComputeHash ( Encoding . UTF8 . GetBytes ( str ) ) ;
282+ var strResult = BitConverter . ToString ( result ) ;
283+ return isUpper ? strResult . Replace ( "-" , "" ) : strResult . Replace ( "-" , "" ) . ToLower ( ) ;
284+ }
285+ }
286+
287+ }
0 commit comments