mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
i18n: expose the LoaderConfig from the main i18n instance and add an example
Signed-off-by: Gerasimos (Makis) Maropoulos <kataras2006@hotmail.com>
This commit is contained in:
parent
b77227a0f9
commit
777ef0cd3e
2
_examples/i18n/i18n-template/locales/el-GR/welcome.yml
Normal file
2
_examples/i18n/i18n-template/locales/el-GR/welcome.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
Dog: "σκυλί"
|
||||
HiDogs: Γειά {{plural (tr .locale "Dog") .count }}
|
2
_examples/i18n/i18n-template/locales/en-US/welcome.yml
Normal file
2
_examples/i18n/i18n-template/locales/en-US/welcome.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
Dog: "dog"
|
||||
HiDogs: Hi {{plural (tr .locale "Dog") .count }}
|
42
_examples/i18n/i18n-template/main.go
Normal file
42
_examples/i18n/i18n-template/main.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris/v12"
|
||||
|
||||
// go get -u github.com/gertd/go-pluralize
|
||||
"github.com/gertd/go-pluralize"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := newApp()
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
|
||||
pluralize := pluralize.NewClient()
|
||||
app.I18n.Loader.FuncMap = map[string]interface{}{
|
||||
"plural": func(word string, count int) string {
|
||||
// Your own implementation or use a 3rd-party package
|
||||
// like we do here.
|
||||
//
|
||||
// Note that this is only for english,
|
||||
// but you can accept the language code
|
||||
// and use a map with dictionaries to
|
||||
// pluralize words based on the given language.
|
||||
return pluralize.Pluralize(word, count, true)
|
||||
},
|
||||
}
|
||||
app.I18n.Load("./locales/*/*.yml", "en-US", "el-GR")
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
text := ctx.Tr("HiDogs", iris.Map{
|
||||
"locale": ctx.GetLocale(),
|
||||
"count": 2,
|
||||
}) // prints "Hi 2 dogs".
|
||||
ctx.WriteString(text)
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
17
_examples/i18n/i18n-template/main_test.go
Normal file
17
_examples/i18n/i18n-template/main_test.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris/v12/httptest"
|
||||
)
|
||||
|
||||
func TestI18nLoaderFuncMap(t *testing.T) {
|
||||
app := newApp()
|
||||
|
||||
e := httptest.New(t, app)
|
||||
e.GET("/").Expect().Status(httptest.StatusOK).
|
||||
Body().Equal("Hi 2 dogs")
|
||||
e.GET("/").WithHeader("Accept-Language", "el").Expect().Status(httptest.StatusOK).
|
||||
Body().Equal("Γειά 2 σκυλί")
|
||||
}
|
|
@ -16,7 +16,8 @@ func main() {
|
|||
|
||||
ac := accesslog.File("./access.log")
|
||||
ac.TimeFormat = "2006-01-02 15:04:05"
|
||||
ac.Async = true
|
||||
// Optionally run logging after response has sent:
|
||||
// ac.Async = true
|
||||
broker := ac.Broker() // <- IMPORTANT
|
||||
|
||||
app := iris.New()
|
||||
|
@ -25,7 +26,11 @@ func main() {
|
|||
app.Get("/", indexHandler)
|
||||
app.Get("/profile/{username}", profileHandler)
|
||||
app.Post("/read_body", readBodyHandler)
|
||||
app.Get("/logs", logsHandler(broker))
|
||||
|
||||
// register the /logs route,
|
||||
// registers a listener and prints the incoming logs.
|
||||
// Optionally, skip logging this handler.
|
||||
app.Get("/logs", accesslog.SkipHandler, logsHandler(broker))
|
||||
|
||||
// http://localhost:8080/logs to see the logs at real-time.
|
||||
app.Listen(":8080")
|
||||
|
@ -52,8 +57,7 @@ func readBodyHandler(ctx iris.Context) {
|
|||
|
||||
func logsHandler(b *accesslog.Broker) iris.Handler {
|
||||
return func(ctx iris.Context) {
|
||||
accesslog.Skip(ctx) // skip logging this handler, optionally.
|
||||
|
||||
// accesslog.Skip(ctx) // or inline skip.
|
||||
logs := b.NewListener() // <- IMPORTANT
|
||||
|
||||
ctx.Header("Transfer-Encoding", "chunked")
|
||||
|
|
14
i18n/i18n.go
14
i18n/i18n.go
|
@ -49,6 +49,7 @@ type I18n struct {
|
|||
localizer Localizer
|
||||
matcher *Matcher
|
||||
|
||||
Loader *LoaderConfig
|
||||
loader Loader
|
||||
mu sync.Mutex
|
||||
|
||||
|
@ -106,11 +107,18 @@ func makeTags(languages ...string) (tags []language.Tag) {
|
|||
|
||||
// New returns a new `I18n` instance. Use its `Load` or `LoadAssets` to load languages.
|
||||
func New() *I18n {
|
||||
return &I18n{
|
||||
i := &I18n{
|
||||
Loader: &LoaderConfig{
|
||||
Left: "{{",
|
||||
Right: "}}",
|
||||
Strict: false,
|
||||
},
|
||||
URLParameter: "lang",
|
||||
Subdomain: true,
|
||||
PathRedirect: true,
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
// Load is a method shortcut to load files using a filepath.Glob pattern.
|
||||
|
@ -118,7 +126,7 @@ func New() *I18n {
|
|||
//
|
||||
// See `New` and `Glob` package-level functions for more.
|
||||
func (i *I18n) Load(globPattern string, languages ...string) error {
|
||||
return i.Reset(Glob(globPattern), languages...)
|
||||
return i.Reset(Glob(globPattern, i.Loader), languages...)
|
||||
}
|
||||
|
||||
// LoadAssets is a method shortcut to load files using go-bindata.
|
||||
|
@ -126,7 +134,7 @@ func (i *I18n) Load(globPattern string, languages ...string) error {
|
|||
//
|
||||
// See `New` and `Asset` package-level functions for more.
|
||||
func (i *I18n) LoadAssets(assetNames func() []string, asset func(string) ([]byte, error), languages ...string) error {
|
||||
return i.Reset(Assets(assetNames, asset), languages...)
|
||||
return i.Reset(Assets(assetNames, asset, i.Loader), languages...)
|
||||
}
|
||||
|
||||
// Reset sets the locales loader and languages.
|
||||
|
|
|
@ -21,7 +21,8 @@ import (
|
|||
// some options about how the template loader should act.
|
||||
//
|
||||
// See `Glob` and `Assets` package-level functions.
|
||||
type LoaderConfig struct {
|
||||
type (
|
||||
LoaderConfig struct {
|
||||
// Template delimeters, defaults to {{ }}.
|
||||
Left, Right string
|
||||
// Template functions map, defaults to nil.
|
||||
|
@ -31,10 +32,28 @@ type LoaderConfig struct {
|
|||
// Defaults to false.
|
||||
Strict bool
|
||||
}
|
||||
|
||||
// LoaderOption is a type which accepts a pointer to `LoaderConfig`
|
||||
// and can be optionally passed to the second variadic input argument of the `Glob` and `Assets` functions.
|
||||
type LoaderOption func(*LoaderConfig)
|
||||
// and can be optionally passed to the second
|
||||
// variadic input argument of the `Glob` and `Assets` functions.
|
||||
LoaderOption interface {
|
||||
Apply(*LoaderConfig)
|
||||
}
|
||||
)
|
||||
|
||||
// Apply implements the `LoaderOption` interface.
|
||||
func (c *LoaderConfig) Apply(cfg *LoaderConfig) {
|
||||
for k, v := range c.FuncMap {
|
||||
if cfg.FuncMap == nil {
|
||||
cfg.FuncMap = make(template.FuncMap)
|
||||
}
|
||||
|
||||
cfg.FuncMap[k] = v
|
||||
}
|
||||
|
||||
cfg.Left = c.Left
|
||||
cfg.Right = c.Right
|
||||
cfg.Strict = c.Strict
|
||||
}
|
||||
|
||||
// Glob accepts a glob pattern (see: https://golang.org/pkg/path/filepath/#Glob)
|
||||
// and loads the locale files based on any "options".
|
||||
|
@ -73,10 +92,18 @@ func load(assetNames []string, asset func(string) ([]byte, error), options ...Lo
|
|||
Left: "{{",
|
||||
Right: "}}",
|
||||
Strict: false,
|
||||
FuncMap: template.FuncMap{
|
||||
// get returns the value of a translate key, can be used inside other template keys
|
||||
// to translate different words based on the current locale.
|
||||
"tr": func(locale context.Locale, key string, args ...interface{}) string {
|
||||
return locale.GetMessage(key, args...)
|
||||
},
|
||||
// ^ Alternative to {{call .tr "Dog" | plural }}
|
||||
},
|
||||
}
|
||||
|
||||
for _, opt := range options {
|
||||
opt(&c)
|
||||
opt.Apply(&c)
|
||||
}
|
||||
|
||||
return func(m *Matcher) (Localizer, error) {
|
||||
|
@ -250,9 +277,11 @@ func (l *defaultLocale) getMessage(langInput, key string, args ...interface{}) s
|
|||
// search on templates.
|
||||
if tmpl, ok := l.templateKeys[key]; ok {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := tmpl.Execute(buf, args[0]); err == nil {
|
||||
return buf.String()
|
||||
err := tmpl.Execute(buf, args[0])
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,13 @@ func Skip(ctx iris.Context) {
|
|||
ctx.Values().Set(skipLogContextKey, struct{}{})
|
||||
}
|
||||
|
||||
// SkipHandler same as `Skip` but it can be used
|
||||
// as a middleware, it executes ctx.Next().
|
||||
func SkipHandler(ctx iris.Context) {
|
||||
Skip(ctx)
|
||||
ctx.Next()
|
||||
}
|
||||
|
||||
func shouldSkip(ctx iris.Context) bool {
|
||||
return ctx.Values().Get(skipLogContextKey) != nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user