dyna.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package i18n
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net/http"
  6. "strings"
  7. "github.com/iancoleman/strcase"
  8. "github.com/sunfmin/reflectutils"
  9. )
  10. type kv struct {
  11. key string
  12. val string
  13. }
  14. type moduleMissing struct {
  15. missingKeys []kv
  16. missingVals []kv
  17. }
  18. type DynaBuilder struct {
  19. lang string
  20. missing map[ModuleKey]*moduleMissing
  21. }
  22. func DynaNew() (r *DynaBuilder) {
  23. return &DynaBuilder{
  24. missing: make(map[ModuleKey]*moduleMissing),
  25. }
  26. }
  27. func (d *DynaBuilder) Language(lang string) (r *DynaBuilder) {
  28. d.lang = lang
  29. return d
  30. }
  31. func T(req *http.Request, module ModuleKey, key string, args ...string) (r string) {
  32. return PT(req, module, "", key, args...)
  33. }
  34. func PT(req *http.Request, module ModuleKey, prefix string, key string, args ...string) (r string) {
  35. defaultVal := strings.NewReplacer(args...).Replace(key)
  36. msgr := MustGetModuleMessages(req, module, nil)
  37. if msgr == nil {
  38. return defaultVal
  39. }
  40. var builder *DynaBuilder
  41. b := req.Context().Value(dynaBuilderKey)
  42. if b != nil {
  43. builder = b.(*DynaBuilder)
  44. }
  45. fieldKey := strcase.ToCamel(prefix + " " + key)
  46. val, err := reflectutils.Get(msgr, fieldKey)
  47. if err != nil {
  48. if builder != nil {
  49. builder.putMissingKey(module, fieldKey, key)
  50. }
  51. return defaultVal
  52. }
  53. if val.(string) == "" {
  54. if builder != nil {
  55. builder.putMissingVal(module, fieldKey, key)
  56. }
  57. }
  58. return strings.NewReplacer(args...).Replace(val.(string))
  59. }
  60. func (d *DynaBuilder) putMissingKey(module ModuleKey, key, val string) {
  61. if d.missing[module] == nil {
  62. d.missing[module] = &moduleMissing{}
  63. }
  64. mm := d.missing[module]
  65. for _, ck := range mm.missingKeys {
  66. if ck.key == key {
  67. return
  68. }
  69. }
  70. mm.missingKeys = append(mm.missingKeys, kv{key, val})
  71. }
  72. func (d *DynaBuilder) putMissingVal(module ModuleKey, key, val string) {
  73. if d.missing[module] == nil {
  74. d.missing[module] = &moduleMissing{}
  75. }
  76. mm := d.missing[module]
  77. for _, ck := range mm.missingVals {
  78. if ck.key == key {
  79. return
  80. }
  81. }
  82. mm.missingVals = append(mm.missingVals, kv{key, val})
  83. }
  84. func (d *DynaBuilder) HaveMissingKeys() bool {
  85. return len(d.missing) > 0
  86. }
  87. func (d *DynaBuilder) PrettyMissingKeys() string {
  88. buf := new(bytes.Buffer)
  89. for module, missing := range d.missing {
  90. buf.WriteString(fmt.Sprintf("For module %s, ", module))
  91. buf.WriteString("Missing the following translations\nCopy these to your Messages struct definition\n============================\n\n")
  92. for _, kv := range missing.missingKeys {
  93. _, _ = fmt.Fprintf(buf, "%s string\n", kv.key)
  94. }
  95. buf.WriteString("\n")
  96. buf.WriteString(fmt.Sprintf("Copy these to your Messages struct values for language: `%s`\n\n", d.lang))
  97. for _, kv := range missing.missingKeys {
  98. _, _ = fmt.Fprintf(buf, "%s: %#+v,\n", kv.key, kv.val)
  99. }
  100. for _, kv := range missing.missingVals {
  101. _, _ = fmt.Fprintf(buf, "%s: %#+v,\n", kv.key, kv.val)
  102. }
  103. }
  104. return buf.String()
  105. }