summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/nicksnyder/go-i18n/i18n/language
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/nicksnyder/go-i18n/i18n/language')
-rw-r--r--vendor/github.com/nicksnyder/go-i18n/i18n/language/language.go99
-rw-r--r--vendor/github.com/nicksnyder/go-i18n/i18n/language/operands.go119
-rw-r--r--vendor/github.com/nicksnyder/go-i18n/i18n/language/plural.go40
-rw-r--r--vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec.go74
-rw-r--r--vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen.go567
5 files changed, 899 insertions, 0 deletions
diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/language/language.go b/vendor/github.com/nicksnyder/go-i18n/i18n/language/language.go
new file mode 100644
index 000000000..9a155efc5
--- /dev/null
+++ b/vendor/github.com/nicksnyder/go-i18n/i18n/language/language.go
@@ -0,0 +1,99 @@
+// Package language defines languages that implement CLDR pluralization.
+package language
+
+import (
+ "fmt"
+ "strings"
+)
+
+// Language is a written human language.
+type Language struct {
+ // Tag uniquely identifies the language as defined by RFC 5646.
+ //
+ // Most language tags are a two character language code (ISO 639-1)
+ // optionally followed by a dash and a two character country code (ISO 3166-1).
+ // (e.g. en, pt-br)
+ Tag string
+ *PluralSpec
+}
+
+func (l *Language) String() string {
+ return l.Tag
+}
+
+// MatchingTags returns the set of language tags that map to this Language.
+// e.g. "zh-hans-cn" yields {"zh", "zh-hans", "zh-hans-cn"}
+// BUG: This should be computed once and stored as a field on Language for efficiency,
+// but this would require changing how Languages are constructed.
+func (l *Language) MatchingTags() []string {
+ parts := strings.Split(l.Tag, "-")
+ var prefix, matches []string
+ for _, part := range parts {
+ prefix = append(prefix, part)
+ match := strings.Join(prefix, "-")
+ matches = append(matches, match)
+ }
+ return matches
+}
+
+// Parse returns a slice of supported languages found in src or nil if none are found.
+// It can parse language tags and Accept-Language headers.
+func Parse(src string) []*Language {
+ var langs []*Language
+ start := 0
+ for end, chr := range src {
+ switch chr {
+ case ',', ';', '.':
+ tag := strings.TrimSpace(src[start:end])
+ if spec := getPluralSpec(tag); spec != nil {
+ langs = append(langs, &Language{NormalizeTag(tag), spec})
+ }
+ start = end + 1
+ }
+ }
+ if start > 0 {
+ tag := strings.TrimSpace(src[start:])
+ if spec := getPluralSpec(tag); spec != nil {
+ langs = append(langs, &Language{NormalizeTag(tag), spec})
+ }
+ return dedupe(langs)
+ }
+ if spec := getPluralSpec(src); spec != nil {
+ langs = append(langs, &Language{NormalizeTag(src), spec})
+ }
+ return langs
+}
+
+func dedupe(langs []*Language) []*Language {
+ found := make(map[string]struct{}, len(langs))
+ deduped := make([]*Language, 0, len(langs))
+ for _, lang := range langs {
+ if _, ok := found[lang.Tag]; !ok {
+ found[lang.Tag] = struct{}{}
+ deduped = append(deduped, lang)
+ }
+ }
+ return deduped
+}
+
+// MustParse is similar to Parse except it panics instead of retuning a nil Language.
+func MustParse(src string) []*Language {
+ langs := Parse(src)
+ if len(langs) == 0 {
+ panic(fmt.Errorf("unable to parse language from %q", src))
+ }
+ return langs
+}
+
+// Add adds support for a new language.
+func Add(l *Language) {
+ tag := NormalizeTag(l.Tag)
+ pluralSpecs[tag] = l.PluralSpec
+}
+
+// NormalizeTag returns a language tag with all lower-case characters
+// and dashes "-" instead of underscores "_"
+func NormalizeTag(tag string) string {
+ tag = strings.ToLower(tag)
+ return strings.Replace(tag, "_", "-", -1)
+}
diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/language/operands.go b/vendor/github.com/nicksnyder/go-i18n/i18n/language/operands.go
new file mode 100644
index 000000000..877bcc89d
--- /dev/null
+++ b/vendor/github.com/nicksnyder/go-i18n/i18n/language/operands.go
@@ -0,0 +1,119 @@
+package language
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+// http://unicode.org/reports/tr35/tr35-numbers.html#Operands
+type operands struct {
+ N float64 // absolute value of the source number (integer and decimals)
+ I int64 // integer digits of n
+ V int64 // number of visible fraction digits in n, with trailing zeros
+ W int64 // number of visible fraction digits in n, without trailing zeros
+ F int64 // visible fractional digits in n, with trailing zeros
+ T int64 // visible fractional digits in n, without trailing zeros
+}
+
+// NmodEqualAny returns true if o represents an integer equal to any of the arguments.
+func (o *operands) NequalsAny(any ...int64) bool {
+ for _, i := range any {
+ if o.I == i && o.T == 0 {
+ return true
+ }
+ }
+ return false
+}
+
+// NmodEqualAny returns true if o represents an integer equal to any of the arguments modulo mod.
+func (o *operands) NmodEqualsAny(mod int64, any ...int64) bool {
+ modI := o.I % mod
+ for _, i := range any {
+ if modI == i && o.T == 0 {
+ return true
+ }
+ }
+ return false
+}
+
+// NmodInRange returns true if o represents an integer in the closed interval [from, to].
+func (o *operands) NinRange(from, to int64) bool {
+ return o.T == 0 && from <= o.I && o.I <= to
+}
+
+// NmodInRange returns true if o represents an integer in the closed interval [from, to] modulo mod.
+func (o *operands) NmodInRange(mod, from, to int64) bool {
+ modI := o.I % mod
+ return o.T == 0 && from <= modI && modI <= to
+}
+
+func newOperands(v interface{}) (*operands, error) {
+ switch v := v.(type) {
+ case int:
+ return newOperandsInt64(int64(v)), nil
+ case int8:
+ return newOperandsInt64(int64(v)), nil
+ case int16:
+ return newOperandsInt64(int64(v)), nil
+ case int32:
+ return newOperandsInt64(int64(v)), nil
+ case int64:
+ return newOperandsInt64(v), nil
+ case string:
+ return newOperandsString(v)
+ case float32, float64:
+ return nil, fmt.Errorf("floats should be formatted into a string")
+ default:
+ return nil, fmt.Errorf("invalid type %T; expected integer or string", v)
+ }
+}
+
+func newOperandsInt64(i int64) *operands {
+ if i < 0 {
+ i = -i
+ }
+ return &operands{float64(i), i, 0, 0, 0, 0}
+}
+
+func newOperandsString(s string) (*operands, error) {
+ if s[0] == '-' {
+ s = s[1:]
+ }
+ n, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return nil, err
+ }
+ ops := &operands{N: n}
+ parts := strings.SplitN(s, ".", 2)
+ ops.I, err = strconv.ParseInt(parts[0], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ if len(parts) == 1 {
+ return ops, nil
+ }
+ fraction := parts[1]
+ ops.V = int64(len(fraction))
+ for i := ops.V - 1; i >= 0; i-- {
+ if fraction[i] != '0' {
+ ops.W = i + 1
+ break
+ }
+ }
+ if ops.V > 0 {
+ f, err := strconv.ParseInt(fraction, 10, 0)
+ if err != nil {
+ return nil, err
+ }
+ ops.F = f
+ }
+ if ops.W > 0 {
+ t, err := strconv.ParseInt(fraction[:ops.W], 10, 0)
+ if err != nil {
+ return nil, err
+ }
+ ops.T = t
+ }
+ return ops, nil
+}
diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/language/plural.go b/vendor/github.com/nicksnyder/go-i18n/i18n/language/plural.go
new file mode 100644
index 000000000..1f3ea5c69
--- /dev/null
+++ b/vendor/github.com/nicksnyder/go-i18n/i18n/language/plural.go
@@ -0,0 +1,40 @@
+package language
+
+import (
+ "fmt"
+)
+
+// Plural represents a language pluralization form as defined here:
+// http://cldr.unicode.org/index/cldr-spec/plural-rules
+type Plural string
+
+// All defined plural categories.
+const (
+ Invalid Plural = "invalid"
+ Zero = "zero"
+ One = "one"
+ Two = "two"
+ Few = "few"
+ Many = "many"
+ Other = "other"
+)
+
+// NewPlural returns src as a Plural
+// or Invalid and a non-nil error if src is not a valid Plural.
+func NewPlural(src string) (Plural, error) {
+ switch src {
+ case "zero":
+ return Zero, nil
+ case "one":
+ return One, nil
+ case "two":
+ return Two, nil
+ case "few":
+ return Few, nil
+ case "many":
+ return Many, nil
+ case "other":
+ return Other, nil
+ }
+ return Invalid, fmt.Errorf("invalid plural category %s", src)
+}
diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec.go b/vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec.go
new file mode 100644
index 000000000..fc3522682
--- /dev/null
+++ b/vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec.go
@@ -0,0 +1,74 @@
+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
+}
diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen.go b/vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen.go
new file mode 100644
index 000000000..c9b4f2667
--- /dev/null
+++ b/vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen.go
@@ -0,0 +1,567 @@
+package language
+
+// This file is generated by i18n/language/codegen/generate.sh
+
+func init() {
+
+ registerPluralSpec([]string{"bm", "bo", "dz", "id", "ig", "ii", "in", "ja", "jbo", "jv", "jw", "kde", "kea", "km", "ko", "lkt", "lo", "ms", "my", "nqo", "root", "sah", "ses", "sg", "th", "to", "vi", "wo", "yo", "zh"}, &PluralSpec{
+ Plurals: newPluralSet(Other),
+ PluralFunc: func(ops *operands) Plural {
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"am", "as", "bn", "fa", "gu", "hi", "kn", "mr", "zu"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // i = 0 or n = 1
+ if intEqualsAny(ops.I, 0) ||
+ ops.NequalsAny(1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"ff", "fr", "hy", "kab"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // i = 0,1
+ if intEqualsAny(ops.I, 0, 1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"ast", "ca", "de", "en", "et", "fi", "fy", "gl", "it", "ji", "nl", "sv", "sw", "ur", "yi"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // i = 1 and v = 0
+ if intEqualsAny(ops.I, 1) && intEqualsAny(ops.V, 0) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"si"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 0,1 or i = 0 and f = 1
+ if ops.NequalsAny(0, 1) ||
+ intEqualsAny(ops.I, 0) && intEqualsAny(ops.F, 1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"ak", "bh", "guw", "ln", "mg", "nso", "pa", "ti", "wa"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 0..1
+ if ops.NinRange(0, 1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"tzm"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 0..1 or n = 11..99
+ if ops.NinRange(0, 1) ||
+ ops.NinRange(11, 99) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"pt"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 0..2 and n != 2
+ if ops.NinRange(0, 2) && !ops.NequalsAny(2) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"af", "asa", "az", "bem", "bez", "bg", "brx", "ce", "cgg", "chr", "ckb", "dv", "ee", "el", "eo", "es", "eu", "fo", "fur", "gsw", "ha", "haw", "hu", "jgo", "jmc", "ka", "kaj", "kcg", "kk", "kkj", "kl", "ks", "ksb", "ku", "ky", "lb", "lg", "mas", "mgo", "ml", "mn", "nah", "nb", "nd", "ne", "nn", "nnh", "no", "nr", "ny", "nyn", "om", "or", "os", "pap", "ps", "rm", "rof", "rwk", "saq", "sdh", "seh", "sn", "so", "sq", "ss", "ssy", "st", "syr", "ta", "te", "teo", "tig", "tk", "tn", "tr", "ts", "ug", "uz", "ve", "vo", "vun", "wae", "xh", "xog"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 1
+ if ops.NequalsAny(1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"pt_PT"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 1 and v = 0
+ if ops.NequalsAny(1) && intEqualsAny(ops.V, 0) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"da"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 1 or t != 0 and i = 0,1
+ if ops.NequalsAny(1) ||
+ !intEqualsAny(ops.T, 0) && intEqualsAny(ops.I, 0, 1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"is"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // t = 0 and i % 10 = 1 and i % 100 != 11 or t != 0
+ if intEqualsAny(ops.T, 0) && intEqualsAny(ops.I%10, 1) && !intEqualsAny(ops.I%100, 11) ||
+ !intEqualsAny(ops.T, 0) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"mk"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // v = 0 and i % 10 = 1 or f % 10 = 1
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%10, 1) ||
+ intEqualsAny(ops.F%10, 1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"fil", "tl"}, &PluralSpec{
+ Plurals: newPluralSet(One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // v = 0 and i = 1,2,3 or v = 0 and i % 10 != 4,6,9 or v != 0 and f % 10 != 4,6,9
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I, 1, 2, 3) ||
+ intEqualsAny(ops.V, 0) && !intEqualsAny(ops.I%10, 4, 6, 9) ||
+ !intEqualsAny(ops.V, 0) && !intEqualsAny(ops.F%10, 4, 6, 9) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"lv", "prg"}, &PluralSpec{
+ Plurals: newPluralSet(Zero, One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19
+ if ops.NmodEqualsAny(10, 0) ||
+ ops.NmodInRange(100, 11, 19) ||
+ intEqualsAny(ops.V, 2) && intInRange(ops.F%100, 11, 19) {
+ return Zero
+ }
+ // n % 10 = 1 and n % 100 != 11 or v = 2 and f % 10 = 1 and f % 100 != 11 or v != 2 and f % 10 = 1
+ if ops.NmodEqualsAny(10, 1) && !ops.NmodEqualsAny(100, 11) ||
+ intEqualsAny(ops.V, 2) && intEqualsAny(ops.F%10, 1) && !intEqualsAny(ops.F%100, 11) ||
+ !intEqualsAny(ops.V, 2) && intEqualsAny(ops.F%10, 1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"lag"}, &PluralSpec{
+ Plurals: newPluralSet(Zero, One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 0
+ if ops.NequalsAny(0) {
+ return Zero
+ }
+ // i = 0,1 and n != 0
+ if intEqualsAny(ops.I, 0, 1) && !ops.NequalsAny(0) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"ksh"}, &PluralSpec{
+ Plurals: newPluralSet(Zero, One, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 0
+ if ops.NequalsAny(0) {
+ return Zero
+ }
+ // n = 1
+ if ops.NequalsAny(1) {
+ return One
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"iu", "kw", "naq", "se", "sma", "smi", "smj", "smn", "sms"}, &PluralSpec{
+ Plurals: newPluralSet(One, Two, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 1
+ if ops.NequalsAny(1) {
+ return One
+ }
+ // n = 2
+ if ops.NequalsAny(2) {
+ return Two
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"shi"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // i = 0 or n = 1
+ if intEqualsAny(ops.I, 0) ||
+ ops.NequalsAny(1) {
+ return One
+ }
+ // n = 2..10
+ if ops.NinRange(2, 10) {
+ return Few
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"mo", "ro"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // i = 1 and v = 0
+ if intEqualsAny(ops.I, 1) && intEqualsAny(ops.V, 0) {
+ return One
+ }
+ // v != 0 or n = 0 or n != 1 and n % 100 = 1..19
+ if !intEqualsAny(ops.V, 0) ||
+ ops.NequalsAny(0) ||
+ !ops.NequalsAny(1) && ops.NmodInRange(100, 1, 19) {
+ return Few
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"bs", "hr", "sh", "sr"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%10, 1) && !intEqualsAny(ops.I%100, 11) ||
+ intEqualsAny(ops.F%10, 1) && !intEqualsAny(ops.F%100, 11) {
+ return One
+ }
+ // v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14
+ if intEqualsAny(ops.V, 0) && intInRange(ops.I%10, 2, 4) && !intInRange(ops.I%100, 12, 14) ||
+ intInRange(ops.F%10, 2, 4) && !intInRange(ops.F%100, 12, 14) {
+ return Few
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"gd"}, &PluralSpec{
+ Plurals: newPluralSet(One, Two, Few, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 1,11
+ if ops.NequalsAny(1, 11) {
+ return One
+ }
+ // n = 2,12
+ if ops.NequalsAny(2, 12) {
+ return Two
+ }
+ // n = 3..10,13..19
+ if ops.NinRange(3, 10) || ops.NinRange(13, 19) {
+ return Few
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"sl"}, &PluralSpec{
+ Plurals: newPluralSet(One, Two, Few, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // v = 0 and i % 100 = 1
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%100, 1) {
+ return One
+ }
+ // v = 0 and i % 100 = 2
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%100, 2) {
+ return Two
+ }
+ // v = 0 and i % 100 = 3..4 or v != 0
+ if intEqualsAny(ops.V, 0) && intInRange(ops.I%100, 3, 4) ||
+ !intEqualsAny(ops.V, 0) {
+ return Few
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"dsb", "hsb"}, &PluralSpec{
+ Plurals: newPluralSet(One, Two, Few, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // v = 0 and i % 100 = 1 or f % 100 = 1
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%100, 1) ||
+ intEqualsAny(ops.F%100, 1) {
+ return One
+ }
+ // v = 0 and i % 100 = 2 or f % 100 = 2
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%100, 2) ||
+ intEqualsAny(ops.F%100, 2) {
+ return Two
+ }
+ // v = 0 and i % 100 = 3..4 or f % 100 = 3..4
+ if intEqualsAny(ops.V, 0) && intInRange(ops.I%100, 3, 4) ||
+ intInRange(ops.F%100, 3, 4) {
+ return Few
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"he", "iw"}, &PluralSpec{
+ Plurals: newPluralSet(One, Two, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // i = 1 and v = 0
+ if intEqualsAny(ops.I, 1) && intEqualsAny(ops.V, 0) {
+ return One
+ }
+ // i = 2 and v = 0
+ if intEqualsAny(ops.I, 2) && intEqualsAny(ops.V, 0) {
+ return Two
+ }
+ // v = 0 and n != 0..10 and n % 10 = 0
+ if intEqualsAny(ops.V, 0) && !ops.NinRange(0, 10) && ops.NmodEqualsAny(10, 0) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"cs", "sk"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // i = 1 and v = 0
+ if intEqualsAny(ops.I, 1) && intEqualsAny(ops.V, 0) {
+ return One
+ }
+ // i = 2..4 and v = 0
+ if intInRange(ops.I, 2, 4) && intEqualsAny(ops.V, 0) {
+ return Few
+ }
+ // v != 0
+ if !intEqualsAny(ops.V, 0) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"pl"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // i = 1 and v = 0
+ if intEqualsAny(ops.I, 1) && intEqualsAny(ops.V, 0) {
+ return One
+ }
+ // v = 0 and i % 10 = 2..4 and i % 100 != 12..14
+ if intEqualsAny(ops.V, 0) && intInRange(ops.I%10, 2, 4) && !intInRange(ops.I%100, 12, 14) {
+ return Few
+ }
+ // v = 0 and i != 1 and i % 10 = 0..1 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 12..14
+ if intEqualsAny(ops.V, 0) && !intEqualsAny(ops.I, 1) && intInRange(ops.I%10, 0, 1) ||
+ intEqualsAny(ops.V, 0) && intInRange(ops.I%10, 5, 9) ||
+ intEqualsAny(ops.V, 0) && intInRange(ops.I%100, 12, 14) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"be"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n % 10 = 1 and n % 100 != 11
+ if ops.NmodEqualsAny(10, 1) && !ops.NmodEqualsAny(100, 11) {
+ return One
+ }
+ // n % 10 = 2..4 and n % 100 != 12..14
+ if ops.NmodInRange(10, 2, 4) && !ops.NmodInRange(100, 12, 14) {
+ return Few
+ }
+ // n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14
+ if ops.NmodEqualsAny(10, 0) ||
+ ops.NmodInRange(10, 5, 9) ||
+ ops.NmodInRange(100, 11, 14) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"lt"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n % 10 = 1 and n % 100 != 11..19
+ if ops.NmodEqualsAny(10, 1) && !ops.NmodInRange(100, 11, 19) {
+ return One
+ }
+ // n % 10 = 2..9 and n % 100 != 11..19
+ if ops.NmodInRange(10, 2, 9) && !ops.NmodInRange(100, 11, 19) {
+ return Few
+ }
+ // f != 0
+ if !intEqualsAny(ops.F, 0) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"mt"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 1
+ if ops.NequalsAny(1) {
+ return One
+ }
+ // n = 0 or n % 100 = 2..10
+ if ops.NequalsAny(0) ||
+ ops.NmodInRange(100, 2, 10) {
+ return Few
+ }
+ // n % 100 = 11..19
+ if ops.NmodInRange(100, 11, 19) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"ru", "uk"}, &PluralSpec{
+ Plurals: newPluralSet(One, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // v = 0 and i % 10 = 1 and i % 100 != 11
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%10, 1) && !intEqualsAny(ops.I%100, 11) {
+ return One
+ }
+ // v = 0 and i % 10 = 2..4 and i % 100 != 12..14
+ if intEqualsAny(ops.V, 0) && intInRange(ops.I%10, 2, 4) && !intInRange(ops.I%100, 12, 14) {
+ return Few
+ }
+ // v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%10, 0) ||
+ intEqualsAny(ops.V, 0) && intInRange(ops.I%10, 5, 9) ||
+ intEqualsAny(ops.V, 0) && intInRange(ops.I%100, 11, 14) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"br"}, &PluralSpec{
+ Plurals: newPluralSet(One, Two, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n % 10 = 1 and n % 100 != 11,71,91
+ if ops.NmodEqualsAny(10, 1) && !ops.NmodEqualsAny(100, 11, 71, 91) {
+ return One
+ }
+ // n % 10 = 2 and n % 100 != 12,72,92
+ if ops.NmodEqualsAny(10, 2) && !ops.NmodEqualsAny(100, 12, 72, 92) {
+ return Two
+ }
+ // n % 10 = 3..4,9 and n % 100 != 10..19,70..79,90..99
+ if (ops.NmodInRange(10, 3, 4) || ops.NmodEqualsAny(10, 9)) && !(ops.NmodInRange(100, 10, 19) || ops.NmodInRange(100, 70, 79) || ops.NmodInRange(100, 90, 99)) {
+ return Few
+ }
+ // n != 0 and n % 1000000 = 0
+ if !ops.NequalsAny(0) && ops.NmodEqualsAny(1000000, 0) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"ga"}, &PluralSpec{
+ Plurals: newPluralSet(One, Two, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 1
+ if ops.NequalsAny(1) {
+ return One
+ }
+ // n = 2
+ if ops.NequalsAny(2) {
+ return Two
+ }
+ // n = 3..6
+ if ops.NinRange(3, 6) {
+ return Few
+ }
+ // n = 7..10
+ if ops.NinRange(7, 10) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"gv"}, &PluralSpec{
+ Plurals: newPluralSet(One, Two, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // v = 0 and i % 10 = 1
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%10, 1) {
+ return One
+ }
+ // v = 0 and i % 10 = 2
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%10, 2) {
+ return Two
+ }
+ // v = 0 and i % 100 = 0,20,40,60,80
+ if intEqualsAny(ops.V, 0) && intEqualsAny(ops.I%100, 0, 20, 40, 60, 80) {
+ return Few
+ }
+ // v != 0
+ if !intEqualsAny(ops.V, 0) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"ar"}, &PluralSpec{
+ Plurals: newPluralSet(Zero, One, Two, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 0
+ if ops.NequalsAny(0) {
+ return Zero
+ }
+ // n = 1
+ if ops.NequalsAny(1) {
+ return One
+ }
+ // n = 2
+ if ops.NequalsAny(2) {
+ return Two
+ }
+ // n % 100 = 3..10
+ if ops.NmodInRange(100, 3, 10) {
+ return Few
+ }
+ // n % 100 = 11..99
+ if ops.NmodInRange(100, 11, 99) {
+ return Many
+ }
+ return Other
+ },
+ })
+ registerPluralSpec([]string{"cy"}, &PluralSpec{
+ Plurals: newPluralSet(Zero, One, Two, Few, Many, Other),
+ PluralFunc: func(ops *operands) Plural {
+ // n = 0
+ if ops.NequalsAny(0) {
+ return Zero
+ }
+ // n = 1
+ if ops.NequalsAny(1) {
+ return One
+ }
+ // n = 2
+ if ops.NequalsAny(2) {
+ return Two
+ }
+ // n = 3
+ if ops.NequalsAny(3) {
+ return Few
+ }
+ // n = 6
+ if ops.NequalsAny(6) {
+ return Many
+ }
+ return Other
+ },
+ })
+}