mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 10:04:55 +08:00
feat(glossary): 实现 Rust Glossary V1
This commit is contained in:
@@ -56,6 +56,9 @@ func (s *Server) handleAdminIndex(w http.ResponseWriter, r *http.Request) {
|
||||
"/admin/translation/handoff",
|
||||
"/admin/translation/memory/summary",
|
||||
"/admin/translation/memory/query",
|
||||
"/admin/translation/glossary/summary",
|
||||
"/admin/translation/glossary/query",
|
||||
"/admin/translation/glossary/diagnose",
|
||||
"/admin/translation/status",
|
||||
},
|
||||
Controls: []string{
|
||||
@@ -75,6 +78,10 @@ func (s *Server) handleAdminIndex(w http.ResponseWriter, r *http.Request) {
|
||||
"/admin/control/translation-worker-run",
|
||||
"/admin/control/translation-proofread",
|
||||
"/admin/control/translation-memory-confirm",
|
||||
"/admin/control/translation-glossary-add",
|
||||
"/admin/control/translation-glossary-update",
|
||||
"/admin/control/translation-glossary-approve",
|
||||
"/admin/control/translation-glossary-deprecate",
|
||||
"/admin/control/localized-publish",
|
||||
"/admin/control/localized-rollback",
|
||||
},
|
||||
@@ -124,6 +131,10 @@ func (s *Server) handleAdminControl(w http.ResponseWriter, r *http.Request) {
|
||||
s.handleAdminTranslationMemoryConfirm(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(action, "translation-glossary-") {
|
||||
s.handleAdminGlossaryControl(w, r, action)
|
||||
return
|
||||
}
|
||||
if action == "localized-publish" {
|
||||
s.handleAdminLocalizedPublish(w, r)
|
||||
return
|
||||
@@ -309,6 +320,201 @@ func (s *Server) handleAdminTranslationMemoryConfirm(w http.ResponseWriter, r *h
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminGlossarySummary(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.(GlossaryBackend)
|
||||
if !ok || backend == nil {
|
||||
writeErrorJSON(w, http.StatusServiceUnavailable, "glossary_backend_unavailable", "Rust bat Glossary backend is unavailable")
|
||||
return
|
||||
}
|
||||
params := backendrpc.GlossarySummaryParams{
|
||||
GlossaryPath: firstTrimmedQuery(r.URL.Query(), "glossary_path"),
|
||||
}
|
||||
result, err := backend.GlossarySummary(r.Context(), params)
|
||||
if err != nil {
|
||||
s.writeControlBackendError(w, "translation-glossary-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) handleAdminGlossaryQuery(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.(GlossaryBackend)
|
||||
if !ok || backend == nil {
|
||||
writeErrorJSON(w, http.StatusServiceUnavailable, "glossary_backend_unavailable", "Rust bat Glossary backend is unavailable")
|
||||
return
|
||||
}
|
||||
params := backendrpc.GlossaryQueryParams{
|
||||
GlossaryPath: firstTrimmedQuery(r.URL.Query(), "glossary_path"),
|
||||
SourceText: firstTrimmedQuery(r.URL.Query(), "source_text"),
|
||||
Category: firstTrimmedQuery(r.URL.Query(), "category"),
|
||||
ReviewStatus: firstTrimmedQuery(r.URL.Query(), "review_status"),
|
||||
}
|
||||
if raw := strings.TrimSpace(r.URL.Query().Get("limit")); raw != "" {
|
||||
limit, err := strconv.ParseUint(raw, 10, 64)
|
||||
if err != nil || limit == 0 || limit > 1000 {
|
||||
writeErrorJSON(w, http.StatusBadRequest, "invalid_glossary_query", "limit must be in 1..=1000")
|
||||
return
|
||||
}
|
||||
params.Limit = &limit
|
||||
}
|
||||
result, err := backend.GlossaryQuery(r.Context(), params)
|
||||
if err != nil {
|
||||
s.writeControlBackendError(w, "translation-glossary-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) handleAdminGlossaryDiagnose(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.(GlossaryBackend)
|
||||
if !ok || backend == nil {
|
||||
writeErrorJSON(w, http.StatusServiceUnavailable, "glossary_backend_unavailable", "Rust bat Glossary backend is unavailable")
|
||||
return
|
||||
}
|
||||
params := backendrpc.GlossaryDiagnoseParams{
|
||||
GlossaryPath: firstTrimmedQuery(r.URL.Query(), "glossary_path"),
|
||||
SourceText: firstTrimmedQuery(r.URL.Query(), "source_text"),
|
||||
}
|
||||
if params.SourceText == "" {
|
||||
writeErrorJSON(w, http.StatusBadRequest, "invalid_glossary_query", "source_text is required")
|
||||
return
|
||||
}
|
||||
if raw := firstTrimmedQuery(r.URL.Query(), "context", "source_context"); raw != "" {
|
||||
if err := json.Unmarshal([]byte(raw), ¶ms.Context); err != nil || params.Context == nil {
|
||||
writeErrorJSON(w, http.StatusBadRequest, "invalid_glossary_query", "context must be a JSON object with string values")
|
||||
return
|
||||
}
|
||||
}
|
||||
result, err := backend.GlossaryDiagnose(r.Context(), params)
|
||||
if err != nil {
|
||||
s.writeControlBackendError(w, "translation-glossary-diagnose", 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) handleAdminGlossaryControl(w http.ResponseWriter, r *http.Request, action string) {
|
||||
backend, ok := s.backend.(GlossaryBackend)
|
||||
if !ok || backend == nil {
|
||||
writeErrorJSON(w, http.StatusServiceUnavailable, "glossary_backend_unavailable", "Rust bat Glossary backend is unavailable")
|
||||
return
|
||||
}
|
||||
switch action {
|
||||
case "translation-glossary-add", "translation-glossary-update":
|
||||
var params backendrpc.GlossaryTermMutationParams
|
||||
if !decodeAdminTranslationJSON(w, r, ¶ms) {
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(params.TermID) == "" || strings.TrimSpace(params.SourceTerm) == "" ||
|
||||
strings.TrimSpace(params.RecommendedTranslation) == "" {
|
||||
writeErrorJSON(w, http.StatusBadRequest, "invalid_glossary_params", "term_id, source_term and recommended_translation are required")
|
||||
return
|
||||
}
|
||||
var result *backendrpc.GlossaryMutationReport
|
||||
var err error
|
||||
if action == "translation-glossary-add" {
|
||||
result, err = backend.GlossaryAdd(r.Context(), params)
|
||||
} else {
|
||||
if strings.TrimSpace(params.Reviewer) == "" {
|
||||
writeErrorJSON(w, http.StatusBadRequest, "invalid_glossary_params", "reviewer is required for update")
|
||||
return
|
||||
}
|
||||
result, err = backend.GlossaryUpdate(r.Context(), params)
|
||||
}
|
||||
if err != nil {
|
||||
s.writeControlBackendError(w, action, err)
|
||||
return
|
||||
}
|
||||
writeNoStoreJSON(w, http.StatusAccepted, AdminControlResponse{
|
||||
Service: "bat-api",
|
||||
Action: action,
|
||||
RPCMethod: glossaryControlRPCMethod(action),
|
||||
Status: "accepted",
|
||||
Result: result,
|
||||
})
|
||||
case "translation-glossary-approve", "translation-glossary-deprecate":
|
||||
var params backendrpc.GlossaryReviewParams
|
||||
if !decodeAdminTranslationJSON(w, r, ¶ms) {
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(params.TermID) == "" || strings.TrimSpace(params.Reviewer) == "" {
|
||||
writeErrorJSON(w, http.StatusBadRequest, "invalid_glossary_params", "term_id and reviewer are required")
|
||||
return
|
||||
}
|
||||
var result *backendrpc.GlossaryMutationReport
|
||||
var err error
|
||||
if action == "translation-glossary-approve" {
|
||||
result, err = backend.GlossaryApprove(r.Context(), params)
|
||||
} else {
|
||||
result, err = backend.GlossaryDeprecate(r.Context(), params)
|
||||
}
|
||||
if err != nil {
|
||||
s.writeControlBackendError(w, action, err)
|
||||
return
|
||||
}
|
||||
writeNoStoreJSON(w, http.StatusAccepted, AdminControlResponse{
|
||||
Service: "bat-api",
|
||||
Action: action,
|
||||
RPCMethod: glossaryControlRPCMethod(action),
|
||||
Status: "accepted",
|
||||
Result: result,
|
||||
})
|
||||
default:
|
||||
writeErrorJSON(w, http.StatusNotFound, "control_not_found", "unknown glossary control action")
|
||||
}
|
||||
}
|
||||
|
||||
func glossaryControlRPCMethod(action string) string {
|
||||
switch action {
|
||||
case "translation-glossary-add":
|
||||
return "translation.glossary.add"
|
||||
case "translation-glossary-update":
|
||||
return "translation.glossary.update"
|
||||
case "translation-glossary-approve":
|
||||
return "translation.glossary.approve"
|
||||
case "translation-glossary-deprecate":
|
||||
return "translation.glossary.deprecate"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handleAdminLocalizedPublish(w http.ResponseWriter, r *http.Request) {
|
||||
backend, ok := s.backend.(LocalizedBackend)
|
||||
if !ok || backend == nil {
|
||||
|
||||
Reference in New Issue
Block a user