mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 08:14:55 +08:00
feat(api): proxy Translation Memory over bat.sock
This commit is contained in:
@@ -54,6 +54,8 @@ func (s *Server) handleAdminIndex(w http.ResponseWriter, r *http.Request) {
|
||||
"/admin/parse/errors",
|
||||
"/admin/translation/tasks",
|
||||
"/admin/translation/handoff",
|
||||
"/admin/translation/memory/summary",
|
||||
"/admin/translation/memory/query",
|
||||
"/admin/translation/status",
|
||||
},
|
||||
Controls: []string{
|
||||
@@ -72,6 +74,7 @@ func (s *Server) handleAdminIndex(w http.ResponseWriter, r *http.Request) {
|
||||
"/admin/control/translation-task-update",
|
||||
"/admin/control/translation-worker-run",
|
||||
"/admin/control/translation-proofread",
|
||||
"/admin/control/translation-memory-confirm",
|
||||
"/admin/control/localized-publish",
|
||||
"/admin/control/localized-rollback",
|
||||
},
|
||||
@@ -117,6 +120,10 @@ func (s *Server) handleAdminControl(w http.ResponseWriter, r *http.Request) {
|
||||
s.handleAdminTranslationProofread(w, r)
|
||||
return
|
||||
}
|
||||
if action == "translation-memory-confirm" {
|
||||
s.handleAdminTranslationMemoryConfirm(w, r)
|
||||
return
|
||||
}
|
||||
if action == "localized-publish" {
|
||||
s.handleAdminLocalizedPublish(w, r)
|
||||
return
|
||||
@@ -274,6 +281,34 @@ func (s *Server) handleAdminTranslationProofread(w http.ResponseWriter, r *http.
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminTranslationMemoryConfirm(w http.ResponseWriter, r *http.Request) {
|
||||
backend, ok := s.backend.(TranslationMemoryBackend)
|
||||
if !ok || backend == nil {
|
||||
writeErrorJSON(w, http.StatusServiceUnavailable, "translation_memory_backend_unavailable", "Rust bat Translation Memory backend is unavailable")
|
||||
return
|
||||
}
|
||||
var params backendrpc.TranslationMemoryConfirmParams
|
||||
if !decodeAdminTranslationJSON(w, r, ¶ms) {
|
||||
return
|
||||
}
|
||||
if err := validateTranslationMemoryConfirmParams(params); err != nil {
|
||||
writeErrorJSON(w, http.StatusBadRequest, "invalid_translation_memory_params", err.Error())
|
||||
return
|
||||
}
|
||||
result, err := backend.TranslationMemoryConfirm(r.Context(), params)
|
||||
if err != nil {
|
||||
s.writeControlBackendError(w, "translation-memory-confirm", err)
|
||||
return
|
||||
}
|
||||
writeNoStoreJSON(w, http.StatusAccepted, AdminControlResponse{
|
||||
Service: "bat-api",
|
||||
Action: "translation-memory-confirm",
|
||||
RPCMethod: "translation.memory.confirm",
|
||||
Status: "accepted",
|
||||
Result: result,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminLocalizedPublish(w http.ResponseWriter, r *http.Request) {
|
||||
backend, ok := s.backend.(LocalizedBackend)
|
||||
if !ok || backend == nil {
|
||||
@@ -656,6 +691,66 @@ func (s *Server) handleAdminTranslationHandoff(w http.ResponseWriter, r *http.Re
|
||||
writeNoStoreJSON(w, http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminTranslationMemorySummary(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||
writeErrorJSON(w, http.StatusMethodNotAllowed, "method_not_allowed", "method not allowed")
|
||||
return
|
||||
}
|
||||
if !s.requireAdminToken(w, r) {
|
||||
return
|
||||
}
|
||||
backend, ok := s.backend.(TranslationMemoryBackend)
|
||||
if !ok || backend == nil {
|
||||
writeErrorJSON(w, http.StatusServiceUnavailable, "translation_memory_backend_unavailable", "Rust bat Translation Memory backend is unavailable")
|
||||
return
|
||||
}
|
||||
params := backendrpc.TranslationMemorySummaryParams{
|
||||
TranslationMemoryPath: firstTrimmedQuery(r.URL.Query(), "translation_memory_path", "tm_path"),
|
||||
}
|
||||
result, err := backend.TranslationMemorySummary(r.Context(), params)
|
||||
if err != nil {
|
||||
s.writeControlBackendError(w, "translation-memory-summary", err)
|
||||
return
|
||||
}
|
||||
if r.Method == http.MethodHead {
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
writeNoStoreJSON(w, http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminTranslationMemoryQuery(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||
writeErrorJSON(w, http.StatusMethodNotAllowed, "method_not_allowed", "method not allowed")
|
||||
return
|
||||
}
|
||||
if !s.requireAdminToken(w, r) {
|
||||
return
|
||||
}
|
||||
backend, ok := s.backend.(TranslationMemoryBackend)
|
||||
if !ok || backend == nil {
|
||||
writeErrorJSON(w, http.StatusServiceUnavailable, "translation_memory_backend_unavailable", "Rust bat Translation Memory backend is unavailable")
|
||||
return
|
||||
}
|
||||
params, err := translationMemoryQueryParams(r)
|
||||
if err != nil {
|
||||
writeErrorJSON(w, http.StatusBadRequest, "invalid_translation_memory_query", err.Error())
|
||||
return
|
||||
}
|
||||
result, err := backend.TranslationMemoryQuery(r.Context(), params)
|
||||
if err != nil {
|
||||
s.writeControlBackendError(w, "translation-memory-query", err)
|
||||
return
|
||||
}
|
||||
if r.Method == http.MethodHead {
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
writeNoStoreJSON(w, http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminSchedules(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||
writeErrorJSON(w, http.StatusMethodNotAllowed, "method_not_allowed", "method not allowed")
|
||||
@@ -747,6 +842,38 @@ func translationTaskListParams(r *http.Request) (backendrpc.TranslationTaskListP
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func translationMemoryQueryParams(r *http.Request) (backendrpc.TranslationMemoryQueryParams, error) {
|
||||
query := r.URL.Query()
|
||||
sourceText := strings.TrimSpace(query.Get("source_text"))
|
||||
if sourceText == "" {
|
||||
return backendrpc.TranslationMemoryQueryParams{}, errors.New("source_text is required")
|
||||
}
|
||||
params := backendrpc.TranslationMemoryQueryParams{
|
||||
TranslationMemoryPath: firstTrimmedQuery(query, "translation_memory_path", "tm_path"),
|
||||
SourceText: sourceText,
|
||||
}
|
||||
if raw := firstTrimmedQuery(query, "source_context", "context"); raw != "" {
|
||||
var context backendrpc.TranslationMemoryContext
|
||||
if raw != "null" {
|
||||
if err := json.Unmarshal([]byte(raw), &context); err != nil {
|
||||
return backendrpc.TranslationMemoryQueryParams{}, errors.New("source_context must be a JSON object with string values")
|
||||
}
|
||||
if context == nil {
|
||||
return backendrpc.TranslationMemoryQueryParams{}, errors.New("source_context must be a JSON object")
|
||||
}
|
||||
params.SourceContext = context
|
||||
}
|
||||
}
|
||||
if raw := strings.TrimSpace(query.Get("limit")); raw != "" {
|
||||
limit, err := strconv.ParseUint(raw, 10, 64)
|
||||
if err != nil || limit == 0 || limit > 1000 {
|
||||
return backendrpc.TranslationMemoryQueryParams{}, errors.New("limit must be in 1..=1000")
|
||||
}
|
||||
params.Limit = &limit
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func parseTextUnitQueryParams(r *http.Request) (backendrpc.TextUnitQueryParams, error) {
|
||||
query := r.URL.Query()
|
||||
params := backendrpc.TextUnitQueryParams{
|
||||
@@ -938,6 +1065,13 @@ func validateTranslationWorkerRunParams(params backendrpc.TranslationWorkerRunPa
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateTranslationMemoryConfirmParams(params backendrpc.TranslationMemoryConfirmParams) error {
|
||||
if strings.TrimSpace(params.RecordID) == "" || strings.TrimSpace(params.Reviewer) == "" {
|
||||
return errors.New("Translation Memory confirm requires record_id and reviewer")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateLocalizedPublishParams(params backendrpc.LocalizedPublishParams) error {
|
||||
hasFile := strings.TrimSpace(params.TranslationFile) != ""
|
||||
if hasFile == params.FromWorker {
|
||||
|
||||
Reference in New Issue
Block a user