feat(04-02): load namespaced translations from embedded plugins

- Walk HasLang FS for lang/<locale>/<group>.yaml and flatten nested keys
- Publish one phrasebook.Translator before Boot with en/en defaults
- Hello plugin resolves en/pl vendor.plugin::group.key after Activate

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jakub Zych
2026-09-18 13:47:45 +02:00
parent e7dba5c4fb
commit f824e55c81
9 changed files with 635 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
package party
import (
"fmt"
"io/fs"
"os"
"path/filepath"
@@ -12,6 +13,7 @@ import (
"git.golem15.com/golem15/summercms/bonfire"
"git.golem15.com/golem15/summercms/compass"
"git.golem15.com/golem15/summercms/pact"
"git.golem15.com/golem15/summercms/phrasebook"
)
type tracePlugin struct {
@@ -394,3 +396,62 @@ func TestActivateDiscoversHasConfigAndHasCommands(t *testing.T) {
t.Fatal("plain plugin must not satisfy HasConfig")
}
}
type langPlugin struct {
id string
fsys fs.FS
got *string
}
func (p *langPlugin) ID() string { return p.id }
func (p *langPlugin) Requires() []string { return nil }
func (p *langPlugin) Register(*backpack.App) error { return nil }
func (p *langPlugin) LangFS() fs.FS { return p.fsys }
func (p *langPlugin) Boot(app *backpack.App) error {
if p.got == nil {
return nil
}
tr, ok := app.Lookup[*phrasebook.Translator]()
if !ok {
return fmt.Errorf("translator missing at boot")
}
*p.got = tr.GetIn("en", p.id+"::lang.greeting", nil)
return nil
}
func TestActivatePublishesTranslatorBeforeBoot(t *testing.T) {
var got string
p := &langPlugin{
id: "golem15.hello",
got: &got,
fsys: fstest.MapFS{
"lang/en/lang.yaml": {Data: []byte("greeting: Hello\n")},
},
}
app := backpack.New(&compass.Config{})
if _, err := activate([]Plugin{p}, app, []string{"golem15.hello"}); err != nil {
t.Fatalf("activate: %v", err)
}
if got != "Hello" {
t.Fatalf("boot lookup = %q, want Hello (translator must be published before Boot)", got)
}
}
func TestActivateMalformedLangFailsWithPluginContext(t *testing.T) {
p := &langPlugin{
id: "golem15.hello",
fsys: fstest.MapFS{
"lang/en.yaml": {Data: []byte("greeting: Hello\n")},
},
}
app := backpack.New(&compass.Config{})
_, err := activate([]Plugin{p}, app, []string{"golem15.hello"})
if err == nil {
t.Fatal("expected malformed catalog error")
}
msg := err.Error()
if !strings.Contains(msg, "golem15.hello") || !strings.Contains(msg, "malformed path") {
t.Fatalf("error %q should name the plugin and path problem", msg)
}
}