plural_rules.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. package flect
  2. var pluralRules = []rule{}
  3. // AddPlural adds a rule that will replace the given suffix with the replacement suffix.
  4. func AddPlural(suffix string, repl string) {
  5. pluralMoot.Lock()
  6. defer pluralMoot.Unlock()
  7. pluralRules = append(pluralRules, rule{
  8. suffix: suffix,
  9. fn: func(s string) string {
  10. s = s[:len(s)-len(suffix)]
  11. return s + repl
  12. },
  13. })
  14. pluralRules = append(pluralRules, rule{
  15. suffix: repl,
  16. fn: noop,
  17. })
  18. }
  19. var singleToPlural = map[string]string{
  20. "aircraft": "aircraft",
  21. "alias": "aliases",
  22. "alumna": "alumnae",
  23. "alumnus": "alumni",
  24. "analysis": "analyses",
  25. "antenna": "antennas",
  26. "antithesis": "antitheses",
  27. "apex": "apexes",
  28. "appendix": "appendices",
  29. "axis": "axes",
  30. "bacillus": "bacilli",
  31. "bacterium": "bacteria",
  32. "basis": "bases",
  33. "beau": "beaus",
  34. "bison": "bison",
  35. "bureau": "bureaus",
  36. "bus": "buses",
  37. "campus": "campuses",
  38. "caucus": "caucuses",
  39. "child": "children",
  40. "château": "châteaux",
  41. "circus": "circuses",
  42. "codex": "codices",
  43. "concerto": "concertos",
  44. "corpus": "corpora",
  45. "crisis": "crises",
  46. "curriculum": "curriculums",
  47. "datum": "data",
  48. "deer": "deer",
  49. "diagnosis": "diagnoses",
  50. "die": "dice",
  51. "dwarf": "dwarves",
  52. "ellipsis": "ellipses",
  53. "equipment": "equipment",
  54. "erratum": "errata",
  55. "faux pas": "faux pas",
  56. "fez": "fezzes",
  57. "fish": "fish",
  58. "focus": "foci",
  59. "foo": "foos",
  60. "foot": "feet",
  61. "formula": "formulas",
  62. "fungus": "fungi",
  63. "genus": "genera",
  64. "goose": "geese",
  65. "graffito": "graffiti",
  66. "grouse": "grouse",
  67. "half": "halves",
  68. "halo": "halos",
  69. "hoof": "hooves",
  70. "human": "humans",
  71. "hypothesis": "hypotheses",
  72. "index": "indices",
  73. "information": "information",
  74. "jeans": "jeans",
  75. "larva": "larvae",
  76. "libretto": "librettos",
  77. "loaf": "loaves",
  78. "locus": "loci",
  79. "louse": "lice",
  80. "matrix": "matrices",
  81. "minutia": "minutiae",
  82. "money": "money",
  83. "moose": "moose",
  84. "mouse": "mice",
  85. "nebula": "nebulae",
  86. "news": "news",
  87. "nucleus": "nuclei",
  88. "oasis": "oases",
  89. "octopus": "octopi",
  90. "offspring": "offspring",
  91. "opus": "opera",
  92. "ovum": "ova",
  93. "ox": "oxen",
  94. "parenthesis": "parentheses",
  95. "phenomenon": "phenomena",
  96. "photo": "photos",
  97. "phylum": "phyla",
  98. "piano": "pianos",
  99. "plus": "pluses",
  100. "police": "police",
  101. "prognosis": "prognoses",
  102. "prometheus": "prometheuses",
  103. "quiz": "quizzes",
  104. "quota": "quotas",
  105. "radius": "radiuses",
  106. "referendum": "referendums",
  107. "ress": "resses",
  108. "rice": "rice",
  109. "salmon": "salmon",
  110. "sex": "sexes",
  111. "series": "series",
  112. "sheep": "sheep",
  113. "shoe": "shoes",
  114. "shrimp": "shrimp",
  115. "species": "species",
  116. "stimulus": "stimuli",
  117. "stratum": "strata",
  118. "swine": "swine",
  119. "syllabus": "syllabi",
  120. "symposium": "symposiums",
  121. "synapse": "synapses",
  122. "synopsis": "synopses",
  123. "tableau": "tableaus",
  124. "testis": "testes",
  125. "thesis": "theses",
  126. "thief": "thieves",
  127. "tooth": "teeth",
  128. "trout": "trout",
  129. "tuna": "tuna",
  130. "vedalia": "vedalias",
  131. "vertebra": "vertebrae",
  132. "vertix": "vertices",
  133. "vita": "vitae",
  134. "vortex": "vortices",
  135. "wharf": "wharves",
  136. "wife": "wives",
  137. "woman": "women",
  138. "wolf": "wolves",
  139. "you": "you",
  140. }
  141. var pluralToSingle = map[string]string{}
  142. func init() {
  143. for k, v := range singleToPlural {
  144. pluralToSingle[v] = k
  145. }
  146. }
  147. type singularToPluralSuffix struct {
  148. singular string
  149. plural string
  150. }
  151. var singularToPluralSuffixList = []singularToPluralSuffix{
  152. {"iterion", "iteria"},
  153. {"campus", "campuses"},
  154. {"genera", "genus"},
  155. {"person", "people"},
  156. {"phylum", "phyla"},
  157. {"randum", "randa"},
  158. {"actus", "acti"},
  159. {"adium", "adia"},
  160. {"basis", "basis"},
  161. {"child", "children"},
  162. {"chive", "chives"},
  163. {"focus", "foci"},
  164. {"hello", "hellos"},
  165. {"jeans", "jeans"},
  166. {"louse", "lice"},
  167. {"media", "media"},
  168. {"mouse", "mice"},
  169. {"movie", "movies"},
  170. {"oasis", "oasis"},
  171. {"atum", "ata"},
  172. {"atus", "atuses"},
  173. {"base", "bases"},
  174. {"cess", "cesses"},
  175. {"dium", "diums"},
  176. {"eses", "esis"},
  177. {"half", "halves"},
  178. {"hive", "hives"},
  179. {"iano", "ianos"},
  180. {"irus", "iri"},
  181. {"isis", "ises"},
  182. {"leus", "li"},
  183. {"mnus", "mni"},
  184. {"move", "moves"},
  185. {"news", "news"},
  186. {"odex", "odice"},
  187. {"oose", "eese"},
  188. {"ouse", "ouses"},
  189. {"ovum", "ova"},
  190. {"rion", "ria"},
  191. {"shoe", "shoes"},
  192. {"stis", "stes"},
  193. {"tive", "tives"},
  194. {"wife", "wives"},
  195. {"afe", "aves"},
  196. {"bfe", "bves"},
  197. {"box", "boxes"},
  198. {"cfe", "cves"},
  199. {"dfe", "dves"},
  200. {"dge", "dges"},
  201. {"efe", "eves"},
  202. {"gfe", "gves"},
  203. {"hfe", "hves"},
  204. {"ife", "ives"},
  205. {"itz", "itzes"},
  206. {"ium", "ia"},
  207. {"ize", "izes"},
  208. {"jfe", "jves"},
  209. {"kfe", "kves"},
  210. {"man", "men"},
  211. {"mfe", "mves"},
  212. {"nfe", "nves"},
  213. {"nna", "nnas"},
  214. {"oaf", "oaves"},
  215. {"oci", "ocus"},
  216. {"ode", "odes"},
  217. {"ofe", "oves"},
  218. {"oot", "eet"},
  219. {"pfe", "pves"},
  220. {"pse", "psis"},
  221. {"qfe", "qves"},
  222. {"quy", "quies"},
  223. {"rfe", "rves"},
  224. {"sfe", "sves"},
  225. {"tfe", "tves"},
  226. {"tum", "ta"},
  227. {"tus", "tuses"},
  228. {"ufe", "uves"},
  229. {"ula", "ulae"},
  230. {"ula", "ulas"},
  231. {"uli", "ulus"},
  232. {"use", "uses"},
  233. {"uss", "usses"},
  234. {"vfe", "vves"},
  235. {"wfe", "wves"},
  236. {"xfe", "xves"},
  237. {"yfe", "yves"},
  238. {"you", "you"},
  239. {"zfe", "zves"},
  240. {"by", "bies"},
  241. {"ch", "ches"},
  242. {"cy", "cies"},
  243. {"dy", "dies"},
  244. {"ex", "ices"},
  245. {"fy", "fies"},
  246. {"gy", "gies"},
  247. {"hy", "hies"},
  248. {"io", "ios"},
  249. {"jy", "jies"},
  250. {"ky", "kies"},
  251. {"lf", "lves"},
  252. {"ly", "lies"},
  253. {"my", "mies"},
  254. {"ny", "nies"},
  255. {"py", "pies"},
  256. {"qy", "qies"},
  257. {"rf", "rves"},
  258. {"ry", "ries"},
  259. {"sh", "shes"},
  260. {"ss", "sses"},
  261. {"sy", "sies"},
  262. {"ty", "ties"},
  263. {"tz", "tzes"},
  264. {"va", "vae"},
  265. {"vy", "vies"},
  266. {"wy", "wies"},
  267. {"xy", "xies"},
  268. {"zy", "zies"},
  269. {"zz", "zzes"},
  270. {"o", "oes"},
  271. {"x", "xes"},
  272. }
  273. func init() {
  274. for _, suffix := range singularToPluralSuffixList {
  275. AddPlural(suffix.singular, suffix.plural)
  276. AddSingular(suffix.plural, suffix.singular)
  277. }
  278. }