From de4c7804101a47a01d0c9b88ea34d2b153e2b6b9 Mon Sep 17 00:00:00 2001
From: Wim <wim@42.be>
Date: Sun, 10 Apr 2016 23:39:38 +0200
Subject: Vendor libs

---
 .../go-i18n/i18n/language/codegen/main.go          | 132 +++++
 .../go-i18n/i18n/language/codegen/xml.go           | 143 ++++++
 .../nicksnyder/go-i18n/i18n/language/language.go   |  99 ++++
 .../nicksnyder/go-i18n/i18n/language/operands.go   | 119 +++++
 .../nicksnyder/go-i18n/i18n/language/plural.go     |  40 ++
 .../nicksnyder/go-i18n/i18n/language/pluralspec.go |  74 +++
 .../go-i18n/i18n/language/pluralspec_gen.go        | 567 +++++++++++++++++++++
 7 files changed, 1174 insertions(+)
 create mode 100644 vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/main.go
 create mode 100644 vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/xml.go
 create mode 100644 vendor/github.com/nicksnyder/go-i18n/i18n/language/language.go
 create mode 100644 vendor/github.com/nicksnyder/go-i18n/i18n/language/operands.go
 create mode 100644 vendor/github.com/nicksnyder/go-i18n/i18n/language/plural.go
 create mode 100644 vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec.go
 create mode 100644 vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen.go

(limited to 'vendor/github.com/nicksnyder/go-i18n/i18n/language')

diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/main.go b/vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/main.go
new file mode 100644
index 00000000..5d6b6ad4
--- /dev/null
+++ b/vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/main.go
@@ -0,0 +1,132 @@
+package main
+
+import (
+	"encoding/xml"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"text/template"
+)
+
+var usage = `%[1]s generates Go code to support CLDR plural rules.
+
+Usage: %[1]s [options]
+
+Options:
+
+`
+
+func main() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, usage, os.Args[0])
+		flag.PrintDefaults()
+	}
+	var in, cout, tout string
+	flag.StringVar(&in, "i", "plurals.xml", "the input XML file containing CLDR plural rules")
+	flag.StringVar(&cout, "cout", "", "the code output file")
+	flag.StringVar(&tout, "tout", "", "the test output file")
+	flag.BoolVar(&verbose, "v", false, "verbose output")
+	flag.Parse()
+
+	buf, err := ioutil.ReadFile(in)
+	if err != nil {
+		fatalf("failed to read file: %s", err)
+	}
+
+	var data SupplementalData
+	if err := xml.Unmarshal(buf, &data); err != nil {
+		fatalf("failed to unmarshal xml: %s", err)
+	}
+
+	count := 0
+	for _, pg := range data.PluralGroups {
+		count += len(pg.SplitLocales())
+	}
+	infof("parsed %d locales", count)
+
+	if cout != "" {
+		file := openWritableFile(cout)
+		if err := codeTemplate.Execute(file, data); err != nil {
+			fatalf("unable to execute code template because %s", err)
+		} else {
+			infof("generated %s", cout)
+		}
+	} else {
+		infof("not generating code file (use -cout)")
+	}
+
+	if tout != "" {
+		file := openWritableFile(tout)
+		if err := testTemplate.Execute(file, data); err != nil {
+			fatalf("unable to execute test template because %s", err)
+		} else {
+			infof("generated %s", tout)
+		}
+	} else {
+		infof("not generating test file (use -tout)")
+	}
+}
+
+func openWritableFile(name string) *os.File {
+	file, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+	if err != nil {
+		fatalf("failed to write file %s because %s", name, err)
+	}
+	return file
+}
+
+var codeTemplate = template.Must(template.New("spec").Parse(`package language
+// This file is generated by i18n/language/codegen/generate.sh
+
+func init() {
+{{range .PluralGroups}}
+	registerPluralSpec({{printf "%#v" .SplitLocales}}, &PluralSpec{
+		Plurals: newPluralSet({{range $i, $e := .PluralRules}}{{if $i}}, {{end}}{{$e.CountTitle}}{{end}}),
+		PluralFunc: func(ops *operands) Plural { {{range .PluralRules}}{{if .GoCondition}}
+			// {{.Condition}}
+			if {{.GoCondition}} {
+				return {{.CountTitle}}
+			}{{end}}{{end}}
+			return Other
+		},
+	}){{end}}
+}
+`))
+
+var testTemplate = template.Must(template.New("spec").Parse(`package language
+// This file is generated by i18n/language/codegen/generate.sh
+
+import "testing"
+
+{{range .PluralGroups}}
+func Test{{.Name}}(t *testing.T) {
+	var tests []pluralTest
+	{{range .PluralRules}}
+	{{if .IntegerExamples}}tests = appendIntegerTests(tests, {{.CountTitle}}, {{printf "%#v" .IntegerExamples}}){{end}}
+	{{if .DecimalExamples}}tests = appendDecimalTests(tests, {{.CountTitle}}, {{printf "%#v" .DecimalExamples}}){{end}}
+	{{end}}
+	locales := {{printf "%#v" .SplitLocales}}
+	for _, locale := range locales {
+	  runTests(t, locale, tests)
+  }
+}
+{{end}}
+`))
+
+func infof(format string, args ...interface{}) {
+	fmt.Fprintf(os.Stderr, format+"\n", args...)
+}
+
+var verbose bool
+
+func verbosef(format string, args ...interface{}) {
+	if verbose {
+		infof(format, args...)
+	}
+}
+
+func fatalf(format string, args ...interface{}) {
+	infof("fatal: "+format+"\n", args...)
+	os.Exit(1)
+}
diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/xml.go b/vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/xml.go
new file mode 100644
index 00000000..9d39053c
--- /dev/null
+++ b/vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/xml.go
@@ -0,0 +1,143 @@
+package main
+
+import (
+	"encoding/xml"
+	"fmt"
+	"regexp"
+	"strings"
+)
+
+// SupplementalData is the top level struct of plural.xml
+type SupplementalData struct {
+	XMLName      xml.Name      `xml:"supplementalData"`
+	PluralGroups []PluralGroup `xml:"plurals>pluralRules"`
+}
+
+// PluralGroup is a group of locales with the same plural rules.
+type PluralGroup struct {
+	Locales     string       `xml:"locales,attr"`
+	PluralRules []PluralRule `xml:"pluralRule"`
+}
+
+// Name returns a unique name for this plural group.
+func (pg *PluralGroup) Name() string {
+	n := strings.Title(pg.Locales)
+	return strings.Replace(n, " ", "", -1)
+}
+
+// SplitLocales returns all the locales in the PluralGroup as a slice.
+func (pg *PluralGroup) SplitLocales() []string {
+	return strings.Split(pg.Locales, " ")
+}
+
+// PluralRule is the rule for a single plural form.
+type PluralRule struct {
+	Count string `xml:"count,attr"`
+	Rule  string `xml:",innerxml"`
+}
+
+// CountTitle returns the title case of the PluralRule's count.
+func (pr *PluralRule) CountTitle() string {
+	return strings.Title(pr.Count)
+}
+
+// Condition returns the condition where the PluralRule applies.
+func (pr *PluralRule) Condition() string {
+	i := strings.Index(pr.Rule, "@")
+	return pr.Rule[:i]
+}
+
+// Examples returns the integer and decimal exmaples for the PLuralRule.
+func (pr *PluralRule) Examples() (integer []string, decimal []string) {
+	ex := strings.Replace(pr.Rule, ", …", "", -1)
+	ddelim := "@decimal"
+	if i := strings.Index(ex, ddelim); i > 0 {
+		dex := strings.TrimSpace(ex[i+len(ddelim):])
+		decimal = strings.Split(dex, ", ")
+		ex = ex[:i]
+	}
+	idelim := "@integer"
+	if i := strings.Index(ex, idelim); i > 0 {
+		iex := strings.TrimSpace(ex[i+len(idelim):])
+		integer = strings.Split(iex, ", ")
+	}
+	return integer, decimal
+}
+
+// IntegerExamples returns the integer exmaples for the PLuralRule.
+func (pr *PluralRule) IntegerExamples() []string {
+	integer, _ := pr.Examples()
+	return integer
+}
+
+// DecimalExamples returns the decimal exmaples for the PLuralRule.
+func (pr *PluralRule) DecimalExamples() []string {
+	_, decimal := pr.Examples()
+	return decimal
+}
+
+var relationRegexp = regexp.MustCompile("([niftvw])(?: % ([0-9]+))? (!=|=)(.*)")
+
+// GoCondition converts the XML condition to valid Go code.
+func (pr *PluralRule) GoCondition() string {
+	var ors []string
+	for _, and := range strings.Split(pr.Condition(), "or") {
+		var ands []string
+		for _, relation := range strings.Split(and, "and") {
+			parts := relationRegexp.FindStringSubmatch(relation)
+			if parts == nil {
+				continue
+			}
+			lvar, lmod, op, rhs := strings.Title(parts[1]), parts[2], parts[3], strings.TrimSpace(parts[4])
+			if op == "=" {
+				op = "=="
+			}
+			lvar = "ops." + lvar
+			var rhor []string
+			var rany []string
+			for _, rh := range strings.Split(rhs, ",") {
+				if parts := strings.Split(rh, ".."); len(parts) == 2 {
+					from, to := parts[0], parts[1]
+					if lvar == "ops.N" {
+						if lmod != "" {
+							rhor = append(rhor, fmt.Sprintf("ops.NmodInRange(%s, %s, %s)", lmod, from, to))
+						} else {
+							rhor = append(rhor, fmt.Sprintf("ops.NinRange(%s, %s)", from, to))
+						}
+					} else if lmod != "" {
+						rhor = append(rhor, fmt.Sprintf("intInRange(%s %% %s, %s, %s)", lvar, lmod, from, to))
+					} else {
+						rhor = append(rhor, fmt.Sprintf("intInRange(%s, %s, %s)", lvar, from, to))
+					}
+				} else {
+					rany = append(rany, rh)
+				}
+			}
+
+			if len(rany) > 0 {
+				rh := strings.Join(rany, ",")
+				if lvar == "ops.N" {
+					if lmod != "" {
+						rhor = append(rhor, fmt.Sprintf("ops.NmodEqualsAny(%s, %s)", lmod, rh))
+					} else {
+						rhor = append(rhor, fmt.Sprintf("ops.NequalsAny(%s)", rh))
+					}
+				} else if lmod != "" {
+					rhor = append(rhor, fmt.Sprintf("intEqualsAny(%s %% %s, %s)", lvar, lmod, rh))
+				} else {
+					rhor = append(rhor, fmt.Sprintf("intEqualsAny(%s, %s)", lvar, rh))
+				}
+			}
+			r := strings.Join(rhor, " || ")
+			if len(rhor) > 1 {
+				r = "(" + r + ")"
+			}
+			if op == "!=" {
+				r = "!" + r
+			}
+			ands = append(ands, r)
+		}
+		ors = append(ors, strings.Join(ands, " && "))
+	}
+	return strings.Join(ors, " ||\n")
+}
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 00000000..9a155efc
--- /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 00000000..877bcc89
--- /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 00000000..1f3ea5c6
--- /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 00000000..fc352268
--- /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 00000000..c9b4f266
--- /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
+		},
+	})
+}
-- 
cgit v1.2.3