113 lines
2.2 KiB
Go
113 lines
2.2 KiB
Go
|
package locale
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type po struct {
|
||
|
Headers map[string]string
|
||
|
Translations map[string]string
|
||
|
}
|
||
|
|
||
|
// A minimal .po file parser.
|
||
|
func parse(s *bufio.Scanner) *po {
|
||
|
p := &po{
|
||
|
Headers: make(map[string]string, 20),
|
||
|
Translations: make(map[string]string, 500),
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
currentNothing = iota
|
||
|
currentMsgID
|
||
|
currentMsgString
|
||
|
)
|
||
|
var current byte
|
||
|
var currentID string
|
||
|
var currentString string
|
||
|
|
||
|
for s.Scan() {
|
||
|
line := strings.TrimSpace(s.Text())
|
||
|
|
||
|
if line == "" || line[0] == '#' {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
switch {
|
||
|
case strings.HasPrefix(line, "msgid "):
|
||
|
unq, err := strconv.Unquote(strings.TrimSpace(strings.TrimPrefix(line, "msgid")))
|
||
|
if err != nil {
|
||
|
fmt.Println(line)
|
||
|
fmt.Println(err)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
if current != currentNothing && currentID == "" && currentString != "" {
|
||
|
for _, h := range strings.Split(currentString, "\n") {
|
||
|
if h == "" {
|
||
|
continue
|
||
|
}
|
||
|
parts := strings.SplitN(h, ": ", 2)
|
||
|
if len(parts) != 2 {
|
||
|
continue
|
||
|
}
|
||
|
p.Headers[parts[0]] = parts[1]
|
||
|
}
|
||
|
} else {
|
||
|
p.Translations[currentID] = currentString
|
||
|
}
|
||
|
|
||
|
currentID = unq
|
||
|
current = currentMsgID
|
||
|
case strings.HasPrefix(line, "msgstr "):
|
||
|
unq, err := strconv.Unquote(strings.TrimSpace(strings.TrimPrefix(line, "msgstr")))
|
||
|
if err != nil {
|
||
|
fmt.Println(line)
|
||
|
fmt.Println(err)
|
||
|
return nil
|
||
|
}
|
||
|
currentString = unq
|
||
|
current = currentMsgString
|
||
|
case strings.HasPrefix(line, "msgid_plural "), strings.HasPrefix(line, "msgstr["):
|
||
|
// We currently don't support plural in the Go parser, at least hold it off 'til it's needed.
|
||
|
current = currentNothing
|
||
|
default:
|
||
|
if current == currentNothing {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
unq, err := strconv.Unquote(strings.TrimSpace(line))
|
||
|
if err != nil {
|
||
|
fmt.Println(line)
|
||
|
fmt.Println(err)
|
||
|
return nil
|
||
|
}
|
||
|
switch current {
|
||
|
case currentMsgID:
|
||
|
currentID += unq
|
||
|
case currentMsgString:
|
||
|
currentString += unq
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if current == currentMsgString {
|
||
|
p.Translations[currentID] = currentString
|
||
|
}
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
func parseFile(fName string) (*po, error) {
|
||
|
f, err := os.Open(fName)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer f.Close()
|
||
|
s := bufio.NewScanner(f)
|
||
|
p := parse(s)
|
||
|
return p, nil
|
||
|
}
|