Compare commits

..

No commits in common. "de9888ca5f760b165343bf8030bdb9b904a4ed4d" and "2d8b84e2c8031a0886edefefa96365231be8a4c1" have entirely different histories.

6 changed files with 116 additions and 159 deletions

View File

@ -15,7 +15,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.23.5' go-version: '1.23.4'
- name: Install golint - name: Install golint
run: go install golang.org/x/lint/golint@latest run: go install golang.org/x/lint/golint@latest

View File

@ -15,7 +15,7 @@ jobs:
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
with: with:
go-version: "1.23.5" go-version: "1.23.4"
- run: bash .cross_compile.sh - run: bash .cross_compile.sh

View File

@ -1,4 +1,4 @@
FROM golang:1.23.5 AS builder FROM golang:1.23.4 AS builder
WORKDIR /go/src/github.com/OwO-Network/DeepLX WORKDIR /go/src/github.com/OwO-Network/DeepLX
COPY . . COPY . .
RUN go get -d -v ./ RUN go get -d -v ./

4
go.mod
View File

@ -1,6 +1,6 @@
module github.com/OwO-Network/DeepLX module github.com/OwO-Network/DeepLX
go 1.23.5 go 1.23.4
require ( require (
github.com/abadojack/whatlanggo v1.0.1 github.com/abadojack/whatlanggo v1.0.1
@ -48,7 +48,7 @@ require (
golang.org/x/crypto v0.31.0 // indirect golang.org/x/crypto v0.31.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/mod v0.21.0 // indirect golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.33.0 // indirect golang.org/x/net v0.29.0 // indirect
golang.org/x/sync v0.10.0 // indirect golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.21.0 // indirect

4
go.sum
View File

@ -122,8 +122,8 @@ golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWB
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -2,7 +2,7 @@
* @Author: Vincent Young * @Author: Vincent Young
* @Date: 2024-09-16 11:59:24 * @Date: 2024-09-16 11:59:24
* @LastEditors: Vincent Yang * @LastEditors: Vincent Yang
* @LastEditTime: 2025-01-20 17:09:59 * @LastEditTime: 2024-12-03 11:23:23
* @FilePath: /DeepLX/translate/translate.go * @FilePath: /DeepLX/translate/translate.go
* @Telegram: https://t.me/missuo * @Telegram: https://t.me/missuo
* @GitHub: https://github.com/missuo * @GitHub: https://github.com/missuo
@ -126,79 +126,87 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
}, nil }, nil
} }
// Split text by newlines and store them for later reconstruction // Split text first
textParts := strings.Split(text, "\n") splitResult, err := splitText(text, tagHandling == "html" || tagHandling == "xml", proxyURL, dlSession)
var translatedParts []string if err != nil {
var allAlternatives [][]string // Store alternatives for each part return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable,
Message: err.Error(),
}, nil
}
for _, part := range textParts { // Get detected language if source language is auto
if strings.TrimSpace(part) == "" { if sourceLang == "auto" || sourceLang == "" {
translatedParts = append(translatedParts, "") sourceLang = strings.ToUpper(whatlanggo.DetectLang(text).Iso6391())
allAlternatives = append(allAlternatives, []string{""}) }
continue
// Prepare jobs from split result
var jobs []Job
chunks := splitResult.Get("result.texts.0.chunks").Array()
for idx, chunk := range chunks {
sentence := chunk.Get("sentences.0")
// Handle context
contextBefore := []string{}
contextAfter := []string{}
if idx > 0 {
contextBefore = []string{chunks[idx-1].Get("sentences.0.text").String()}
}
if idx < len(chunks)-1 {
contextAfter = []string{chunks[idx+1].Get("sentences.0.text").String()}
} }
// Split text first jobs = append(jobs, Job{
splitResult, err := splitText(part, tagHandling == "html" || tagHandling == "xml", proxyURL, dlSession) Kind: "default",
if err != nil { PreferredNumBeams: 4,
return DeepLXTranslationResult{ RawEnContextBefore: contextBefore,
Code: http.StatusServiceUnavailable, RawEnContextAfter: contextAfter,
Message: err.Error(), Sentences: []Sentence{{
}, nil Prefix: sentence.Get("prefix").String(),
} Text: sentence.Get("text").String(),
ID: idx + 1,
}},
})
}
// Get detected language if source language is auto hasRegionalVariant := false
if sourceLang == "auto" || sourceLang == "" { targetLangCode := targetLang
sourceLang = strings.ToUpper(whatlanggo.DetectLang(part).Iso6391()) targetLangParts := strings.Split(targetLang, "-")
} if len(targetLangParts) > 1 {
targetLangCode = targetLangParts[0]
hasRegionalVariant = true
}
// Prepare jobs from split result // Prepare translation request
var jobs []Job id := getRandomNumber()
chunks := splitResult.Get("result.texts.0.chunks").Array()
for idx, chunk := range chunks {
sentence := chunk.Get("sentences.0")
// Handle context postData := &PostData{
contextBefore := []string{} Jsonrpc: "2.0",
contextAfter := []string{} Method: "LMT_handle_jobs",
if idx > 0 { ID: id,
contextBefore = []string{chunks[idx-1].Get("sentences.0.text").String()} Params: Params{
} CommonJobParams: CommonJobParams{
if idx < len(chunks)-1 { Mode: "translate",
contextAfter = []string{chunks[idx+1].Get("sentences.0.text").String()} },
} Lang: Lang{
SourceLangComputed: strings.ToUpper(sourceLang),
TargetLang: strings.ToUpper(targetLangCode),
},
Jobs: jobs,
Priority: 1,
Timestamp: getTimeStamp(getICount(text)),
},
}
jobs = append(jobs, Job{ if hasRegionalVariant {
Kind: "default", postData = &PostData{
PreferredNumBeams: 4,
RawEnContextBefore: contextBefore,
RawEnContextAfter: contextAfter,
Sentences: []Sentence{{
Prefix: sentence.Get("prefix").String(),
Text: sentence.Get("text").String(),
ID: idx + 1,
}},
})
}
hasRegionalVariant := false
targetLangCode := targetLang
targetLangParts := strings.Split(targetLang, "-")
if len(targetLangParts) > 1 {
targetLangCode = targetLangParts[0]
hasRegionalVariant = true
}
// Prepare translation request
id := getRandomNumber()
postData := &PostData{
Jsonrpc: "2.0", Jsonrpc: "2.0",
Method: "LMT_handle_jobs", Method: "LMT_handle_jobs",
ID: id, ID: id,
Params: Params{ Params: Params{
CommonJobParams: CommonJobParams{ CommonJobParams: CommonJobParams{
Mode: "translate", Mode: "translate",
RegionalVariant: map[bool]string{true: targetLang, false: ""}[hasRegionalVariant],
}, },
Lang: Lang{ Lang: Lang{
SourceLangComputed: strings.ToUpper(sourceLang), SourceLangComputed: strings.ToUpper(sourceLang),
@ -206,111 +214,60 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
}, },
Jobs: jobs, Jobs: jobs,
Priority: 1, Priority: 1,
Timestamp: getTimeStamp(getICount(part)), Timestamp: getTimeStamp(getICount(text)),
}, },
} }
}
if hasRegionalVariant { // Make translation request
postData = &PostData{ result, err := makeRequest(postData, "LMT_handle_jobs", proxyURL, dlSession)
Jsonrpc: "2.0", if err != nil {
Method: "LMT_handle_jobs", return DeepLXTranslationResult{
ID: id, Code: http.StatusServiceUnavailable,
Params: Params{ Message: err.Error(),
CommonJobParams: CommonJobParams{ }, nil
Mode: "translate", }
RegionalVariant: map[bool]string{true: targetLang, false: ""}[hasRegionalVariant],
},
Lang: Lang{
SourceLangComputed: strings.ToUpper(sourceLang),
TargetLang: strings.ToUpper(targetLangCode),
},
Jobs: jobs,
Priority: 1,
Timestamp: getTimeStamp(getICount(part)),
},
}
}
// Make translation request // Process translation results
result, err := makeRequest(postData, "LMT_handle_jobs", proxyURL, dlSession) var alternatives []string
if err != nil { var translatedText string
return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable,
Message: err.Error(),
}, nil
}
// Process translation results translations := result.Get("result.translations").Array()
var partTranslation string if len(translations) > 0 {
var partAlternatives []string // Get alternatives
numBeams := len(translations[0].Get("beams").Array())
translations := result.Get("result.translations").Array() for i := 0; i < numBeams; i++ {
if len(translations) > 0 { var altText string
// Process main translation
for _, translation := range translations { for _, translation := range translations {
partTranslation += translation.Get("beams.0.sentences.0.text").String() + " " beams := translation.Get("beams").Array()
} if i < len(beams) {
partTranslation = strings.TrimSpace(partTranslation) altText += beams[i].Get("sentences.0.text").String()
// Process alternatives
numBeams := len(translations[0].Get("beams").Array())
for i := 1; i < numBeams; i++ { // Start from 1 since 0 is the main translation
var altText string
for _, translation := range translations {
beams := translation.Get("beams").Array()
if i < len(beams) {
altText += beams[i].Get("sentences.0.text").String() + " "
}
}
if altText != "" {
partAlternatives = append(partAlternatives, strings.TrimSpace(altText))
} }
} }
} if altText != "" {
alternatives = append(alternatives, altText)
if partTranslation == "" {
return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable,
Message: "Translation failed",
}, nil
}
translatedParts = append(translatedParts, partTranslation)
allAlternatives = append(allAlternatives, partAlternatives)
}
// Join all translated parts with newlines
translatedText := strings.Join(translatedParts, "\n")
// Combine alternatives with proper newline handling
var combinedAlternatives []string
maxAlts := 0
for _, alts := range allAlternatives {
if len(alts) > maxAlts {
maxAlts = len(alts)
}
}
// Create combined alternatives preserving line structure
for i := 0; i < maxAlts; i++ {
var altParts []string
for j, alts := range allAlternatives {
if i < len(alts) {
altParts = append(altParts, alts[i])
} else if len(translatedParts[j]) == 0 {
altParts = append(altParts, "") // Keep empty lines
} else {
altParts = append(altParts, translatedParts[j]) // Use main translation if no alternative
} }
} }
combinedAlternatives = append(combinedAlternatives, strings.Join(altParts, "\n"))
// Get main translation
for _, translation := range translations {
translatedText += translation.Get("beams.0.sentences.0.text").String() + " "
}
translatedText = strings.TrimSpace(translatedText)
}
if translatedText == "" {
return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable,
Message: "Translation failed",
}, nil
} }
return DeepLXTranslationResult{ return DeepLXTranslationResult{
Code: http.StatusOK, Code: http.StatusOK,
ID: getRandomNumber(), // Using new ID for the complete translation ID: id,
Data: translatedText, Data: translatedText,
Alternatives: combinedAlternatives, Alternatives: alternatives,
SourceLang: sourceLang, SourceLang: sourceLang,
TargetLang: targetLang, TargetLang: targetLang,
Method: map[bool]string{true: "Pro", false: "Free"}[dlSession != ""], Method: map[bool]string{true: "Pro", false: "Free"}[dlSession != ""],