package  inflection 
 
import  ( 
	"regexp"  
	"strings"  
) 
 
type  inflection struct  { 
	regexp  *regexp .Regexp  
	replace string  
} 
 
 
type  Regular  struct  { 
	find    string  
	replace string  
} 
 
 
 
type  Irregular  struct  { 
	singular string  
	plural   string  
} 
 
 
type  RegularSlice  []Regular  
 
 
type  IrregularSlice  []Irregular  
 
var  pluralInflections = RegularSlice { 
	{"([a-z])$" , "${1}s" }, 
	{"s$" , "s" }, 
	{"^(ax|test)is$" , "${1}es" }, 
	{"(octop|vir)us$" , "${1}i" }, 
	{"(octop|vir)i$" , "${1}i" }, 
	{"(alias|status)$" , "${1}es" }, 
	{"(bu)s$" , "${1}ses" }, 
	{"(buffal|tomat)o$" , "${1}oes" }, 
	{"([ti])um$" , "${1}a" }, 
	{"([ti])a$" , "${1}a" }, 
	{"sis$" , "ses" }, 
	{"(?:([^f])fe|([lr])f)$" , "${1}${2}ves" }, 
	{"(hive)$" , "${1}s" }, 
	{"([^aeiouy]|qu)y$" , "${1}ies" }, 
	{"(x|ch|ss|sh)$" , "${1}es" }, 
	{"(matr|vert|ind)(?:ix|ex)$" , "${1}ices" }, 
	{"^(m|l)ouse$" , "${1}ice" }, 
	{"^(m|l)ice$" , "${1}ice" }, 
	{"^(ox)$" , "${1}en" }, 
	{"^(oxen)$" , "${1}" }, 
	{"(quiz)$" , "${1}zes" }, 
} 
 
var  singularInflections = RegularSlice { 
	{"s$" , "" }, 
	{"(ss)$" , "${1}" }, 
	{"(n)ews$" , "${1}ews" }, 
	{"([ti])a$" , "${1}um" }, 
	{"((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$" , "${1}sis" }, 
	{"(^analy)(sis|ses)$" , "${1}sis" }, 
	{"([^f])ves$" , "${1}fe" }, 
	{"(hive)s$" , "${1}" }, 
	{"(tive)s$" , "${1}" }, 
	{"([lr])ves$" , "${1}f" }, 
	{"([^aeiouy]|qu)ies$" , "${1}y" }, 
	{"(s)eries$" , "${1}eries" }, 
	{"(m)ovies$" , "${1}ovie" }, 
	{"(c)ookies$" , "${1}ookie" }, 
	{"(x|ch|ss|sh)es$" , "${1}" }, 
	{"^(m|l)ice$" , "${1}ouse" }, 
	{"(bus)(es)?$" , "${1}" }, 
	{"(o)es$" , "${1}" }, 
	{"(shoe)s$" , "${1}" }, 
	{"(cris|test)(is|es)$" , "${1}is" }, 
	{"^(a)x[ie]s$" , "${1}xis" }, 
	{"(octop|vir)(us|i)$" , "${1}us" }, 
	{"(alias|status)(es)?$" , "${1}" }, 
	{"^(ox)en" , "${1}" }, 
	{"(vert|ind)ices$" , "${1}ex" }, 
	{"(matr)ices$" , "${1}ix" }, 
	{"(quiz)zes$" , "${1}" }, 
	{"(database)s$" , "${1}" }, 
} 
 
var  irregularInflections = IrregularSlice { 
	{"person" , "people" }, 
	{"man" , "men" }, 
	{"child" , "children" }, 
	{"sex" , "sexes" }, 
	{"move" , "moves" }, 
	{"mombie" , "mombies" }, 
} 
 
var  uncountableInflections = []string {"equipment" , "information" , "rice" , "money" , "species" , "series" , "fish" , "sheep" , "jeans" , "police" } 
 
var  compiledPluralMaps []inflection  
var  compiledSingularMaps []inflection  
 
func  compile() { 
	compiledPluralMaps  = []inflection {} 
	compiledSingularMaps  = []inflection {} 
	for  _ , uncountable  := range  uncountableInflections  { 
		inf  := inflection { 
			regexp :  regexp .MustCompile ("^(?i)("  + uncountable  + ")$" ), 
			replace : "${1}" , 
		} 
		compiledPluralMaps  = append (compiledPluralMaps , inf ) 
		compiledSingularMaps  = append (compiledSingularMaps , inf ) 
	} 
 
	for  _ , value  := range  irregularInflections  { 
		infs  := []inflection { 
			inflection {regexp : regexp .MustCompile (strings .ToUpper (value .singular ) + "$" ), replace : strings .ToUpper (value .plural )}, 
			inflection {regexp : regexp .MustCompile (strings .Title (value .singular ) + "$" ), replace : strings .Title (value .plural )}, 
			inflection {regexp : regexp .MustCompile (value .singular  + "$" ), replace : value .plural }, 
		} 
		compiledPluralMaps  = append (compiledPluralMaps , infs ...) 
	} 
 
	for  _ , value  := range  irregularInflections  { 
		infs  := []inflection { 
			inflection {regexp : regexp .MustCompile (strings .ToUpper (value .plural ) + "$" ), replace : strings .ToUpper (value .singular )}, 
			inflection {regexp : regexp .MustCompile (strings .Title (value .plural ) + "$" ), replace : strings .Title (value .singular )}, 
			inflection {regexp : regexp .MustCompile (value .plural  + "$" ), replace : value .singular }, 
		} 
		compiledSingularMaps  = append (compiledSingularMaps , infs ...) 
	} 
 
	for  i  := len (pluralInflections ) - 1 ; i  >= 0 ; i -- { 
		value  := pluralInflections [i ] 
		infs  := []inflection { 
			inflection {regexp : regexp .MustCompile (strings .ToUpper (value .find )), replace : strings .ToUpper (value .replace )}, 
			inflection {regexp : regexp .MustCompile (value .find ), replace : value .replace }, 
			inflection {regexp : regexp .MustCompile ("(?i)"  + value .find ), replace : value .replace }, 
		} 
		compiledPluralMaps  = append (compiledPluralMaps , infs ...) 
	} 
 
	for  i  := len (singularInflections ) - 1 ; i  >= 0 ; i -- { 
		value  := singularInflections [i ] 
		infs  := []inflection { 
			inflection {regexp : regexp .MustCompile (strings .ToUpper (value .find )), replace : strings .ToUpper (value .replace )}, 
			inflection {regexp : regexp .MustCompile (value .find ), replace : value .replace }, 
			inflection {regexp : regexp .MustCompile ("(?i)"  + value .find ), replace : value .replace }, 
		} 
		compiledSingularMaps  = append (compiledSingularMaps , infs ...) 
	} 
} 
 
func  init() { 
	compile () 
} 
 
 
func  AddPlural  (find , replace  string ) { 
	pluralInflections  = append (pluralInflections , Regular {find , replace }) 
	compile () 
} 
 
 
func  AddSingular  (find , replace  string ) { 
	singularInflections  = append (singularInflections , Regular {find , replace }) 
	compile () 
} 
 
 
func  AddIrregular  (singular , plural  string ) { 
	irregularInflections  = append (irregularInflections , Irregular {singular , plural }) 
	compile () 
} 
 
 
func  AddUncountable  (values  ...string ) { 
	uncountableInflections  = append (uncountableInflections , values ...) 
	compile () 
} 
 
 
func  GetPlural  () RegularSlice  { 
	plurals  := make (RegularSlice , len (pluralInflections )) 
	copy (plurals , pluralInflections ) 
	return  plurals  
} 
 
 
func  GetSingular  () RegularSlice  { 
	singulars  := make (RegularSlice , len (singularInflections )) 
	copy (singulars , singularInflections ) 
	return  singulars  
} 
 
 
func  GetIrregular  () IrregularSlice  { 
	irregular  := make (IrregularSlice , len (irregularInflections )) 
	copy (irregular , irregularInflections ) 
	return  irregular  
} 
 
 
func  GetUncountable  () []string  { 
	uncountables  := make ([]string , len (uncountableInflections )) 
	copy (uncountables , uncountableInflections ) 
	return  uncountables  
} 
 
 
func  SetPlural  (inflections  RegularSlice ) { 
	pluralInflections  = inflections  
	compile () 
} 
 
 
func  SetSingular  (inflections  RegularSlice ) { 
	singularInflections  = inflections  
	compile () 
} 
 
 
func  SetIrregular  (inflections  IrregularSlice ) { 
	irregularInflections  = inflections  
	compile () 
} 
 
 
func  SetUncountable  (inflections  []string ) { 
	uncountableInflections  = inflections  
	compile () 
} 
 
 
func  Plural  (str  string ) string  { 
	for  _ , inflection  := range  compiledPluralMaps  { 
		if  inflection .regexp .MatchString (str ) { 
			return  inflection .regexp .ReplaceAllString (str , inflection .replace ) 
		} 
	} 
	return  str  
} 
 
 
func  Singular  (str  string ) string  { 
	for  _ , inflection  := range  compiledSingularMaps  { 
		if  inflection .regexp .MatchString (str ) { 
			return  inflection .regexp .ReplaceAllString (str , inflection .replace ) 
		} 
	} 
	return  str  
} 
  
The pages are generated with Golds   v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds  is a Go 101  project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1  (reachable from the left QR code) to get the latest news of Golds .