package suggestions import ( "database/sql" "errors" "net/http" "strings" "github.com/go-chi/chi/v5" "gitea.parodia.dev/drwily/petal/internal/auth" "gitea.parodia.dev/drwily/petal/internal/httputil" "gitea.parodia.dev/drwily/petal/internal/llm" ) type translateResponse struct { Translation string `json:"translation"` } // translate renders a suggestion's English explanation into Simplified Chinese // for the Ask Petal bubble, so the ESL reader sees the "why" in her first // language instead of a second copy of the same English text. The explanation is // loaded server-side from the suggestion id (scoped to the local user) and never // trusted from the client, mirroring chat (spec Note #10). func (h *Handler) translate(w http.ResponseWriter, r *http.Request) { sugID := chi.URLParam(r, "id") var explanation, pairLang string err := h.DB.QueryRow( `SELECT s.explanation, COALESCE(u.pair_lang, '') FROM suggestions s JOIN documents d ON d.id = s.doc_id JOIN users u ON u.id = d.user_id WHERE s.id = ? AND d.user_id = ?`, sugID, auth.UserID(r.Context()), ).Scan(&explanation, &pairLang) if errors.Is(err, sql.ErrNoRows) { httputil.ErrorJSON(w, http.StatusNotFound, "suggestion not found") return } if err != nil { httputil.ServerError(w, err) return } explanation = strings.TrimSpace(explanation) if explanation == "" { httputil.WriteJSON(w, http.StatusOK, translateResponse{Translation: ""}) return } out, err := llm.RunTranslate(r.Context(), h.Client, explanation, llm.LangFor(pairLang)) if err != nil { httputil.UpstreamError(w, "translate", err) return } httputil.WriteJSON(w, http.StatusOK, translateResponse{Translation: out}) }