mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
i18n: respect fallback language when Strict is false and no DefaultMessageFunc was provided
This commit is contained in:
parent
5b983800ec
commit
5017e3c986
|
@ -1254,14 +1254,8 @@ func (ctx *Context) GetLocale() Locale {
|
|||
// See `GetLocale` too.
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/i18n
|
||||
func (ctx *Context) Tr(message string, values ...interface{}) string {
|
||||
if locale := ctx.GetLocale(); locale != nil {
|
||||
return locale.GetMessageContext(ctx, message, values...)
|
||||
}
|
||||
|
||||
// This should never happen as the locale fallbacks to
|
||||
// the default.
|
||||
return message
|
||||
func (ctx *Context) Tr(key string, args ...interface{}) string {
|
||||
return ctx.app.I18nReadOnly().TrContext(ctx, key, args...)
|
||||
}
|
||||
|
||||
// +------------------------------------------------------------+
|
||||
|
|
|
@ -7,7 +7,8 @@ import "golang.org/x/text/language"
|
|||
type I18nReadOnly interface {
|
||||
Tags() []language.Tag
|
||||
GetLocale(ctx *Context) Locale
|
||||
Tr(lang string, format string, args ...interface{}) string
|
||||
Tr(lang string, key string, args ...interface{}) string
|
||||
TrContext(ctx *Context, key string, args ...interface{}) string
|
||||
}
|
||||
|
||||
// Locale is the interface which returns from a `Localizer.GetLocale` method.
|
||||
|
@ -25,10 +26,4 @@ type Locale interface {
|
|||
Language() string
|
||||
// GetMessage should return translated text based on the given "key".
|
||||
GetMessage(key string, args ...interface{}) string
|
||||
// GetMessageContext same as GetMessage
|
||||
// but it accepts the Context as its first input.
|
||||
// If DefaultMessageFunc was not nil then this Context
|
||||
// will provide the real language input instead of the locale's which
|
||||
// may be the default language one.
|
||||
GetMessageContext(ctx *Context, key string, args ...interface{}) string
|
||||
}
|
||||
|
|
71
i18n/i18n.go
71
i18n/i18n.go
|
@ -79,8 +79,11 @@ type I18n struct {
|
|||
//
|
||||
// Defaults to true.
|
||||
Subdomain bool
|
||||
// If true then it will return empty string when translation for a a specific language's key was not found.
|
||||
// If a DefaultMessageFunc is NOT set:
|
||||
// If true then it will return empty string when translation for a
|
||||
// specific language's key was not found.
|
||||
// Defaults to false, fallback defaultLang:key will be used.
|
||||
// Otherwise, DefaultMessageFunc is called in either case.
|
||||
Strict bool
|
||||
|
||||
// If true then Iris will wrap its router with the i18n router wrapper on its Build state.
|
||||
|
@ -96,6 +99,8 @@ var _ context.I18nReadOnly = (*I18n)(nil)
|
|||
|
||||
// makeTags converts language codes to language Tags.
|
||||
func makeTags(languages ...string) (tags []language.Tag) {
|
||||
languages = removeDuplicates(languages)
|
||||
|
||||
for _, lang := range languages {
|
||||
tag, err := language.Parse(lang)
|
||||
if err == nil && tag != language.Und {
|
||||
|
@ -324,31 +329,43 @@ func (i *I18n) TryMatchString(s string) (language.Tag, int, bool) {
|
|||
}
|
||||
|
||||
// Tr returns a translated message based on the "lang" language code
|
||||
// and its key(format) with any optional arguments attached to it.
|
||||
// and its key with any optional arguments attached to it.
|
||||
//
|
||||
// It returns an empty string if "lang" not matched, unless DefaultMessageFunc.
|
||||
// It returns the default language's translation if "key" not matched, unless DefaultMessageFunc.
|
||||
func (i *I18n) Tr(lang, format string, args ...interface{}) (msg string) {
|
||||
func (i *I18n) Tr(lang, key string, args ...interface{}) string {
|
||||
_, index, ok := i.TryMatchString(lang)
|
||||
if !ok {
|
||||
index = 0
|
||||
}
|
||||
loc := i.localizer.GetLocale(index)
|
||||
return i.getLocaleMessage(loc, lang, key, args...)
|
||||
}
|
||||
|
||||
// TrContext returns the localized text message for this Context.
|
||||
// It returns an empty string if context's locale not matched, unless DefaultMessageFunc.
|
||||
// It returns the default language's translation if "key" not matched, unless DefaultMessageFunc.
|
||||
func (i *I18n) TrContext(ctx *context.Context, key string, args ...interface{}) string {
|
||||
loc := ctx.GetLocale()
|
||||
langInput := ctx.Values().GetString(ctx.Application().ConfigurationReadOnly().GetLanguageInputContextKey())
|
||||
return i.getLocaleMessage(loc, langInput, key, args...)
|
||||
}
|
||||
|
||||
func (i *I18n) getLocaleMessage(loc context.Locale, langInput string, key string, args ...interface{}) (msg string) {
|
||||
langMatched := ""
|
||||
|
||||
loc := i.localizer.GetLocale(index)
|
||||
if loc != nil {
|
||||
langMatched = loc.Language()
|
||||
|
||||
msg = loc.GetMessage(format, args...)
|
||||
if msg == "" && i.DefaultMessageFunc == nil && !i.Strict && index > 0 {
|
||||
msg = loc.GetMessage(key, args...)
|
||||
if msg == "" && i.DefaultMessageFunc == nil && !i.Strict && loc.Index() > 0 {
|
||||
// it's not the default/fallback language and not message found for that lang:key.
|
||||
msg = i.localizer.GetLocale(0).GetMessage(format, args...)
|
||||
msg = i.localizer.GetLocale(0).GetMessage(key, args...)
|
||||
}
|
||||
}
|
||||
|
||||
if msg == "" && i.DefaultMessageFunc != nil {
|
||||
msg = i.DefaultMessageFunc(lang, langMatched, format, args)
|
||||
msg = i.DefaultMessageFunc(langInput, langMatched, key, args)
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -447,30 +464,6 @@ func (i *I18n) GetLocale(ctx *context.Context) context.Locale {
|
|||
return locale
|
||||
}
|
||||
|
||||
// GetMessage returns the localized text message for this "r" request based on the key "format".
|
||||
// It returns an empty string if context's locale not matched, unless DefaultMessageFunc.
|
||||
// It returns the default language's translation if "key" not matched, unless DefaultMessageFunc.
|
||||
func (i *I18n) GetMessage(ctx *context.Context, format string, args ...interface{}) (msg string) {
|
||||
loc := i.GetLocale(ctx)
|
||||
langMatched := ""
|
||||
if loc != nil {
|
||||
langMatched = loc.Language()
|
||||
// it's not the default/fallback language and not message found for that lang:key.
|
||||
msg = loc.GetMessage(format, args...)
|
||||
if msg == "" && i.DefaultMessageFunc == nil && !i.Strict && loc.Index() > 0 {
|
||||
return i.localizer.GetLocale(0).GetMessage(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
if msg == "" && i.DefaultMessageFunc != nil {
|
||||
langInput := ctx.Values().GetString(ctx.Application().ConfigurationReadOnly().GetLanguageInputContextKey())
|
||||
|
||||
msg = i.DefaultMessageFunc(langInput, langMatched, format, args...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (i *I18n) setLangWithoutContext(w http.ResponseWriter, r *http.Request, lang string) {
|
||||
if i.Cookie != "" {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
|
@ -541,3 +534,17 @@ func (i *I18n) Wrapper() router.WrapperFunc {
|
|||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func removeDuplicates(elements []string) (result []string) {
|
||||
seen := make(map[string]struct{})
|
||||
|
||||
for v := range elements {
|
||||
val := elements[v]
|
||||
if _, ok := seen[val]; !ok {
|
||||
seen[val] = struct{}{}
|
||||
result = append(result, val)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -163,20 +163,6 @@ func (loc *Locale) Language() string {
|
|||
|
||||
// GetMessage should return translated text based on the given "key".
|
||||
func (loc *Locale) GetMessage(key string, args ...interface{}) string {
|
||||
return loc.getMessage(loc.ID, key, args...)
|
||||
}
|
||||
|
||||
// GetMessageContext same as GetMessage
|
||||
// but it accepts the Context as its first input.
|
||||
// If DefaultMessageFunc was not nil then this Context
|
||||
// will provide the real language input instead of the locale's which
|
||||
// may be the default language one.
|
||||
func (loc *Locale) GetMessageContext(ctx *context.Context, key string, args ...interface{}) string {
|
||||
langInput := ctx.Values().GetString(ctx.Application().ConfigurationReadOnly().GetLanguageInputContextKey())
|
||||
return loc.getMessage(langInput, key, args...)
|
||||
}
|
||||
|
||||
func (loc *Locale) getMessage(langInput, key string, args ...interface{}) string {
|
||||
if msg, ok := loc.Messages[key]; ok {
|
||||
result, err := msg.Render(args...)
|
||||
if err != nil {
|
||||
|
@ -186,10 +172,5 @@ func (loc *Locale) getMessage(langInput, key string, args ...interface{}) string
|
|||
return result
|
||||
}
|
||||
|
||||
if fn := loc.Options.DefaultMessageFunc; fn != nil {
|
||||
// let langInput to be empty if that's the case.
|
||||
return fn(langInput, loc.ID, key, args...)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user