message.go 2.0 KB

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