diff options
Diffstat (limited to 'vendor/github.com/nicksnyder/go-i18n/v2/internal/parse.go')
-rw-r--r-- | vendor/github.com/nicksnyder/go-i18n/v2/internal/parse.go | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/vendor/github.com/nicksnyder/go-i18n/v2/internal/parse.go b/vendor/github.com/nicksnyder/go-i18n/v2/internal/parse.go new file mode 100644 index 000000000..a5cee87c6 --- /dev/null +++ b/vendor/github.com/nicksnyder/go-i18n/v2/internal/parse.go @@ -0,0 +1,112 @@ +package internal + +import ( + "encoding/json" + "fmt" + "os" + + "golang.org/x/text/language" +) + +// UnmarshalFunc unmarshals data into v. +type UnmarshalFunc func(data []byte, v interface{}) error + +// MessageFile represents a parsed message file. +type MessageFile struct { + Path string + Tag language.Tag + Format string + Messages []*Message +} + +// ParseMessageFileBytes returns the messages parsed from file. +func ParseMessageFileBytes(buf []byte, path string, unmarshalFuncs map[string]UnmarshalFunc) (*MessageFile, error) { + lang, format := parsePath(path) + tag := language.Make(lang) + messageFile := &MessageFile{ + Path: path, + Tag: tag, + Format: format, + } + if len(buf) == 0 { + return messageFile, nil + } + unmarshalFunc := unmarshalFuncs[messageFile.Format] + if unmarshalFunc == nil { + if messageFile.Format == "json" { + unmarshalFunc = json.Unmarshal + } else { + return nil, fmt.Errorf("no unmarshaler registered for %s", messageFile.Format) + } + } + var raw interface{} + if err := unmarshalFunc(buf, &raw); err != nil { + return nil, err + } + switch data := raw.(type) { + case map[string]interface{}: + messageFile.Messages = make([]*Message, 0, len(data)) + for id, data := range data { + m, err := NewMessage(data) + if err != nil { + return nil, err + } + m.ID = id + messageFile.Messages = append(messageFile.Messages, m) + } + case map[interface{}]interface{}: + messageFile.Messages = make([]*Message, 0, len(data)) + for id, data := range data { + strid, ok := id.(string) + if !ok { + return nil, fmt.Errorf("expected key to be string but got %#v", id) + } + m, err := NewMessage(data) + if err != nil { + return nil, err + } + m.ID = strid + messageFile.Messages = append(messageFile.Messages, m) + } + case []interface{}: + // Backward compatibility for v1 file format. + messageFile.Messages = make([]*Message, 0, len(data)) + for _, data := range data { + m, err := NewMessage(data) + if err != nil { + return nil, err + } + messageFile.Messages = append(messageFile.Messages, m) + } + default: + return nil, fmt.Errorf("unsupported file format %T", raw) + } + return messageFile, nil +} + +func parsePath(path string) (langTag, format string) { + formatStartIdx := -1 + for i := len(path) - 1; i >= 0; i-- { + c := path[i] + if os.IsPathSeparator(c) { + if formatStartIdx != -1 { + langTag = path[i+1 : formatStartIdx] + } + return + } + if path[i] == '.' { + if formatStartIdx != -1 { + langTag = path[i+1 : formatStartIdx] + return + } + if formatStartIdx == -1 { + format = path[i+1:] + formatStartIdx = i + } + } + } + if formatStartIdx != -1 { + langTag = path[:formatStartIdx] + } + return +} |