75 lines
1.7 KiB
Go
75 lines
1.7 KiB
Go
package language
|
|
|
|
import "strings"
|
|
|
|
// PluralSpec defines the CLDR plural rules for a language.
|
|
// http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
|
|
// http://unicode.org/reports/tr35/tr35-numbers.html#Operands
|
|
type PluralSpec struct {
|
|
Plurals map[Plural]struct{}
|
|
PluralFunc func(*operands) Plural
|
|
}
|
|
|
|
var pluralSpecs = make(map[string]*PluralSpec)
|
|
|
|
func normalizePluralSpecID(id string) string {
|
|
id = strings.Replace(id, "_", "-", -1)
|
|
id = strings.ToLower(id)
|
|
return id
|
|
}
|
|
|
|
func registerPluralSpec(ids []string, ps *PluralSpec) {
|
|
for _, id := range ids {
|
|
id = normalizePluralSpecID(id)
|
|
pluralSpecs[id] = ps
|
|
}
|
|
}
|
|
|
|
// Plural returns the plural category for number as defined by
|
|
// the language's CLDR plural rules.
|
|
func (ps *PluralSpec) Plural(number interface{}) (Plural, error) {
|
|
ops, err := newOperands(number)
|
|
if err != nil {
|
|
return Invalid, err
|
|
}
|
|
return ps.PluralFunc(ops), nil
|
|
}
|
|
|
|
// getPluralSpec returns the PluralSpec that matches the longest prefix of tag.
|
|
// It returns nil if no PluralSpec matches tag.
|
|
func getPluralSpec(tag string) *PluralSpec {
|
|
tag = NormalizeTag(tag)
|
|
subtag := tag
|
|
for {
|
|
if spec := pluralSpecs[subtag]; spec != nil {
|
|
return spec
|
|
}
|
|
end := strings.LastIndex(subtag, "-")
|
|
if end == -1 {
|
|
return nil
|
|
}
|
|
subtag = subtag[:end]
|
|
}
|
|
}
|
|
|
|
func newPluralSet(plurals ...Plural) map[Plural]struct{} {
|
|
set := make(map[Plural]struct{}, len(plurals))
|
|
for _, plural := range plurals {
|
|
set[plural] = struct{}{}
|
|
}
|
|
return set
|
|
}
|
|
|
|
func intInRange(i, from, to int64) bool {
|
|
return from <= i && i <= to
|
|
}
|
|
|
|
func intEqualsAny(i int64, any ...int64) bool {
|
|
for _, a := range any {
|
|
if i == a {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|