3d6ba2852f
gates / gates (push) Successful in 50s
22 Go-literal messages (escrow handler, share password page, export upload, network-storage uid/remove/attach failures) are bundle keys with te-form Hungarian and English; a detached attach failure renders in the reader's language. The NAS refusal says „Válassz". Setup wizard, recovery-info.txt (R-554) and the SMART/fill-watch wire texts are left. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
132 lines
5.8 KiB
Go
132 lines
5.8 KiB
Go
package web
|
|
|
|
import (
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/i18n"
|
|
)
|
|
|
|
var goStringLit = regexp.MustCompile(`"(?:[^"\\]|\\.)*"`)
|
|
|
|
// R-516 (2026-10-06 night) — the formal („ön") forms that lived in GO LITERALS, where the bundle gate
|
|
// cannot read them: the escrow and share handlers, the export upload, the network-storage attach and
|
|
// remove errors, the uid refusal. They are bundle keys now, te-form in Hungarian, with English.
|
|
//
|
|
// Left on purpose (named so the scan's exemptions are not a wish): internal/setup and
|
|
// internal/recovery (the setup wizard and the household's recovery-info.txt — R-554, the operator's
|
|
// call); internal/notify and internal/fillwatch (the SMART and fill-watch texts are the hub event's
|
|
// MESSAGE — wire text the hub mails as is; converting them needs the household-copy producer shape).
|
|
//
|
|
// COMPANION RED-PROOF (observed): put back „próbálja újra" in share_handlers.go → the source scan fails
|
|
// naming the file and the stem. Restored.
|
|
func TestR516_GoLiteralFormalFormsAreGone(t *testing.T) {
|
|
b, err := i18n.Shared()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := map[string]string{
|
|
"api.escrow.too_many_attempts": "Túl sok sikertelen próbálkozás, próbáld újra 1 perc múlva.",
|
|
"api.escrow.no_active_job": "Nincs aktív helyreállítási folyamat — előbb indítsd el a kódkészítést.",
|
|
"api.share.form_invalid": "Érvénytelen űrlap — töltsd újra az oldalt.",
|
|
"api.export.upload_size_mismatch": "A feltöltött méret nem egyezik — próbáld újra.",
|
|
"api.netstorage.add.smb_share": "A megadott SMB-megosztás nem található a szerveren. Ellenőrizd a megosztás nevét.",
|
|
"api.netstorage.add.busy": "Már folyamatban van egy csatlakoztatás. Várd meg, amíg befejeződik.",
|
|
"api.netstorage.uid_range": "Az alkalmazás felhasználói azonosítója (uid) érvénytelen. Adj meg 1 és 65533 közötti értéket — a legtöbb médiaalkalmazás az 1000-est használja.",
|
|
"api.netstorage.add.not_network_fs": "A hálózati tárhely csatolása a rendszeren belül nem jött létre megfelelően. Próbáld újra a csatlakoztatást; ha a hiba ismétlődik, jelezd az üzemeltetőnek.",
|
|
}
|
|
for key, w := range want {
|
|
if got, fellBack, ok := b.Text("hu", key); !ok || fellBack || got != w {
|
|
t.Errorf("hu %s: %q, want %q", key, got, w)
|
|
}
|
|
if _, fellBack, ok := b.Text("en", key); !ok || fellBack {
|
|
t.Errorf("en %s: missing (fell back to Hungarian)", key)
|
|
}
|
|
}
|
|
|
|
// Source scan over the Go literals this row converted. ASCII-folded, so an accent cannot hide one.
|
|
fold := strings.NewReplacer("á", "a", "é", "e", "í", "i", "ó", "o", "ö", "o", "ő", "o", "ú", "u", "ü", "u", "ű", "u")
|
|
stems := []string{"probalja", "toltse ujra", "allitson be", "varja meg", "inditsa", "ellenorizze",
|
|
"hasznalja az eszkoz", "kapcsolja be", "allitsa a", "jelezze az", "tavolitsa el vagy", "adjon meg", "valasszon csatlakoztatott"}
|
|
skip := map[string]bool{"setup": true, "recovery": true, "notify": true, "fillwatch": true}
|
|
root := filepath.Join("..")
|
|
scanned := 0
|
|
err = filepath.Walk(root, func(p string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if info.IsDir() {
|
|
if skip[info.Name()] || info.Name() == "testdata" {
|
|
return filepath.SkipDir
|
|
}
|
|
return nil
|
|
}
|
|
if !strings.HasSuffix(p, ".go") || strings.HasSuffix(p, "_test.go") {
|
|
return nil
|
|
}
|
|
data, rerr := os.ReadFile(p)
|
|
if rerr != nil {
|
|
return rerr
|
|
}
|
|
scanned++
|
|
for i, line := range strings.Split(string(data), "\n") {
|
|
tl := strings.TrimSpace(line)
|
|
if strings.HasPrefix(tl, "//") || !strings.Contains(tl, `"`) {
|
|
continue
|
|
}
|
|
// Only literals with a space are sentences; a bundle KEY (no space) may carry a stem in its name.
|
|
var sentences []string
|
|
for _, m := range goStringLit.FindAllString(tl, -1) {
|
|
if strings.Contains(m, " ") {
|
|
sentences = append(sentences, m)
|
|
}
|
|
}
|
|
lv := fold.Replace(strings.ToLower(strings.Join(sentences, " ")))
|
|
for _, st := range stems {
|
|
if strings.Contains(lv, st) {
|
|
t.Errorf("%s:%d still carries the formal %q: %s", p, i+1, st, tl)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if scanned < 50 {
|
|
t.Fatalf("the scan read only %d Go files — it judged nothing", scanned)
|
|
}
|
|
// Positive control: the fold turns a formal literal into a matching stem.
|
|
if lv := fold.Replace(strings.ToLower(`"Próbálja újra."`)); !strings.Contains(lv, "probalja") {
|
|
t.Fatal("the ASCII fold does not work — the scan proves nothing")
|
|
}
|
|
}
|
|
|
|
// A detached attach job's failure is rendered in the READER's language, not frozen in the language of
|
|
// the moment it failed.
|
|
//
|
|
// COMPANION RED-PROOF (observed): make handleNetStorageAddStatus return job.Message again → the English
|
|
// reader gets the Hungarian sentence and this fails. Restored.
|
|
func TestR516_NetAddFailureFollowsTheReader(t *testing.T) {
|
|
s := testServer(t)
|
|
job := &netAddJob{Name: "media", Phase: netAddPhaseFailed, Category: "unreachable", server: "FELHOM", mappedUID: 1000}
|
|
job.Message = s.netAddMessage("hu", job.Category, job.server, job.mappedUID)
|
|
s.netAdd.set(job)
|
|
|
|
rr := httptest.NewRecorder()
|
|
s.handleNetStorageAddStatus(rr, httptest.NewRequest("GET", "/api/storage/network/add/status?lang=en", nil))
|
|
body := rr.Body.String()
|
|
if !strings.Contains(body, "The server cannot be reached (FELHOM)") || !strings.Contains(body, "looks like a Windows network name") {
|
|
t.Fatalf("an English reader must get the English failure with its tip: %s", body)
|
|
}
|
|
rr = httptest.NewRecorder()
|
|
s.handleNetStorageAddStatus(rr, httptest.NewRequest("GET", "/api/storage/network/add/status?lang=hu", nil))
|
|
if !strings.Contains(rr.Body.String(), "Ellenőrizd az IP-címet") {
|
|
t.Fatalf("a Hungarian reader must get the te-form sentence: %s", rr.Body.String())
|
|
}
|
|
}
|