// cmd/geni18n/main.go package main import ( "bufio" "flag" "fmt" "io/fs" "os" "path/filepath" "sort" "strings" "github.com/goccy/go-yaml" ) func main() { dir := flag.String("dir", "./common/i18n/locale", "Locales directory path") out := flag.String("out", "common/i18n/i18nk/keys.go", "Output file path") pkg := flag.String("pkg", "i18nk", "Package name for generated file") flag.Parse() keys := make(map[string]struct{}) err := filepath.WalkDir(*dir, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if d.IsDir() || !(strings.HasSuffix(d.Name(), ".yaml") || strings.HasSuffix(d.Name(), ".yml")) { return nil } data, err := os.ReadFile(path) if err != nil { return err } var content map[string]interface{} if err := yaml.Unmarshal(data, &content); err != nil { return fmt.Errorf("failed to parse yaml %s: %w", path, err) } collectKeys(content, "", keys) return nil }) if err != nil { fmt.Fprintf(os.Stderr, "Error walking directory: %v\n", err) os.Exit(1) } var list []string for k := range keys { list = append(list, k) } sort.Strings(list) f, err := os.Create(*out) if err != nil { fmt.Fprintf(os.Stderr, "Error creating output file: %v\n", err) os.Exit(1) } defer f.Close() w := bufio.NewWriter(f) fmt.Fprintf(w, "// Code generated by cmd/geni18n. DO NOT EDIT.\n") fmt.Fprintf(w, "package %s\n\n", *pkg) fmt.Fprintf(w, "type Key string\n\n") fmt.Fprintf(w, "const (\n") for _, key := range list { name := toPascal(key) fmt.Fprintf(w, "\t%s Key = %q\n", name, key) } fmt.Fprintf(w, ")\n") w.Flush() } func collectKeys(node map[string]interface{}, prefix string, keys map[string]struct{}) { for k, v := range node { fullKey := k if prefix != "" { fullKey = prefix + "." + k } switch val := v.(type) { case map[string]interface{}: collectKeys(val, fullKey, keys) default: keys[fullKey] = struct{}{} } } } // 转 PascalCase func toPascal(key string) string { parts := strings.Split(key, ".") for i, p := range parts { subs := strings.Split(p, "_") for j, s := range subs { if len(s) > 0 { subs[j] = strings.ToUpper(s[:1]) + s[1:] } } parts[i] = strings.Join(subs, "") } return strings.Join(parts, "") }