package main import "errors" type ResourceId uint16 type Translator struct { values map[ResourceId]string } func NewTranslator() *Translator { return &Translator{ values: make(map[ResourceId]string), } } func (t *Translator) addString(res ResourceId, val string) { t.values[res] = val if _, ok := t.values[(res & 255)]; !ok { t.values[(res & 255)] = val } } func (t *Translator) getString(res ResourceId) (string, error) { if v, ok := t.values[res]; ok { return v, nil } // Couldn't pull the exact resource, try the basic one if v, ok := t.values[(res & 255)]; ok { return v, nil } return "", errors.New("String Resource Not Found") } const ( ResStrListChanged ResourceId = iota ResStrTaskListNotLoaded ResStrDoneListNotLoaded ResStrInvalidRefreshRequest ResModeCLI ResourceId = 1 << (iota + 9) ResModeUI ) func (a *AppState) initLanguage() { a.lang = NewTranslator() // Strings that are the same regardless of mode a.lang.addString((ResStrTaskListNotLoaded), "Task list hasn't been loaded") a.lang.addString((ResStrDoneListNotLoaded), "Done list hasn't been loaded") // CLI Strings a.lang.addString((ResStrListChanged | ResModeCLI), "List changed somewhere else") // UI Strings a.lang.addString((ResStrListChanged | ResModeUI), "List changed somewhere else, reload and try again (Ctrl+R)") } // s returns a string with the given stringId // (per the constants above) func (a *AppState) s(stringId ResourceId) string { if stringId&255 != stringId { // the attribute already has extended data in it. if v, err := a.lang.getString(stringId); err == nil { return v } return "" } if v, err := a.lang.getString((stringId | a.mode)); err == nil { return v } return "" } // e is basically the same as 's', but returns // the string in an error object func (a *AppState) e(stringId ResourceId) error { return errors.New(a.s(stringId)) }