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 .