2
2
* @Author: Vincent Young
3
3
* @Date: 2024-09-16 11:59:24
4
4
* @LastEditors: Vincent Yang
5
- * @LastEditTime: 2025-01-20 17:09:59
5
+ * @LastEditTime: 2025-03-01 04:23:49
6
6
* @FilePath: /DeepLX/translate/translate.go
7
7
* @Telegram: https://t.me/missuo
8
8
* @GitHub: https://github.com/missuo
@@ -14,6 +14,8 @@ package translate
14
14
15
15
import (
16
16
"bytes"
17
+ "compress/flate"
18
+ "compress/gzip"
17
19
"fmt"
18
20
"io"
19
21
"net/http"
@@ -27,35 +29,28 @@ import (
27
29
"github.com/tidwall/gjson"
28
30
)
29
31
30
- const baseURL = "https://www2.deepl.com/jsonrpc"
31
-
32
32
// makeRequest makes an HTTP request to DeepL API
33
-
34
- func makeRequest (postData * PostData , urlMethod string , proxyURL string , dlSession string ) (gjson.Result , error ) {
35
- urlFull := fmt .Sprintf ("%s?client=chrome-extension,1.28.0&method=%s" , baseURL , urlMethod )
36
-
33
+ func makeRequest (postData * PostData , proxyURL string , dlSession string ) (gjson.Result , error ) {
34
+ urlFull := "https://www2.deepl.com/jsonrpc"
37
35
postStr := formatPostString (postData )
38
36
39
37
// Create a new req client
40
38
client := req .C ().SetTLSFingerprintRandomized ()
41
39
42
40
// Set headers
43
41
headers := http.Header {
44
- "Accept" : []string {"*/*" },
45
- "Accept-Language" : []string {"en-US,en;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh-HK;q=0.6,zh;q=0.5" },
46
- "Authorization" : []string {"None" },
47
- "Cache-Control" : []string {"no-cache" },
48
- "Content-Type" : []string {"application/json" },
49
- "DNT" : []string {"1" },
50
- "Origin" : []string {"chrome-extension://cofdbpoegempjloogbagkncekinflcnj" },
51
- "Pragma" : []string {"no-cache" },
52
- "Priority" : []string {"u=1, i" },
53
- "Referer" : []string {"https://www.deepl.com/" },
54
- "Sec-Fetch-Dest" : []string {"empty" },
55
- "Sec-Fetch-Mode" : []string {"cors" },
56
- "Sec-Fetch-Site" : []string {"none" },
57
- "Sec-GPC" : []string {"1" },
58
- "User-Agent" : []string {"DeepLBrowserExtension/1.28.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" },
42
+ "Content-Type" : []string {"application/json" },
43
+ "User-Agent" : []string {"DeepL/1627620 CFNetwork/3826.500.62.2.1 Darwin/24.4.0" },
44
+ "Accept" : []string {"*/*" },
45
+ "X-App-Os-Name" : []string {"iOS" },
46
+ "X-App-Os-Version" : []string {"18.4.0" },
47
+ "Accept-Language" : []string {"en-US,en;q=0.9" },
48
+ "Accept-Encoding" : []string {"gzip, deflate, br" }, // Keep this!
49
+ "X-App-Device" : []string {"iPhone16,2" },
50
+ "Referer" : []string {"https://www.deepl.com/" },
51
+ "X-Product" : []string {"translator" },
52
+ "X-App-Build" : []string {"1627620" },
53
+ "X-App-Version" : []string {"25.1" },
59
54
}
60
55
61
56
if dlSession != "" {
@@ -83,40 +78,28 @@ func makeRequest(postData *PostData, urlMethod string, proxyURL string, dlSessio
83
78
}
84
79
85
80
var bodyReader io.Reader
86
- if resp .Header .Get ("Content-Encoding" ) == "br" {
81
+ contentEncoding := resp .Header .Get ("Content-Encoding" )
82
+ switch contentEncoding {
83
+ case "br" :
87
84
bodyReader = brotli .NewReader (resp .Body )
88
- } else {
85
+ case "gzip" :
86
+ bodyReader , err = gzip .NewReader (resp .Body ) // Use gzip.NewReader
87
+ if err != nil {
88
+ return gjson.Result {}, fmt .Errorf ("failed to create gzip reader: %w" , err )
89
+ }
90
+ case "deflate" : // Less common, but good to handle
91
+ bodyReader = flate .NewReader (resp .Body )
92
+ default :
89
93
bodyReader = resp .Body
90
94
}
91
95
92
96
body , err := io .ReadAll (bodyReader )
93
97
if err != nil {
94
- return gjson.Result {}, err
98
+ return gjson.Result {}, fmt . Errorf ( "failed to read response body: %w" , err )
95
99
}
96
100
return gjson .ParseBytes (body ), nil
97
101
}
98
102
99
- // splitText splits the input text for translation
100
- func splitText (text string , tagHandling bool , proxyURL string , dlSession string ) (gjson.Result , error ) {
101
- postData := & PostData {
102
- Jsonrpc : "2.0" ,
103
- Method : "LMT_split_text" ,
104
- ID : getRandomNumber (),
105
- Params : Params {
106
- CommonJobParams : CommonJobParams {
107
- Mode : "translate" ,
108
- },
109
- Lang : Lang {
110
- LangUserSelected : "auto" ,
111
- },
112
- Texts : []string {text },
113
- TextType : map [bool ]string {true : "richtext" , false : "plaintext" }[tagHandling || isRichText (text )],
114
- },
115
- }
116
-
117
- return makeRequest (postData , "LMT_split_text" , proxyURL , dlSession )
118
- }
119
-
120
103
// TranslateByDeepLX performs translation using DeepL API
121
104
func TranslateByDeepLX (sourceLang , targetLang , text string , tagHandling string , proxyURL string , dlSession string ) (DeepLXTranslationResult , error ) {
122
105
if text == "" {
@@ -126,6 +109,10 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
126
109
}, nil
127
110
}
128
111
112
+ if tagHandling == "" {
113
+ tagHandling = "plaintext"
114
+ }
115
+
129
116
// Split text by newlines and store them for later reconstruction
130
117
textParts := strings .Split (text , "\n " )
131
118
var translatedParts []string
@@ -138,48 +125,25 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
138
125
continue
139
126
}
140
127
141
- // Split text first
142
- splitResult , err := splitText (part , tagHandling == "html" || tagHandling == "xml" , proxyURL , dlSession )
143
- if err != nil {
144
- return DeepLXTranslationResult {
145
- Code : http .StatusServiceUnavailable ,
146
- Message : err .Error (),
147
- }, nil
148
- }
149
-
150
128
// Get detected language if source language is auto
151
129
if sourceLang == "auto" || sourceLang == "" {
152
130
sourceLang = strings .ToUpper (whatlanggo .DetectLang (part ).Iso6391 ())
153
131
}
154
132
155
133
// Prepare jobs from split result
156
134
var jobs []Job
157
- chunks := splitResult .Get ("result.texts.0.chunks" ).Array ()
158
- for idx , chunk := range chunks {
159
- sentence := chunk .Get ("sentences.0" )
160
-
161
- // Handle context
162
- contextBefore := []string {}
163
- contextAfter := []string {}
164
- if idx > 0 {
165
- contextBefore = []string {chunks [idx - 1 ].Get ("sentences.0.text" ).String ()}
166
- }
167
- if idx < len (chunks )- 1 {
168
- contextAfter = []string {chunks [idx + 1 ].Get ("sentences.0.text" ).String ()}
169
- }
170
135
171
- jobs = append (jobs , Job {
172
- Kind : "default" ,
173
- PreferredNumBeams : 4 ,
174
- RawEnContextBefore : contextBefore ,
175
- RawEnContextAfter : contextAfter ,
176
- Sentences : []Sentence {{
177
- Prefix : sentence .Get ("prefix" ).String (),
178
- Text : sentence .Get ("text" ).String (),
179
- ID : idx + 1 ,
180
- }},
181
- })
182
- }
136
+ jobs = append (jobs , Job {
137
+ Kind : "default" ,
138
+ PreferredNumBeams : 4 ,
139
+ RawEnContextBefore : []string {},
140
+ RawEnContextAfter : []string {},
141
+ Sentences : []Sentence {{
142
+ Prefix : "" ,
143
+ Text : text ,
144
+ ID : 0 ,
145
+ }},
146
+ })
183
147
184
148
hasRegionalVariant := false
185
149
targetLangCode := targetLang
@@ -198,14 +162,19 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
198
162
ID : id ,
199
163
Params : Params {
200
164
CommonJobParams : CommonJobParams {
201
- Mode : "translate" ,
165
+ Mode : "translate" ,
166
+ Formality : "undefined" ,
167
+ TranscribeAs : "romanize" ,
168
+ AdvancedMode : false ,
169
+ TextType : tagHandling ,
170
+ WasSpoken : false ,
202
171
},
203
172
Lang : Lang {
204
- SourceLangComputed : strings .ToUpper (sourceLang ),
205
- TargetLang : strings .ToUpper (targetLangCode ),
173
+ SourceLangUserSelected : "auto" ,
174
+ TargetLang : strings .ToUpper (targetLangCode ),
175
+ SourceLangComputed : strings .ToUpper (sourceLang ),
206
176
},
207
177
Jobs : jobs ,
208
- Priority : 1 ,
209
178
Timestamp : getTimeStamp (getICount (part )),
210
179
},
211
180
}
@@ -218,21 +187,26 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
218
187
Params : Params {
219
188
CommonJobParams : CommonJobParams {
220
189
Mode : "translate" ,
221
- RegionalVariant : map [bool ]string {true : targetLang , false : "" }[hasRegionalVariant ],
190
+ Formality : "undefined" ,
191
+ TranscribeAs : "romanize" ,
192
+ AdvancedMode : false ,
193
+ TextType : tagHandling ,
194
+ WasSpoken : false ,
195
+ RegionalVariant : targetLang ,
222
196
},
223
197
Lang : Lang {
224
- SourceLangComputed : strings .ToUpper (sourceLang ),
225
- TargetLang : strings .ToUpper (targetLangCode ),
198
+ SourceLangUserSelected : "auto" ,
199
+ TargetLang : strings .ToUpper (targetLangCode ),
200
+ SourceLangComputed : strings .ToUpper (sourceLang ),
226
201
},
227
202
Jobs : jobs ,
228
- Priority : 1 ,
229
203
Timestamp : getTimeStamp (getICount (part )),
230
204
},
231
205
}
232
206
}
233
207
234
208
// Make translation request
235
- result , err := makeRequest (postData , "LMT_handle_jobs" , proxyURL , dlSession )
209
+ result , err := makeRequest (postData , proxyURL , dlSession )
236
210
if err != nil {
237
211
return DeepLXTranslationResult {
238
212
Code : http .StatusServiceUnavailable ,
0 commit comments