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 := accesslog.File("./access.log")
|
||||||
ac.TimeFormat = "2006-01-02 15:04:05"
|
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
|
broker := ac.Broker() // <- IMPORTANT
|
||||||
|
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
@ -25,7 +26,11 @@ func main() {
|
||||||
app.Get("/", indexHandler)
|
app.Get("/", indexHandler)
|
||||||
app.Get("/profile/{username}", profileHandler)
|
app.Get("/profile/{username}", profileHandler)
|
||||||
app.Post("/read_body", readBodyHandler)
|
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.
|
// http://localhost:8080/logs to see the logs at real-time.
|
||||||
app.Listen(":8080")
|
app.Listen(":8080")
|
||||||
|
@ -52,8 +57,7 @@ func readBodyHandler(ctx iris.Context) {
|
||||||
|
|
||||||
func logsHandler(b *accesslog.Broker) iris.Handler {
|
func logsHandler(b *accesslog.Broker) iris.Handler {
|
||||||
return func(ctx iris.Context) {
|
return func(ctx iris.Context) {
|
||||||
accesslog.Skip(ctx) // skip logging this handler, optionally.
|
// accesslog.Skip(ctx) // or inline skip.
|
||||||
|
|
||||||
logs := b.NewListener() // <- IMPORTANT
|
logs := b.NewListener() // <- IMPORTANT
|
||||||
|
|
||||||
ctx.Header("Transfer-Encoding", "chunked")
|
ctx.Header("Transfer-Encoding", "chunked")
|
||||||
|
|
14
i18n/i18n.go
14
i18n/i18n.go
|
@ -49,6 +49,7 @@ type I18n struct {
|
||||||
localizer Localizer
|
localizer Localizer
|
||||||
matcher *Matcher
|
matcher *Matcher
|
||||||
|
|
||||||
|
Loader *LoaderConfig
|
||||||
loader Loader
|
loader Loader
|
||||||
mu sync.Mutex
|
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.
|
// New returns a new `I18n` instance. Use its `Load` or `LoadAssets` to load languages.
|
||||||
func New() *I18n {
|
func New() *I18n {
|
||||||
return &I18n{
|
i := &I18n{
|
||||||
|
Loader: &LoaderConfig{
|
||||||
|
Left: "{{",
|
||||||
|
Right: "}}",
|
||||||
|
Strict: false,
|
||||||
|
},
|
||||||
URLParameter: "lang",
|
URLParameter: "lang",
|
||||||
Subdomain: true,
|
Subdomain: true,
|
||||||
PathRedirect: true,
|
PathRedirect: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load is a method shortcut to load files using a filepath.Glob pattern.
|
// 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.
|
// See `New` and `Glob` package-level functions for more.
|
||||||
func (i *I18n) Load(globPattern string, languages ...string) error {
|
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.
|
// 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.
|
// See `New` and `Asset` package-level functions for more.
|
||||||
func (i *I18n) LoadAssets(assetNames func() []string, asset func(string) ([]byte, error), languages ...string) error {
|
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.
|
// Reset sets the locales loader and languages.
|
||||||
|
|
|
@ -21,7 +21,8 @@ import (
|
||||||
// some options about how the template loader should act.
|
// some options about how the template loader should act.
|
||||||
//
|
//
|
||||||
// See `Glob` and `Assets` package-level functions.
|
// See `Glob` and `Assets` package-level functions.
|
||||||
type LoaderConfig struct {
|
type (
|
||||||
|
LoaderConfig struct {
|
||||||
// Template delimeters, defaults to {{ }}.
|
// Template delimeters, defaults to {{ }}.
|
||||||
Left, Right string
|
Left, Right string
|
||||||
// Template functions map, defaults to nil.
|
// Template functions map, defaults to nil.
|
||||||
|
@ -31,10 +32,28 @@ type LoaderConfig struct {
|
||||||
// Defaults to false.
|
// Defaults to false.
|
||||||
Strict bool
|
Strict bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoaderOption is a type which accepts a pointer to `LoaderConfig`
|
// 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.
|
// and can be optionally passed to the second
|
||||||
type LoaderOption func(*LoaderConfig)
|
// 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)
|
// Glob accepts a glob pattern (see: https://golang.org/pkg/path/filepath/#Glob)
|
||||||
// and loads the locale files based on any "options".
|
// 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: "{{",
|
Left: "{{",
|
||||||
Right: "}}",
|
Right: "}}",
|
||||||
Strict: false,
|
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 {
|
for _, opt := range options {
|
||||||
opt(&c)
|
opt.Apply(&c)
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(m *Matcher) (Localizer, error) {
|
return func(m *Matcher) (Localizer, error) {
|
||||||
|
@ -250,9 +277,11 @@ func (l *defaultLocale) getMessage(langInput, key string, args ...interface{}) s
|
||||||
// search on templates.
|
// search on templates.
|
||||||
if tmpl, ok := l.templateKeys[key]; ok {
|
if tmpl, ok := l.templateKeys[key]; ok {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
if err := tmpl.Execute(buf, args[0]); err == nil {
|
err := tmpl.Execute(buf, args[0])
|
||||||
return buf.String()
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
}
|
}
|
||||||
|
return buf.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,13 @@ func Skip(ctx iris.Context) {
|
||||||
ctx.Values().Set(skipLogContextKey, struct{}{})
|
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 {
|
func shouldSkip(ctx iris.Context) bool {
|
||||||
return ctx.Values().Get(skipLogContextKey) != nil
|
return ctx.Values().Get(skipLogContextKey) != nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user