decred.org/dcrdex@v1.0.3/client/webserver/site/template-builder/main.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "flag" 6 "fmt" 7 "os" 8 "path/filepath" 9 "strings" 10 11 "decred.org/dcrdex/client/intl" 12 "decred.org/dcrdex/client/webserver/locales" 13 "golang.org/x/text/cases" 14 "golang.org/x/text/language" 15 ) 16 17 var ( 18 workingDirectory, _ = os.Getwd() 19 titler cases.Caser 20 ) 21 22 func main() { 23 write := flag.Bool("write", false, "write out translated html templates, otherwise just check (default false)") 24 siteDir := workingDirectory 25 if filepath.Base(workingDirectory) == "template-builder" { 26 siteDir = filepath.Dir(workingDirectory) 27 } 28 29 templateDir := filepath.Join(siteDir, "src", "html") 30 outputDirectory := filepath.Join(siteDir, "src", "localized_html") 31 32 if *write { 33 fmt.Println("Creating output directory:", outputDirectory) 34 err := os.MkdirAll(outputDirectory, 0755) 35 if err != nil { 36 fmt.Printf("MkdirAll %q error: %v \n", outputDirectory, err) 37 os.Exit(1) 38 } 39 40 for lang := range locales.Locales { 41 langDir := filepath.Join(outputDirectory, lang) 42 err := os.MkdirAll(langDir, 0755) 43 if err != nil { 44 fmt.Printf("MkdirAll %q error: %v \n", langDir, err) 45 os.Exit(2) 46 } 47 } 48 } 49 50 err := filepath.Walk(templateDir, func(_ string, fi os.FileInfo, err error) error { 51 if err != nil { 52 return err 53 } 54 if fi.IsDir() { 55 return nil 56 } 57 baseName := fi.Name() 58 if filepath.Ext(baseName) != ".tmpl" { 59 return nil 60 } 61 rawTmplPath := filepath.Join(templateDir, baseName) 62 rawTmpl, err := os.ReadFile(rawTmplPath) 63 if err != nil { 64 return fmt.Errorf("ReadFile error: %w", err) 65 } 66 67 localizedTemplates := make(map[string][]byte, len(locales.Locales)) 68 enDict := locales.Locales["en-US"] 69 70 for lang := range locales.Locales { 71 tmpl := make([]byte, len(rawTmpl)) 72 copy(tmpl, rawTmpl) 73 localizedTemplates[lang] = tmpl 74 } 75 76 for _, matchGroup := range locales.Tokens(rawTmpl) { 77 if len(matchGroup) != 2 { 78 return fmt.Errorf("can't parse match group: %v", matchGroup) 79 } 80 token, key := matchGroup[0], string(matchGroup[1]) 81 for lang, tmpl := range localizedTemplates { 82 titler = cases.Title(language.MustParse(lang)) 83 dict := locales.Locales[lang] 84 85 var toTitle bool 86 var found bool 87 var replacement *intl.Translation 88 if titleKey := strings.TrimPrefix(key, ":title:"); titleKey != key { 89 // Check if there's a value for :title:key. Especially for languages 90 // that do not work well with cases.Caser, e.g zh-cn. 91 if replacement, found = dict[key]; !found { 92 toTitle = true 93 key = titleKey 94 } 95 } 96 97 if !found { 98 if replacement, found = dict[key]; !found { 99 if replacement, found = enDict[key]; !found { 100 return fmt.Errorf("no %s translation in %q and no default replacement for %s", lang, baseName, key) 101 } 102 } 103 } 104 105 if toTitle { 106 replacement.T = titler.String(replacement.T) 107 } 108 109 localizedTemplates[lang] = bytes.Replace(tmpl, token, []byte(replacement.T), -1) // Could just do 1 110 } 111 } 112 113 if *write { 114 for lang, tmpl := range localizedTemplates { 115 langDir := filepath.Join(outputDirectory, lang) 116 localizedName := filepath.Join(langDir, baseName) 117 if err := os.WriteFile(localizedName, tmpl, 0644); err != nil { 118 return fmt.Errorf("error writing localized template %s: %v", localizedName, err) 119 } 120 } 121 } 122 return nil 123 }) 124 if err != nil { 125 fmt.Println("WalkDir error:", err) 126 os.Exit(3) 127 } 128 }