syncthing/script/transifexdl.go

176 lines
3.6 KiB
Go

// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
//go:build ignore
// +build ignore
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"regexp"
"sort"
"strings"
)
type stat struct {
Translated int `json:"translated_entities"`
Untranslated int `json:"untranslated_entities"`
}
type translation struct {
Content string
}
func main() {
log.SetFlags(log.Lshortfile)
if u, p := userPass(); u == "" || p == "" {
log.Fatal("Need environment variables TRANSIFEX_USER and TRANSIFEX_PASS")
}
curValidLangs := map[string]bool{}
for _, lang := range loadValidLangs() {
curValidLangs[lang] = true
}
log.Println(curValidLangs)
resp := req("https://www.transifex.com/api/2/project/syncthing/resource/gui/stats")
var stats map[string]stat
err := json.NewDecoder(resp.Body).Decode(&stats)
if err != nil {
log.Fatal(err)
}
resp.Body.Close()
names := make(map[string]string)
var langs []string
for code, stat := range stats {
code = strings.Replace(code, "_", "-", 1)
pct := 100 * stat.Translated / (stat.Translated + stat.Untranslated)
if pct < 75 || !curValidLangs[code] && pct < 95 {
log.Printf("Skipping language %q (too low completion ratio %d%%)", code, pct)
os.Remove("lang-" + code + ".json")
continue
}
langs = append(langs, code)
names[code] = languageName(code)
if code == "en" {
continue
}
log.Printf("Updating language %q", code)
resp := req("https://www.transifex.com/api/2/project/syncthing/resource/gui/translation/" + code)
var t translation
err := json.NewDecoder(resp.Body).Decode(&t)
if err != nil {
log.Fatal(err)
}
resp.Body.Close()
fd, err := os.Create("lang-" + code + ".json")
if err != nil {
log.Fatal(err)
}
fd.WriteString(t.Content)
fd.Close()
}
saveValidLangs(langs)
saveLanguageNames(names)
}
func saveValidLangs(langs []string) {
sort.Strings(langs)
fd, err := os.Create("valid-langs.js")
if err != nil {
log.Fatal(err)
}
fmt.Fprint(fd, "var validLangs = ")
json.NewEncoder(fd).Encode(langs)
fd.Close()
}
func saveLanguageNames(names map[string]string) {
fd, err := os.Create("prettyprint.js")
if err != nil {
log.Fatal(err)
}
fmt.Fprint(fd, "var langPrettyprint = ")
json.NewEncoder(fd).Encode(names)
fd.Close()
}
func userPass() (string, string) {
user := os.Getenv("TRANSIFEX_USER")
pass := os.Getenv("TRANSIFEX_PASS")
return user, pass
}
func req(url string) *http.Response {
user, pass := userPass()
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Fatal(err)
}
req.SetBasicAuth(user, pass)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
return resp
}
func loadValidLangs() []string {
fd, err := os.Open("valid-langs.js")
if err != nil {
log.Fatal(err)
}
defer fd.Close()
bs, err := io.ReadAll(fd)
if err != nil {
log.Fatal(err)
}
var langs []string
exp := regexp.MustCompile(`\[([a-zA-Z@",-]+)\]`)
if matches := exp.FindSubmatch(bs); len(matches) == 2 {
langs = strings.Split(string(matches[1]), ",")
for i := range langs {
// Remove quotes
langs[i] = langs[i][1 : len(langs[i])-1]
}
}
return langs
}
type languageResponse struct {
Code string
Name string
}
func languageName(code string) string {
var lang languageResponse
resp := req("https://www.transifex.com/api/2/language/" + code)
defer resp.Body.Close()
json.NewDecoder(resp.Body).Decode(&lang)
if lang.Name == "" {
return code
}
return lang.Name
}