package data import ( "bufio" "bytes" "fmt" "os" "path/filepath" "strconv" ) // WH40K has basic text internationalisation capabilities based on a .dta // file that maps string IDs to messages type I18n struct { Name string mapping map[int]string } // FIXME: this should be put into the config file maybe, or detected from a list // of possibilities? const ( I18nFile = "USEng.dta" ) func LoadI18n(filename string) (*I18n, error) { f, err := os.Open(filename) if err != nil { return nil, err } defer f.Close() out := &I18n{ Name: filepath.Base(filename), mapping: make(map[int]string), } scanner := bufio.NewScanner(f) for i := 0; scanner.Scan(); i++ { // Remove comments from lines line := bytes.TrimSpace(bytes.SplitN(scanner.Bytes(), []byte("//"), 2)[0]) // Ignore empty lines if len(line) == 0 { continue } // Lines are expected to be in this format: // "text that may include \" or not" parts := bytes.SplitN(line, []byte(" "), 2) if len(parts) != 2 { return nil, fmt.Errorf("Bad line in %v at %v: %q", filename, i, scanner.Text()) } num, err := strconv.Atoi(string(parts[0])) if err != nil { return nil, err } // Cut off the leading and trailing quote characters of the string val := parts[1] val = val[1 : len(val)-1] // TODO: Replace certain escape characters with their literals? out.mapping[num] = string(val) } if err := scanner.Err(); err != nil { return nil, err } return out, nil } func (n *I18n) Len() int { return len(n.mapping) } // Puts the internationalized string into `out` if `in` matches a known ID func (n *I18n) Replace(in int, out *string) { if str, ok := n.mapping[in]; ok { *out = str } }