Found during v0.118.0's own live proof, which is the only reason it was found: I went to press "send test notification" for the English demo box and read sendTestEmail first. It had its own hardcoded Hungarian subject and body and never went through FormatCustomerEmail, so it was the one customer mail v0.118.0 did not localise — and it is the only customer mail an operator can trigger on demand, which makes it the one most likely to be used to check whether the localisation works. Pressing the button for an English household would have answered that question wrongly, and convincingly. The two sentences are extracted byte-for-byte into the bundle, so the Hungarian test mail is unchanged. Red-proofed against the hardcoded version. The general form worth keeping: the surface you would use to CHECK a feature is the one most worth checking first. A broken instrument that reports success is worse than a broken feature. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -1,3 +1,21 @@
|
||||
## v0.118.1 — the test mail follows the language too (2026-09-18, R-558)
|
||||
|
||||
Found during v0.118.0's own live proof, which is the only reason it was found: I went to press "send
|
||||
test notification" for the English demo box and read `sendTestEmail` first.
|
||||
|
||||
- **`sendTestEmail` had its own hardcoded Hungarian subject and body** and never went through
|
||||
`FormatCustomerEmail`, so it was the one customer mail v0.118.0 did not localise. It is also **the
|
||||
only customer mail an operator can trigger on demand** — which makes it the one most likely to be
|
||||
used to check whether the localisation works. Left alone, pressing the button for an English
|
||||
household would have answered that question wrongly, and convincingly.
|
||||
- Its two sentences are now `mail.test.subject` / `mail.test.body` in the bundle, extracted
|
||||
byte-for-byte from the literals so the Hungarian test mail is unchanged.
|
||||
- `TestTestMailFollowsTheHouseholdLanguage`, red-proofed against the hardcoded version ("en test mail
|
||||
subject = \"[Felhom] Teszt értesítés\", want it to contain \"Test notification\"").
|
||||
|
||||
**The general form worth keeping: the surface you would use to CHECK a feature is the one most worth
|
||||
checking first.** A broken instrument that reports success is worse than a broken feature.
|
||||
|
||||
## v0.118.0 — the household's e-mails follow the household's language (2026-09-18, R-558 / R-555)
|
||||
|
||||
**Localisation slice 3, Part A.** The hub has written every customer e-mail in Hungarian whatever the
|
||||
|
||||
@@ -77,5 +77,7 @@
|
||||
"bind.locked.body": "There were too many failed attempts. For safety the link has locked — contact support to link the box.",
|
||||
"bind.invalid.lead": "This link is invalid or has expired.",
|
||||
"bind.invalid.body": "The link is valid for 7 days. If it has expired, ask support for a new one, or your operator can do the linking.",
|
||||
"bind.htmllang": "en"
|
||||
"bind.htmllang": "en",
|
||||
"mail.test.subject": "[Felhom] Test notification",
|
||||
"mail.test.body": "Dear Customer,\n\nThis is a test notification from the Felhom monitoring system.\nNotifications are working correctly.\n\nBest regards,\nFelhom.eu monitoring"
|
||||
}
|
||||
|
||||
@@ -77,5 +77,7 @@
|
||||
"bind.locked.body": "Túl sok sikertelen próbálkozás történt. Biztonsági okból a hivatkozás zárolódott — kérjük, vedd fel a kapcsolatot az ügyfélszolgálattal a doboz összekötéséhez.",
|
||||
"bind.invalid.lead": "Ez a hivatkozás érvénytelen vagy lejárt.",
|
||||
"bind.invalid.body": "A hivatkozás 7 napig érvényes. Ha lejárt, kérj újat az ügyfélszolgálattól, vagy az összekötést az üzemeltető is elvégezheti.",
|
||||
"bind.htmllang": "hu"
|
||||
"bind.htmllang": "hu",
|
||||
"mail.test.subject": "[Felhom] Teszt értesítés",
|
||||
"mail.test.body": "Kedves Ügyfél!\n\nEz egy teszt értesítés a Felhom monitoring rendszerből.\nAz értesítések megfelelően működnek.\n\nÜdvözlettel,\nFelhom.eu monitoring"
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
"time"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-hub/internal/i18n"
|
||||
)
|
||||
|
||||
// Dispatcher routes events to operator and/or customer email channels.
|
||||
@@ -199,8 +201,17 @@ func (d *Dispatcher) sendTestEmail(customerID string) {
|
||||
if err != nil || prefs == nil || prefs.Email == "" {
|
||||
d.logger.Printf("[WARN] Test email: no email configured for %s", customerID)
|
||||
} else {
|
||||
subject := "[Felhom] Teszt értesítés"
|
||||
body := "Kedves Ügyfél!\n\nEz egy teszt értesítés a Felhom monitoring rendszerből.\nAz értesítések megfelelően működnek.\n\nÜdvözlettel,\nFelhom.eu monitoring"
|
||||
// The test mail follows the household's language like every other customer mail (R-558).
|
||||
//
|
||||
// It was the ONE that would not have: it is the only customer mail with its own hardcoded
|
||||
// text, because it never goes through FormatCustomerEmail — and it is also the only one an
|
||||
// operator can trigger on demand, so it is the one most likely to be used to CHECK whether
|
||||
// the localisation works. Left alone, pressing "send test" for an English household would
|
||||
// have answered that question wrongly.
|
||||
b := i18n.Shared()
|
||||
lang := d.store.CustomerLanguage(customerID)
|
||||
subject := b.Msg(lang, "mail.test.subject")
|
||||
body := b.Msg(lang, "mail.test.body")
|
||||
|
||||
if err := d.sendEmailFn(prefs.Email, subject, body, nil); err != nil {
|
||||
d.logger.Printf("[ERROR] Test email to %s failed: %v", prefs.Email, err)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-hub/internal/i18n"
|
||||
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
||||
)
|
||||
|
||||
// Localisation slice 3 (R-558) — the behaviour the bundle exists to produce.
|
||||
@@ -123,3 +126,44 @@ func TestUnknownLanguageRendersHungarian(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The TEST mail follows the household's language too.
|
||||
//
|
||||
// It is the one customer mail with its own text — it never goes through FormatCustomerEmail — and
|
||||
// it is also the only one an operator can trigger on demand, so it is the one most likely to be
|
||||
// used to CHECK whether the localisation works. It was still hardcoded Hungarian when the rest of
|
||||
// this release was finished; pressing "send test" for an English household would have answered that
|
||||
// question wrongly, in the most convincing possible way.
|
||||
func TestTestMailFollowsTheHouseholdLanguage(t *testing.T) {
|
||||
for _, tc := range []struct{ lang, want, notWant string }{
|
||||
{"en", "Test notification", "Teszt"},
|
||||
{"hu", "Teszt értesítés", "Test notification"},
|
||||
} {
|
||||
st := newDispStore(t)
|
||||
if err := st.SaveCustomerConfig(&store.CustomerConfig{
|
||||
CustomerID: "c1", APIKey: "k", RetrievalPassword: "p", Language: tc.lang,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := st.SaveNotificationPrefs("c1", "fam@example.com", []string{"test"}, 6); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d := NewDispatcher(st, "test-key", "from@felhom.eu", "", false, log.New(io.Discard, "", 0))
|
||||
var subject, body string
|
||||
d.sendEmailFn = func(_, s, b string, _ map[string]string) error {
|
||||
subject, body = s, b
|
||||
return nil
|
||||
}
|
||||
d.ProcessEvent("c1", "test", "info", "", "{}", "hub")
|
||||
|
||||
if !strings.Contains(subject, tc.want) {
|
||||
t.Errorf("%s test mail subject = %q, want it to contain %q", tc.lang, subject, tc.want)
|
||||
}
|
||||
if strings.Contains(subject, tc.notWant) || strings.Contains(body, tc.notWant) {
|
||||
t.Errorf("%s test mail carries the other language (%q):\n%s\n%s", tc.lang, tc.notWant, subject, body)
|
||||
}
|
||||
if body == "" {
|
||||
t.Fatalf("%s test mail has an empty body — the seam did not fire", tc.lang)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: hub
|
||||
image: gitea.dooplex.hu/admin/felhom-hub:0.118.0
|
||||
image: gitea.dooplex.hu/admin/felhom-hub:0.118.1
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
|
||||
Reference in New Issue
Block a user