code: func recGetMessages(raw interface{}, isMapMessage, isInitialCall bool) ([]*Message, error) {
  	var messages []*Message
  	var err error
  
  	switch data := raw.(type) {
  	case string:
  		if isInitialCall {
  			return nil, errInvalidTranslationFile
  		}
  		m, err := NewMessage(data)
  		return []*Message{m}, err
  
  	case map[string]interface{}:
  		if isMapMessage {
  			m, err := NewMessage(data)
  			return []*Message{m}, err
  		}
  		messages = make([]*Message, 0, len(data))
  		for id, data := range data {
  			// recursively scan map items
  			messages, err = addChildMessages(id, data, messages)
  			if err != nil {
  				return nil, err
  			}
  		}
  
  	case map[interface{}]interface{}:
  		if isMapMessage {
  			m, err := NewMessage(data)
  			return []*Message{m}, err
  		}
  		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)
  			}
  			// recursively scan map items
  			messages, err = addChildMessages(strid, data, messages)
  			if err != nil {
  				return nil, err
  			}
  		}
  
  	case []interface{}:
  		// Backward compatibility for v1 file format.
  		messages = make([]*Message, 0, len(data))
  		for _, data := range data {
  			// recursively scan slice items
  			childMessages, err := recGetMessages(data, isMessage(data), false)
  			if err != nil {
  				return nil, err
  			}
  			messages = append(messages, childMessages...)
  		}
  
  	default:
  		return nil, fmt.Errorf("unsupported file format %T", raw)
  	}
  
  	return messages, nil
  }
docs: // recGetMessages looks for translation messages inside "raw" parameter,
  // scanning nested maps using recursion.