feat: release v0.26 portable i18n and presentation adapters
This commit is contained in:
135
examples/i18n/main.go
Normal file
135
examples/i18n/main.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
omni "git.yuntuo.hk/k2safe/go-omni"
|
||||
apierrors "git.yuntuo.hk/k2safe/go-omni/errors"
|
||||
"git.yuntuo.hk/k2safe/go-omni/httpx"
|
||||
"git.yuntuo.hk/k2safe/go-omni/i18n"
|
||||
browseri18n "git.yuntuo.hk/k2safe/go-omni/i18n/browser"
|
||||
"git.yuntuo.hk/k2safe/go-omni/i18n/errori18n"
|
||||
"git.yuntuo.hk/k2safe/go-omni/i18n/httpi18n"
|
||||
"git.yuntuo.hk/k2safe/go-omni/response"
|
||||
)
|
||||
|
||||
//go:embed config.json locales/*.json index.html
|
||||
var resources embed.FS
|
||||
|
||||
func catalog() apierrors.Catalog {
|
||||
return errori18n.Bind(apierrors.Catalog{Definitions: map[string]apierrors.Definition{
|
||||
"LIMIT_EXCEEDED": {Status: 409, Code: 400001, Message: "Count must not exceed {max}", Params: []apierrors.Parameter{{Name: "max", Type: "int64"}}},
|
||||
}}, "errors")
|
||||
}
|
||||
|
||||
func bundle() (*i18n.Bundle, error) {
|
||||
raw, err := resources.ReadFile("config.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cfg i18n.Config
|
||||
if err := i18n.DecodeJSON(raw, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
docs, err := i18n.LoadFS(resources, "locales/ui.en.json", "locales/ui.zh-Hans.json", "locales/errors.zh-Hans.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
source, err := errori18n.Source(catalog(), cfg.SourceLocale)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
docs = append(docs, source...)
|
||||
return i18n.New(cfg, docs...)
|
||||
}
|
||||
|
||||
func application(b *i18n.Bundle) (*omni.App, error) {
|
||||
policy, err := httpi18n.New(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
localizer := errori18n.New(b, nil)
|
||||
if err := localizer.Validate(catalog()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a := omni.New(omni.WithErrors(catalog()), omni.WithResponse(response.Config{CodeType: "int32", SuccessCode: 0, ErrorCode: 9999}), omni.WithLanguagePolicy(policy), omni.WithErrorLocalizer(localizer))
|
||||
a.GET("/", func(c *httpx.Context) error {
|
||||
data, err := resources.ReadFile("index.html")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Bytes(200, "text/html; charset=utf-8", data)
|
||||
})
|
||||
a.GET("/runtime.mjs", func(c *httpx.Context) error {
|
||||
data, err := fs.ReadFile(browseri18n.Files(), "runtime.mjs")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Bytes(200, "text/javascript; charset=utf-8", data)
|
||||
})
|
||||
a.GET("/locales/:file", func(c *httpx.Context) error {
|
||||
var locale string
|
||||
switch c.Param("file") {
|
||||
case "en.json":
|
||||
locale = "en"
|
||||
case "zh-Hans.json":
|
||||
locale = "zh-Hans"
|
||||
default:
|
||||
return apierrors.NotFound("NOT_FOUND", "language pack not found")
|
||||
}
|
||||
var out bytes.Buffer
|
||||
if err := b.Export(&out, locale, "ui"); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Bytes(200, "application/json; charset=utf-8", out.Bytes())
|
||||
})
|
||||
a.GET("/api/limit", func(*httpx.Context) error {
|
||||
return apierrors.ByCode("LIMIT_EXCEEDED").WithParams(map[string]any{"max": int64(100)})
|
||||
})
|
||||
a.POST("/api/action", func(c *httpx.Context) error { return c.OK(map[string]bool{"accepted": true}) })
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
serve := flag.String("serve", "", "optional local HTTP listen address")
|
||||
locale := flag.String("export-locale", "", "export a UI language pack to stdout")
|
||||
exportCatalog := flag.Bool("catalog", false, "export the Go error catalog to stdout")
|
||||
flag.Parse()
|
||||
if err := run(*serve, *locale, *exportCatalog); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
func run(serve, locale string, exportCatalog bool) error {
|
||||
if exportCatalog {
|
||||
return apierrors.ExportCatalog(os.Stdout, catalog())
|
||||
}
|
||||
b, err := bundle()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if locale != "" {
|
||||
return b.Export(os.Stdout, locale, "ui")
|
||||
}
|
||||
if serve != "" {
|
||||
a, err := application(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer a.Close()
|
||||
return a.Run(serve)
|
||||
}
|
||||
for _, l := range b.Config().Locales {
|
||||
result, err := b.Render(l, i18n.Ref{Namespace: "ui", Key: "greeting"}, map[string]any{"name": "Alex"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(result.Locale + ": " + result.Text)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user