formatEntityName converts a PascalCase entity name to lowercase words and optionally pluralizes it. Consecutive uppercase letters (acronyms like API) are kept together as a single word. e.g. "MessageSendSchedule" → "message send schedules", "PhoneAPIKey" → "phone API keys"
(name string, plural bool)
| 114 | // Consecutive uppercase letters (acronyms like API) are kept together as a single word. |
| 115 | // e.g. "MessageSendSchedule" → "message send schedules", "PhoneAPIKey" → "phone API keys" |
| 116 | func formatEntityName(name string, plural bool) string { |
| 117 | var words []string |
| 118 | runes := []rune(name) |
| 119 | start := 0 |
| 120 | for i := 1; i < len(runes); i++ { |
| 121 | if unicode.IsUpper(runes[i]) { |
| 122 | if !unicode.IsUpper(runes[i-1]) { |
| 123 | // transition from lowercase to uppercase: split before i |
| 124 | words = append(words, string(runes[start:i])) |
| 125 | start = i |
| 126 | } else if i+1 < len(runes) && unicode.IsLower(runes[i+1]) { |
| 127 | // transition from uppercase run to a new word (e.g., "API" followed by "Key") |
| 128 | words = append(words, string(runes[start:i])) |
| 129 | start = i |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | words = append(words, string(runes[start:])) |
| 134 | |
| 135 | for i, word := range words { |
| 136 | if word == strings.ToUpper(word) && len(word) > 1 { |
| 137 | // keep acronyms uppercase (e.g., "API") |
| 138 | continue |
| 139 | } |
| 140 | words[i] = strings.ToLower(word) |
| 141 | } |
| 142 | |
| 143 | if plural && len(words) > 0 { |
| 144 | client := pluralize.NewClient() |
| 145 | words[len(words)-1] = client.Plural(words[len(words)-1]) |
| 146 | } |
| 147 | |
| 148 | return strings.Join(words, " ") |
| 149 | } |