fix: report the old translated content_html on API post events

syncTranslations adds content_html to a translation that sends content, after
snapshotPost read the old values, so the event saw content_html as newly
submitted and reported Old: nil for a translation that existed.
submittedTranslations now lists content_html whenever a non-blank content is
sent, so the snapshot and the event cover the same fields.
This commit is contained in:
2026-10-27 15:36:11 +01:00
parent 62c75b1fc2
commit 7a03640b88
2 changed files with 35 additions and 2 deletions

View File

@@ -2,9 +2,11 @@ package api
import (
"context"
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"time"
"git.golem15.com/golem15/sm-journal-plugin/models"
@@ -121,7 +123,11 @@ func postSavedEvent(ctx context.Context, db *gorm.DB, before *postSnapshot, post
}
// submittedTranslations lists, per locale, the translated fields a request
// body submits with a value, in translatedEventFields order.
// body submits with a value, in translatedEventFields order. content_html is
// listed whenever a non-blank content is, as the write derives it from the
// content (classes.FormatTranslation): the snapshot before the write and the
// event after it then cover the same fields, whether or not the write has
// already added content_html to the body.
func submittedTranslations(body map[string]any) map[string][]string {
out := map[string][]string{}
m, ok := body["translations"].(map[string]any)
@@ -134,7 +140,8 @@ func submittedTranslations(body map[string]any) map[string][]string {
continue
}
for _, field := range translatedEventFields {
if v, has := attrs[field]; has && v != nil {
v, has := attrs[field]
if (has && v != nil) || (field == "content_html" && derivesContentHTML(attrs)) {
out[locale] = append(out[locale], field)
}
}
@@ -142,6 +149,13 @@ func submittedTranslations(body map[string]any) map[string][]string {
return out
}
// derivesContentHTML reports whether a translation's attributes carry a
// content the write turns into content_html (a non-blank value).
func derivesContentHTML(attrs map[string]any) bool {
content, has := attrs["content"]
return has && content != nil && strings.TrimSpace(fmt.Sprint(content)) != ""
}
// derefValue is a pointer column's value, nil for a nil pointer.
func derefValue[T any](p *T) any {
if p == nil {