Added basic i18n

This commit is contained in:
2026-03-10 15:18:34 +08:00
parent 093a8745ac
commit 7d1de5f781
25 changed files with 660 additions and 105 deletions

3
cmd/compilei18n/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module chatgpt.com/c/tools/compliei18n
go 1.25.0

121
cmd/compilei18n/main.go Normal file
View File

@@ -0,0 +1,121 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
"sort"
"strconv"
)
func main() {
const goFile = "i18n/messages.go"
const outFile = "resources/src/messages.json"
keys, err := extractStringConsts(goFile)
if err != nil {
panic(err)
}
existing := map[string]string{}
if data, err := os.ReadFile(outFile); err == nil {
if len(bytes.TrimSpace(data)) > 0 {
if err := json.Unmarshal(data, &existing); err != nil {
panic(fmt.Errorf("parse %s: %w", outFile, err))
}
}
} else if !os.IsNotExist(err) {
panic(err)
}
merged := map[string]string{}
for _, key := range keys {
if val, ok := existing[key]; ok {
merged[key] = val
} else {
merged[key] = "TODO: " + key
}
}
// Detect stale keys.
for key := range existing {
found := false
for _, k := range keys {
if k == key {
found = true
break
}
}
if !found {
fmt.Fprintf(os.Stderr, "stale key in %s: %s\n", outFile, key)
}
}
// Write stable sorted JSON.
sorted := make([]string, 0, len(merged))
for k := range merged {
sorted = append(sorted, k)
}
sort.Strings(sorted)
buf := &bytes.Buffer{}
buf.WriteString("{\n")
for i, k := range sorted {
kj, _ := json.Marshal(k)
vj, _ := json.Marshal(merged[k])
comma := ","
if i == len(sorted)-1 {
comma = ""
}
fmt.Fprintf(buf, " %s: %s%s\n", kj, vj, comma)
}
buf.WriteString("}\n")
if err := os.WriteFile(outFile, buf.Bytes(), 0644); err != nil {
panic(err)
}
}
func extractStringConsts(path string) ([]string, error) {
fset := token.NewFileSet()
file, err := parser.ParseFile(fset, path, nil, 0)
if err != nil {
return nil, err
}
var keys []string
for _, decl := range file.Decls {
gen, ok := decl.(*ast.GenDecl)
if !ok || gen.Tok != token.CONST {
continue
}
for _, spec := range gen.Specs {
vs, ok := spec.(*ast.ValueSpec)
if !ok {
continue
}
for _, value := range vs.Values {
lit, ok := value.(*ast.BasicLit)
if !ok || lit.Kind != token.STRING {
continue
}
s, err := strconv.Unquote(lit.Value)
if err != nil {
return nil, err
}
keys = append(keys, s)
}
}
}
sort.Strings(keys)
return keys, nil
}

9
cmd/po-build.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
RES_ROOT=./resources
# Primary language
cp -r "$RES_ROOT/src" "$RES_ROOT/langpacks/en"
# zh-Hant
po2json -t "$RES_ROOT/src/" "$RES_ROOT/po/zh-Hant" "$RES_ROOT/langpacks/zh-Hant"

7
cmd/po-export.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
RES_ROOT=./resources
./cmd/compilei18n/compliei18n
json2po -P "$RES_ROOT/src/" "$RES_ROOT/pot/"
pot2po -t "$RES_ROOT/po/zh-Hant" "$RES_ROOT/pot" "$RES_ROOT/po/zh-Hant"