message.go (2065B)
1 package internal 2 3 import ( 4 "fmt" 5 "sort" 6 ) 7 8 // Renderer is responsible to render a translation based 9 // on the given "args". 10 type Renderer interface { 11 Render(args ...interface{}) (string, error) 12 } 13 14 // Message is the default Renderer for translation messages. 15 // Holds the variables and the plurals of this key. 16 // Each Locale has its own list of messages. 17 type Message struct { 18 Locale *Locale 19 20 Key string 21 Value string 22 23 Plural bool 24 Plurals []*PluralMessage // plural forms by order. 25 26 Vars []Var 27 } 28 29 // AddPlural adds a plural message to the Plurals list. 30 func (m *Message) AddPlural(form PluralForm, r Renderer) { 31 msg := &PluralMessage{ 32 Form: form, 33 Renderer: r, 34 } 35 36 if len(m.Plurals) == 0 { 37 m.Plural = true 38 m.Plurals = append(m.Plurals, msg) 39 return 40 } 41 42 for i, p := range m.Plurals { 43 if p.Form.String() == form.String() { 44 // replace 45 m.Plurals[i] = msg 46 return 47 } 48 } 49 50 m.Plurals = append(m.Plurals, msg) 51 sort.SliceStable(m.Plurals, func(i, j int) bool { 52 return m.Plurals[i].Form.Less(m.Plurals[j].Form) 53 }) 54 } 55 56 // Render completes the Renderer interface. 57 // It accepts arguments, which can resolve the pluralization type of the message 58 // and its variables. If the Message is wrapped by a Template then the 59 // first argument should be a map. The map key resolves to the pluralization 60 // of the message is the "PluralCount". And for variables the user 61 // should set a message key which looks like: %VAR_NAME%Count, e.g. "DogsCount" 62 // to set plural count for the "Dogs" variable, case-sensitive. 63 func (m *Message) Render(args ...interface{}) (string, error) { 64 if m.Plural { 65 if len(args) > 0 { 66 if pluralCount, ok := findPluralCount(args[0]); ok { 67 for _, plural := range m.Plurals { 68 if plural.Form.MatchPlural(pluralCount) { 69 return plural.Renderer.Render(args...) 70 } 71 } 72 73 return "", fmt.Errorf("key: %q: no registered plurals for <%d>", m.Key, pluralCount) 74 } 75 } 76 77 return "", fmt.Errorf("key: %q: missing plural count argument", m.Key) 78 } 79 80 return m.Locale.Printer.Sprintf(m.Key, args...), nil 81 }