main.go (5168B)
1 package main 2 3 import ( 4 "context" 5 "flag" 6 "fmt" 7 "os" 8 "path" 9 "strings" 10 11 fsdb "git.defalsify.org/vise.git/db/fs" 12 "git.defalsify.org/vise.git/debug" 13 "git.defalsify.org/vise.git/lang" 14 "git.defalsify.org/vise.git/logging" 15 "git.defalsify.org/vise.git/resource" 16 ) 17 18 var ( 19 logg = logging.NewVanilla() 20 ) 21 22 type translator struct { 23 langs []lang.Language 24 haveLang map[string]bool 25 ctx context.Context 26 rs *resource.PoResource 27 outPath string 28 madePath bool 29 } 30 31 func newTranslator(ctx context.Context, defaultLanguage lang.Language, inPath string, outPath string) *translator { 32 tr := &translator{ 33 langs: []lang.Language{defaultLanguage}, 34 haveLang: make(map[string]bool), 35 ctx: ctx, 36 rs: resource.NewPoResource(defaultLanguage, inPath), 37 outPath: outPath, 38 } 39 tr.haveLang[defaultLanguage.Code] = true 40 return tr 41 } 42 43 func (tr *translator) AddLang(ln lang.Language) error { 44 var ok bool 45 _, ok = tr.haveLang[ln.Code] 46 if !ok { 47 tr.langs = append(tr.langs, ln) 48 tr.rs = tr.rs.WithLanguage(ln) 49 tr.haveLang[ln.Code] = true 50 } 51 return nil 52 } 53 54 func (tr *translator) nodeFunc(node *debug.Node) error { 55 sym := node.Name 56 for i, ln := range tr.langs { 57 ctx := context.WithValue(tr.ctx, "Language", ln) 58 s, err := tr.rs.GetTemplate(ctx, sym) 59 if err != nil { 60 logg.DebugCtxf(ctx, "template not found", "sym", s) 61 continue 62 } 63 if s != sym { 64 if !tr.madePath { 65 err := os.MkdirAll(tr.outPath, 0700) 66 if err != nil { 67 return err 68 } 69 } 70 fb := sym 71 if i > 0 { 72 fb += "_" + ln.Code 73 } 74 fp := path.Join(tr.outPath, fb) 75 w, err := os.OpenFile(fp, os.O_WRONLY|os.O_CREATE, 0644) 76 if err != nil { 77 return err 78 } 79 c, err := w.Write([]byte(s)) 80 defer w.Close() 81 if err != nil { 82 return err 83 } 84 logg.DebugCtxf(ctx, "wrote node", "sym", sym, "lang", ln.Code, "bytes", c) 85 } 86 } 87 return nil 88 } 89 90 func (tr *translator) menuFunc(sym string) error { 91 for i, ln := range tr.langs { 92 ctx := context.WithValue(tr.ctx, "Language", ln) 93 s, err := tr.rs.GetMenu(ctx, sym) 94 if err != nil { 95 logg.DebugCtxf(ctx, "menu not found", "sym", s) 96 continue 97 } 98 if s != sym { 99 if !tr.madePath { 100 err := os.MkdirAll(tr.outPath, 0700) 101 if err != nil { 102 return err 103 } 104 } 105 // TODO: use menu sym generator func instead 106 fb := sym + "_menu" 107 if i > 0 { 108 fb += "_" + ln.Code 109 } 110 // TODO: use lang filename generator func instead 111 fp := path.Join(tr.outPath, fb) 112 w, err := os.OpenFile(fp, os.O_WRONLY|os.O_CREATE, 0644) 113 if err != nil { 114 return err 115 } 116 c, err := w.Write([]byte(s)) 117 defer w.Close() 118 if err != nil { 119 return err 120 } 121 logg.DebugCtxf(ctx, "wrote menu", "sym", sym, "lang", ln.Code, "bytes", c) 122 } 123 } 124 return nil 125 } 126 127 func (tr *translator) Close() error { 128 return nil 129 } 130 131 type langVar struct { 132 v []lang.Language 133 } 134 135 func (lv *langVar) Set(s string) error { 136 v, err := lang.LanguageFromCode(s) 137 if err != nil { 138 return err 139 } 140 lv.v = append(lv.v, v) 141 return err 142 } 143 144 func (lv *langVar) String() string { 145 var s []string 146 for _, v := range lv.v { 147 s = append(s, v.Code) 148 } 149 return strings.Join(s, ",") 150 } 151 152 func (lv *langVar) Langs() []lang.Language { 153 return lv.v 154 } 155 156 func main() { 157 var dir string 158 var inDir string 159 var outDir string 160 var root string 161 var langs langVar 162 var defaultLanguage string 163 164 flag.StringVar(&dir, "d", ".", "node resource dir to read from") 165 flag.StringVar(&inDir, "i", "", "gettext dir") 166 flag.StringVar(&outDir, "o", "locale", "output directory") 167 flag.StringVar(&root, "root", "root", "entry point symbol") 168 flag.Var(&langs, "l", "process for language") 169 flag.StringVar(&defaultLanguage, "defaultlanguage", "eng", "default language to resolve for") 170 flag.Parse() 171 172 fmt.Fprintf(os.Stderr, "starting session at symbol '%s' using resource dir: %s\n", root, dir) 173 174 err := os.MkdirAll(outDir, 0700) 175 if err != nil { 176 fmt.Fprintf(os.Stderr, "output dir create error: %v", err) 177 os.Exit(1) 178 } 179 180 ctx := context.Background() 181 rsStore := fsdb.NewFsDb() 182 err = rsStore.Connect(ctx, dir) 183 if err != nil { 184 fmt.Fprintf(os.Stderr, "resource db connect error: %v", err) 185 os.Exit(1) 186 } 187 188 rs := resource.NewDbResource(rsStore) 189 190 ln, err := lang.LanguageFromCode(defaultLanguage) 191 if err != nil { 192 fmt.Fprintf(os.Stderr, "invalid default language: %v", err) 193 os.Exit(1) 194 } 195 tr := newTranslator(ctx, ln, inDir, outDir) 196 defer tr.Close() 197 for _, ln := range langs.Langs() { 198 logg.DebugCtxf(ctx, "lang", "lang", ln) 199 err = tr.AddLang(ln) 200 if err != nil { 201 fmt.Fprintf(os.Stderr, "add language failed for %s: %v", ln.Code, err) 202 os.Exit(1) 203 } 204 } 205 206 nm := debug.NewNodeMap(root) 207 err = nm.Run(ctx, rs) 208 if err != nil { 209 fmt.Fprintf(os.Stderr, "node tree process fail: %v", err) 210 os.Exit(1) 211 } 212 213 for k, v := range debug.NodeIndex { 214 logg.Tracef("processing node", "sym", k) 215 err = tr.nodeFunc(&v) 216 if err != nil { 217 fmt.Fprintf(os.Stderr, "translate process error for node %s: %v", k, err) 218 os.Exit(1) 219 } 220 } 221 222 for k, _ := range debug.MenuIndex { 223 logg.Tracef("processing menu", "sym", k) 224 err = tr.menuFunc(k) 225 if err != nil { 226 fmt.Fprintf(os.Stderr, "translate process error for menu %s: %v", k, err) 227 os.Exit(1) 228 } 229 } 230 231 }