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]Entry } // FIXME: this should be put into the config file maybe, or detected from a list // of possibilities? const ( I18nFile = "USEng.dta" ) // I18n entries may have 1 or 2 items. If two, the first is a menu item and the // second is a help string for that menu item. // // The text or help may contain some magic strings, as mentioned in USEng.data type Entry struct { Text string Help string } 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]Entry), } 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? if entry, ok := out.mapping[num]; !ok { // first time we've seen this out.mapping[num] = Entry{Text: string(val)} } else { // Second time, the item is help text entry.Help = string(val) out.mapping[num] = entry } } 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) ReplaceText(in int, out *string) { if str, ok := n.mapping[in]; ok { *out = str.Text } } func (n *I18n) ReplaceHelp(in int, out *string) { if str, ok := n.mapping[in]; ok { *out = str.Help } }