/cmd/transifexdl/main.go

https://gitlab.com/Blueprint-Marketing/syncthing · Go · 143 lines · 115 code · 23 blank · 5 comment · 30 complexity · c13a113eda2a58d43e4b1d615c0477f9 MD5 · raw file

  1. // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. // All rights reserved. Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. // +build ignore
  5. package main
  6. import (
  7. "encoding/json"
  8. "fmt"
  9. "io/ioutil"
  10. "log"
  11. "net/http"
  12. "os"
  13. "regexp"
  14. "sort"
  15. "strings"
  16. )
  17. type stat struct {
  18. Translated int `json:"translated_entities"`
  19. Untranslated int `json:"untranslated_entities"`
  20. }
  21. type translation struct {
  22. Content string
  23. }
  24. func main() {
  25. log.SetFlags(log.Lshortfile)
  26. if u, p := userPass(); u == "" || p == "" {
  27. log.Fatal("Need environment variables TRANSIFEX_USER and TRANSIFEX_PASS")
  28. }
  29. curValidLangs := map[string]bool{}
  30. for _, lang := range loadValidLangs() {
  31. curValidLangs[lang] = true
  32. }
  33. log.Println(curValidLangs)
  34. resp := req("https://www.transifex.com/api/2/project/syncthing/resource/gui/stats")
  35. var stats map[string]stat
  36. err := json.NewDecoder(resp.Body).Decode(&stats)
  37. if err != nil {
  38. log.Fatal(err)
  39. }
  40. resp.Body.Close()
  41. var langs []string
  42. for code, stat := range stats {
  43. code = strings.Replace(code, "_", "-", 1)
  44. if !curValidLangs[code] {
  45. if pct := 100 * stat.Translated / (stat.Translated + stat.Untranslated); pct < 95 {
  46. log.Printf("Skipping language %q (too low completion ratio %d%%)", code, pct)
  47. os.Remove("lang-" + code + ".json")
  48. continue
  49. }
  50. }
  51. langs = append(langs, code)
  52. if code == "en" {
  53. continue
  54. }
  55. log.Printf("Updating language %q", code)
  56. resp := req("https://www.transifex.com/api/2/project/syncthing/resource/gui/translation/" + code)
  57. var t translation
  58. err := json.NewDecoder(resp.Body).Decode(&t)
  59. if err != nil {
  60. log.Fatal(err)
  61. }
  62. resp.Body.Close()
  63. fd, err := os.Create("lang-" + code + ".json")
  64. if err != nil {
  65. log.Fatal(err)
  66. }
  67. fd.WriteString(t.Content)
  68. fd.Close()
  69. }
  70. saveValidLangs(langs)
  71. }
  72. func saveValidLangs(langs []string) {
  73. sort.Strings(langs)
  74. fd, err := os.Create("valid-langs.js")
  75. if err != nil {
  76. log.Fatal(err)
  77. }
  78. fmt.Fprint(fd, "var validLangs = ")
  79. json.NewEncoder(fd).Encode(langs)
  80. fd.Close()
  81. }
  82. func userPass() (string, string) {
  83. user := os.Getenv("TRANSIFEX_USER")
  84. pass := os.Getenv("TRANSIFEX_PASS")
  85. return user, pass
  86. }
  87. func req(url string) *http.Response {
  88. user, pass := userPass()
  89. req, err := http.NewRequest("GET", url, nil)
  90. if err != nil {
  91. log.Fatal(err)
  92. }
  93. req.SetBasicAuth(user, pass)
  94. resp, err := http.DefaultClient.Do(req)
  95. if err != nil {
  96. log.Fatal(err)
  97. }
  98. return resp
  99. }
  100. func loadValidLangs() []string {
  101. fd, err := os.Open("valid-langs.js")
  102. if err != nil {
  103. log.Fatal(err)
  104. }
  105. defer fd.Close()
  106. bs, err := ioutil.ReadAll(fd)
  107. if err != nil {
  108. log.Fatal(err)
  109. }
  110. var langs []string
  111. exp := regexp.MustCompile(`\[([a-zA-Z",-]+)\]`)
  112. if matches := exp.FindSubmatch(bs); len(matches) == 2 {
  113. langs = strings.Split(string(matches[1]), ",")
  114. for i := range langs {
  115. // Remove quotes
  116. langs[i] = langs[i][1 : len(langs[i])-1]
  117. }
  118. }
  119. return langs
  120. }