mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
add LoadKV method on Iris.Application.I18N instance
This commit is contained in:
parent
41326d4ddd
commit
0954986a66
|
@ -23,6 +23,8 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
|
||||||
|
|
||||||
Change applies to `master` branch.
|
Change applies to `master` branch.
|
||||||
|
|
||||||
|
- Add `LoadKV` method on `Iris.Application.I18N` instance. It should be used when no locale files are available. It loads locales via pure Go Map (or database decoded values).
|
||||||
|
|
||||||
- Remove [ace](https://github.com/eknkc/amber) template parser support, as it was discontinued by its author more than five years ago.
|
- Remove [ace](https://github.com/eknkc/amber) template parser support, as it was discontinued by its author more than five years ago.
|
||||||
|
|
||||||
# Sa, 11 March 2023 | v12.2.0
|
# Sa, 11 March 2023 | v12.2.0
|
||||||
|
|
|
@ -4,7 +4,7 @@ User = Λογαριασμός
|
||||||
[debug]
|
[debug]
|
||||||
Title = Μενού προγραμματιστή
|
Title = Μενού προγραμματιστή
|
||||||
AccessLog = Πρόσβαση στο αρχείο καταγραφής
|
AccessLog = Πρόσβαση στο αρχείο καταγραφής
|
||||||
AccessLogClear = Καθαρισμός {{tr "debug.AccessLog"}}
|
AccessLogClear = Καθαρισμός {{ tr "debug.AccessLog" }}
|
||||||
|
|
||||||
[user.connections]
|
[user.connections]
|
||||||
Title = {{tr "nav.User"}} Συνδέσεις
|
Title = {{ tr "nav.User" }} Συνδέσεις
|
|
@ -1,4 +1,4 @@
|
||||||
[forms]
|
[forms]
|
||||||
member = μέλος
|
member = μέλος
|
||||||
register = Γίνε {{uppercase (tr "forms.member") }}
|
register = Γίνε {{ uppercase (tr "forms.member") }}
|
||||||
registered = εγγεγραμμένοι
|
registered = εγγεγραμμένοι
|
|
@ -6,7 +6,7 @@ User = Account
|
||||||
[debug]
|
[debug]
|
||||||
Title = Developer Menu
|
Title = Developer Menu
|
||||||
AccessLog = Access Log
|
AccessLog = Access Log
|
||||||
AccessLogClear = Clear {{tr "debug.AccessLog"}}
|
AccessLogClear = Clear {{ tr "debug.AccessLog" }}
|
||||||
|
|
||||||
[user.connections]
|
[user.connections]
|
||||||
Title = {{tr "nav.User"}} Connections
|
Title = {{ tr "nav.User" }} Connections
|
|
@ -1,4 +1,4 @@
|
||||||
[forms]
|
[forms]
|
||||||
member = member
|
member = member
|
||||||
register = Become a {{uppercase (tr "forms.member") }}
|
register = Become a {{ uppercase (tr "forms.member") }}
|
||||||
registered = registered
|
registered = registered
|
|
@ -13,6 +13,16 @@ var embeddedFS embed.FS
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := newApp()
|
app := newApp()
|
||||||
|
// http://localhost:8080
|
||||||
|
// http://localhost:8080?lang=el
|
||||||
|
// http://localhost:8080?lang=el
|
||||||
|
// http://localhost:8080?lang=el-GR
|
||||||
|
// http://localhost:8080?lang=en
|
||||||
|
// http://localhost:8080?lang=en-US
|
||||||
|
//
|
||||||
|
// http://localhost:8080/title
|
||||||
|
// http://localhost:8080/title?lang=el-GR
|
||||||
|
// ...
|
||||||
app.Listen(":8080")
|
app.Listen(":8080")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +40,14 @@ func newApp() *iris.Application {
|
||||||
|
|
||||||
// Instead of:
|
// Instead of:
|
||||||
// err := app.I18n.Load("./locales/*/*.ini", "en-US", "el-GR")
|
// err := app.I18n.Load("./locales/*/*.ini", "en-US", "el-GR")
|
||||||
// Apply the below in order to build with embedded locales inside your executable binary.
|
// apply the below in order to build with embedded locales inside your executable binary.
|
||||||
err := app.I18n.LoadFS(embeddedFS, "./embedded/locales/*/*.ini", "en-US", "el-GR")
|
err := app.I18n.LoadFS(embeddedFS, "./embedded/locales/*/*.ini", "en-US", "el-GR")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
} // OR to load all languages by filename:
|
||||||
|
// app.I18n.LoadFS(embeddedFS, "./embedded/locales/*/*.ini")
|
||||||
|
// Then set the default language using:
|
||||||
|
// app.I18n.SetDefault("en-US")
|
||||||
|
|
||||||
app.Get("/", func(ctx iris.Context) {
|
app.Get("/", func(ctx iris.Context) {
|
||||||
text := ctx.Tr("forms.register") // en-US: prints "Become a MEMBER".
|
text := ctx.Tr("forms.register") // en-US: prints "Become a MEMBER".
|
||||||
|
|
21
i18n/i18n.go
21
i18n/i18n.go
|
@ -141,8 +141,8 @@ func (i *I18n) LoadAssets(assetNames func() []string, asset func(string) ([]byte
|
||||||
return i.Reset(Assets(assetNames, asset, i.Loader), languages...)
|
return i.Reset(Assets(assetNames, asset, i.Loader), languages...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadFS is a method shortcut to load files using `embed.FS` or `fs.FS` or
|
// LoadFS is a method shortcut to load files using
|
||||||
// `http.FileSystem` or `string` (local directory).
|
// an `embed.FS` or `fs.FS` or `http.FileSystem` value.
|
||||||
// The "pattern" is a classic glob pattern.
|
// The "pattern" is a classic glob pattern.
|
||||||
//
|
//
|
||||||
// See `New` and `FS` package-level functions for more.
|
// See `New` and `FS` package-level functions for more.
|
||||||
|
@ -156,6 +156,13 @@ func (i *I18n) LoadFS(fileSystem fs.FS, pattern string, languages ...string) err
|
||||||
return i.Reset(loader, languages...)
|
return i.Reset(loader, languages...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadKV is a method shortcut to load locales from a map of specified languages.
|
||||||
|
// See `KV` package-level function for more.
|
||||||
|
func (i *I18n) LoadKV(langMap LangMap, languages ...string) error {
|
||||||
|
loader := KV(langMap, i.Loader)
|
||||||
|
return i.Reset(loader, languages...)
|
||||||
|
}
|
||||||
|
|
||||||
// Reset sets the locales loader and languages.
|
// Reset sets the locales loader and languages.
|
||||||
// It is not meant to be used by users unless
|
// It is not meant to be used by users unless
|
||||||
// a custom `Loader` must be used instead of the default one.
|
// a custom `Loader` must be used instead of the default one.
|
||||||
|
@ -300,6 +307,16 @@ func parsePath(m *Matcher, path string) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseLanguageName(m *Matcher, name string) int {
|
||||||
|
if t, err := language.Parse(name); err == nil {
|
||||||
|
if _, index, conf := m.MatchOrAdd(t); conf > language.Low {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
func reverseStrings(s []string) []string {
|
func reverseStrings(s []string) []string {
|
||||||
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
||||||
s[i], s[j] = s[j], s[i]
|
s[i], s[j] = s[j], s[i]
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
|
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
"golang.org/x/text/message"
|
"golang.org/x/text/message"
|
||||||
"golang.org/x/text/message/catalog"
|
"golang.org/x/text/message/catalog"
|
||||||
|
|
|
@ -73,6 +73,70 @@ func FS(fileSystem fs.FS, pattern string, options LoaderConfig) (Loader, error)
|
||||||
return load(assetNames, assetFunc, options), nil
|
return load(assetNames, assetFunc, options), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LangMap key as language (e.g. "el-GR") and value as a map of key-value pairs (e.g. "hello": "Γειά").
|
||||||
|
type LangMap = map[string]map[string]interface{}
|
||||||
|
|
||||||
|
// KV is a loader which accepts a map of language(key) and the available key-value pairs.
|
||||||
|
// Example Code:
|
||||||
|
//
|
||||||
|
// m := i18n.LangMap{
|
||||||
|
// "en-US": map[string]interface{}{
|
||||||
|
// "hello": "Hello",
|
||||||
|
// },
|
||||||
|
// "el-GR": map[string]interface{}{
|
||||||
|
// "hello": "Γειά",
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// app := iris.New()
|
||||||
|
// [...]
|
||||||
|
// app.I18N.LoadKV(m)
|
||||||
|
// app.I18N.SetDefault("en-US")
|
||||||
|
func KV(langMap LangMap, opts ...LoaderConfig) Loader {
|
||||||
|
return func(m *Matcher) (Localizer, error) {
|
||||||
|
options := DefaultLoaderConfig
|
||||||
|
if len(opts) > 0 {
|
||||||
|
options = opts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
languageIndexes := make([]int, 0, len(langMap))
|
||||||
|
keyValuesMulti := make([]map[string]interface{}, 0, len(langMap))
|
||||||
|
|
||||||
|
for languageName, pairs := range langMap {
|
||||||
|
langIndex := parseLanguageName(m, languageName) // matches and adds the language tag to m.Languages.
|
||||||
|
languageIndexes = append(languageIndexes, langIndex)
|
||||||
|
keyValuesMulti = append(keyValuesMulti, pairs)
|
||||||
|
}
|
||||||
|
|
||||||
|
cat, err := internal.NewCatalog(m.Languages, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, langIndex := range languageIndexes {
|
||||||
|
if langIndex == -1 {
|
||||||
|
// If loader has more languages than defined for use in New function,
|
||||||
|
// e.g. when New(KV(m), "en-US") contains el-GR and en-US but only "en-US" passed.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
kv := keyValuesMulti[langIndex]
|
||||||
|
err := cat.Store(langIndex, kv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n := len(cat.Locales); n == 0 {
|
||||||
|
return nil, fmt.Errorf("locales not found in map")
|
||||||
|
} else if options.Strict && n < len(m.Languages) {
|
||||||
|
return nil, fmt.Errorf("locales expected to be %d but %d parsed", len(m.Languages), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cat, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultLoaderConfig represents the default loader configuration.
|
// DefaultLoaderConfig represents the default loader configuration.
|
||||||
var DefaultLoaderConfig = LoaderConfig{
|
var DefaultLoaderConfig = LoaderConfig{
|
||||||
Left: "{{",
|
Left: "{{",
|
||||||
|
@ -88,7 +152,7 @@ var DefaultLoaderConfig = LoaderConfig{
|
||||||
// and any Loader options.
|
// and any Loader options.
|
||||||
// It returns a valid `Loader` which loads and maps the locale files.
|
// It returns a valid `Loader` which loads and maps the locale files.
|
||||||
//
|
//
|
||||||
// See `Glob`, `Assets` and `LoaderConfig` too.
|
// See `FS`, `Glob`, `Assets` and `LoaderConfig` too.
|
||||||
func load(assetNames []string, asset func(string) ([]byte, error), options LoaderConfig) Loader {
|
func load(assetNames []string, asset func(string) ([]byte, error), options LoaderConfig) Loader {
|
||||||
return func(m *Matcher) (Localizer, error) {
|
return func(m *Matcher) (Localizer, error) {
|
||||||
languageFiles, err := m.ParseLanguageFiles(assetNames)
|
languageFiles, err := m.ParseLanguageFiles(assetNames)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user