summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/nicksnyder/go-i18n/v2/i18n/localizer.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/nicksnyder/go-i18n/v2/i18n/localizer.go')
-rw-r--r--vendor/github.com/nicksnyder/go-i18n/v2/i18n/localizer.go124
1 files changed, 80 insertions, 44 deletions
diff --git a/vendor/github.com/nicksnyder/go-i18n/v2/i18n/localizer.go b/vendor/github.com/nicksnyder/go-i18n/v2/i18n/localizer.go
index f9d516fa6..5d3b0df13 100644
--- a/vendor/github.com/nicksnyder/go-i18n/v2/i18n/localizer.go
+++ b/vendor/github.com/nicksnyder/go-i18n/v2/i18n/localizer.go
@@ -5,7 +5,6 @@ import (
"text/template"
- "github.com/nicksnyder/go-i18n/v2/internal"
"github.com/nicksnyder/go-i18n/v2/internal/plural"
"golang.org/x/text/language"
)
@@ -24,7 +23,6 @@ type Localizer struct {
// in the bundle according to the language preferences in langs.
// It can parse Accept-Language headers as defined in http://www.ietf.org/rfc/rfc2616.txt.
func NewLocalizer(bundle *Bundle, langs ...string) *Localizer {
- bundle.init()
return &Localizer{
bundle: bundle,
tags: parseTags(langs),
@@ -60,7 +58,7 @@ type LocalizeConfig struct {
// DefaultMessage is used if the message is not found in any message files.
DefaultMessage *Message
- // Funcs is used to extend the Go template engines built in functions
+ // Funcs is used to extend the Go template engine's built in functions
Funcs template.FuncMap
}
@@ -74,11 +72,12 @@ func (e *invalidPluralCountErr) Error() string {
return fmt.Sprintf("invalid plural count %#v for message id %q: %s", e.pluralCount, e.messageID, e.err)
}
-type messageNotFoundErr struct {
+// MessageNotFoundErr is returned from Localize when a message could not be found.
+type MessageNotFoundErr struct {
messageID string
}
-func (e *messageNotFoundErr) Error() string {
+func (e *MessageNotFoundErr) Error() string {
return fmt.Sprintf("message %q not found", e.messageID)
}
@@ -91,10 +90,44 @@ func (e *pluralizeErr) Error() string {
return fmt.Sprintf("unable to pluralize %q because there no plural rule for %q", e.messageID, e.tag)
}
+type messageIDMismatchErr struct {
+ messageID string
+ defaultMessageID string
+}
+
+func (e *messageIDMismatchErr) Error() string {
+ return fmt.Sprintf("message id %q does not match default message id %q", e.messageID, e.defaultMessageID)
+}
+
// Localize returns a localized message.
func (l *Localizer) Localize(lc *LocalizeConfig) (string, error) {
+ msg, _, err := l.LocalizeWithTag(lc)
+ return msg, err
+}
+
+// Localize returns a localized message.
+func (l *Localizer) LocalizeMessage(msg *Message) (string, error) {
+ return l.Localize(&LocalizeConfig{
+ DefaultMessage: msg,
+ })
+}
+
+// TODO: uncomment this (and the test) when extract has been updated to extract these call sites too.
+// Localize returns a localized message.
+// func (l *Localizer) LocalizeMessageID(messageID string) (string, error) {
+// return l.Localize(&LocalizeConfig{
+// MessageID: messageID,
+// })
+// }
+
+// LocalizeWithTag returns a localized message and the language tag.
+// It may return a best effort localized message even if an error happens.
+func (l *Localizer) LocalizeWithTag(lc *LocalizeConfig) (string, language.Tag, error) {
messageID := lc.MessageID
if lc.DefaultMessage != nil {
+ if messageID != "" && messageID != lc.DefaultMessage.ID {
+ return "", language.Und, &messageIDMismatchErr{messageID: messageID, defaultMessageID: lc.DefaultMessage.ID}
+ }
messageID = lc.DefaultMessage.ID
}
@@ -104,7 +137,7 @@ func (l *Localizer) Localize(lc *LocalizeConfig) (string, error) {
var err error
operands, err = plural.NewOperands(lc.PluralCount)
if err != nil {
- return "", &invalidPluralCountErr{messageID: messageID, pluralCount: lc.PluralCount, err: err}
+ return "", language.Und, &invalidPluralCountErr{messageID: messageID, pluralCount: lc.PluralCount, err: err}
}
if templateData == nil {
templateData = map[string]interface{}{
@@ -112,68 +145,71 @@ func (l *Localizer) Localize(lc *LocalizeConfig) (string, error) {
}
}
}
+
tag, template := l.getTemplate(messageID, lc.DefaultMessage)
if template == nil {
- return "", &messageNotFoundErr{messageID: messageID}
+ return "", language.Und, &MessageNotFoundErr{messageID: messageID}
}
+
pluralForm := l.pluralForm(tag, operands)
if pluralForm == plural.Invalid {
- return "", &pluralizeErr{messageID: messageID, tag: tag}
+ return "", language.Und, &pluralizeErr{messageID: messageID, tag: tag}
+ }
+
+ msg, err := template.Execute(pluralForm, templateData, lc.Funcs)
+ if err != nil {
+ // Attempt to fallback to "Other" pluralization in case translations are incomplete.
+ if pluralForm != plural.Other {
+ msg2, err2 := template.Execute(plural.Other, templateData, lc.Funcs)
+ if err2 == nil {
+ return msg2, tag, err
+ }
+ }
+ return "", language.Und, err
}
- return template.Execute(pluralForm, templateData, lc.Funcs)
+ return msg, tag, nil
}
-func (l *Localizer) getTemplate(id string, defaultMessage *Message) (language.Tag, *internal.MessageTemplate) {
+func (l *Localizer) getTemplate(id string, defaultMessage *Message) (language.Tag, *MessageTemplate) {
// Fast path.
// Optimistically assume this message id is defined in each language.
- fastTag, template := l.matchTemplate(id, l.bundle.matcher, l.bundle.tags)
+ fastTag, template := l.matchTemplate(id, defaultMessage, l.bundle.matcher, l.bundle.tags)
if template != nil {
return fastTag, template
}
- if fastTag == l.bundle.DefaultLanguage {
- if defaultMessage == nil {
- return fastTag, nil
- }
- return fastTag, internal.NewMessageTemplate(defaultMessage)
+
+ if len(l.bundle.tags) <= 1 {
+ return l.bundle.defaultLanguage, nil
}
- if len(l.bundle.tags) > 1 {
- // Slow path.
- // We didn't find a translation for the tag suggested by the default matcher
- // so we need to create a new matcher that contains only the tags in the bundle
- // that have this message.
- foundTags := make([]language.Tag, 0, len(l.bundle.messageTemplates))
- if l.bundle.DefaultLanguage != fastTag {
- foundTags = append(foundTags, l.bundle.DefaultLanguage)
- }
- for t, templates := range l.bundle.messageTemplates {
- if t == fastTag {
- // We already tried this tag in the fast path
- continue
- }
- template := templates[id]
- if template == nil || template.Other == "" {
- continue
- }
- foundTags = append(foundTags, t)
- }
- tag, template := l.matchTemplate(id, language.NewMatcher(foundTags), foundTags)
- if template != nil {
- return tag, template
+
+ // Slow path.
+ // We didn't find a translation for the tag suggested by the default matcher
+ // so we need to create a new matcher that contains only the tags in the bundle
+ // that have this message.
+ foundTags := make([]language.Tag, 0, len(l.bundle.messageTemplates)+1)
+ foundTags = append(foundTags, l.bundle.defaultLanguage)
+
+ for t, templates := range l.bundle.messageTemplates {
+ template := templates[id]
+ if template == nil || template.Other == "" {
+ continue
}
+ foundTags = append(foundTags, t)
}
- if defaultMessage == nil {
- return l.bundle.DefaultLanguage, nil
- }
- return l.bundle.DefaultLanguage, internal.NewMessageTemplate(defaultMessage)
+
+ return l.matchTemplate(id, defaultMessage, language.NewMatcher(foundTags), foundTags)
}
-func (l *Localizer) matchTemplate(id string, matcher language.Matcher, tags []language.Tag) (language.Tag, *internal.MessageTemplate) {
+func (l *Localizer) matchTemplate(id string, defaultMessage *Message, matcher language.Matcher, tags []language.Tag) (language.Tag, *MessageTemplate) {
_, i, _ := matcher.Match(l.tags...)
tag := tags[i]
templates := l.bundle.messageTemplates[tag]
if templates != nil && templates[id] != nil {
return tag, templates[id]
}
+ if tag == l.bundle.defaultLanguage && defaultMessage != nil {
+ return tag, NewMessageTemplate(defaultMessage)
+ }
return tag, nil
}