Update vendored dependencies, added goi18n
This commit is contained in:
parent
9e2679bfaa
commit
50c5e6cb61
18
glide.lock
generated
18
glide.lock
generated
|
@ -1,10 +1,10 @@
|
|||
hash: 58b946577727dc003cc7efacfff614b6f47602a136e8bf501bd39a18bd3c768c
|
||||
updated: 2016-06-20T17:29:39.656363943-07:00
|
||||
hash: 90b4d676820ec357d9eac7be23afe091897035f8e22579f32bef93f9e1971e42
|
||||
updated: 2016-06-21T09:01:11.596780617-07:00
|
||||
imports:
|
||||
- name: github.com/antonholmquist/jason
|
||||
version: 423803175a265e07c3f35cd8faf009eac345efb8
|
||||
version: c23cef7eaa75a6a5b8810120e167bd590d8fd2ab
|
||||
- name: github.com/BurntSushi/toml
|
||||
version: f0aeabca5a127c4078abb8c8d64298b147264b55
|
||||
version: bbd5bb678321a0d6e58f1099321dfa73391c1b6f
|
||||
- name: github.com/ChannelMeter/iso8601duration
|
||||
version: 8da3af7a2a61a4eb5ae9bddec06bf637fa9593da
|
||||
- name: github.com/fsnotify/fsnotify
|
||||
|
@ -39,8 +39,12 @@ imports:
|
|||
version: c265cfa48dda6474e208715ca93e987829f572f8
|
||||
- name: github.com/mitchellh/mapstructure
|
||||
version: d2dd0262208475919e1a362f675cfc0e7c10e905
|
||||
- name: github.com/nicksnyder/go-i18n
|
||||
version: 37e5c2de3e03e4b82693e3fcb4a6aa2cc4eb07e3
|
||||
subpackages:
|
||||
- i18n
|
||||
- name: github.com/Sirupsen/logrus
|
||||
version: f3cfb454f4c209e6668c95216c4744b8fddb2356
|
||||
version: 4b6ea7319e214d98c938f12692336f7ca9348d6b
|
||||
- name: github.com/spf13/cast
|
||||
version: 27b586b42e29bec072fe7379259cc719e1289da6
|
||||
- name: github.com/spf13/jwalterweatherman
|
||||
|
@ -50,9 +54,9 @@ imports:
|
|||
- name: github.com/spf13/viper
|
||||
version: c1ccc378a054ea8d4e38d8c67f6938d4760b53dd
|
||||
- name: github.com/stretchr/testify
|
||||
version: d77da356e56a7428ad25149ca77381849a6a5232
|
||||
version: f390dcf405f7b83c997eac1b06768bb9f44dec18
|
||||
- name: github.com/urfave/cli
|
||||
version: 6011f165dc288c72abd8acd7722f837c5c64198d
|
||||
version: 01857ac33766ce0c93856370626f9799281c14f4
|
||||
- name: golang.org/x/sys
|
||||
version: 62bee037599929a6e9146f29d10dd5208c43507d
|
||||
subpackages:
|
||||
|
|
|
@ -8,7 +8,9 @@ owners:
|
|||
import:
|
||||
- package: github.com/ChannelMeter/iso8601duration
|
||||
- package: github.com/Sirupsen/logrus
|
||||
version: v0.10.0
|
||||
- package: github.com/antonholmquist/jason
|
||||
version: v1.0.0
|
||||
- package: github.com/layeh/gumble
|
||||
subpackages:
|
||||
- gumble
|
||||
|
@ -17,5 +19,12 @@ import:
|
|||
- opus
|
||||
- package: github.com/spf13/viper
|
||||
- package: github.com/urfave/cli
|
||||
version: v1.17.0
|
||||
- package: github.com/stretchr/testify
|
||||
version: v1.1.3
|
||||
- package: github.com/BurntSushi/toml
|
||||
version: v0.2.0
|
||||
- package: github.com/nicksnyder/go-i18n
|
||||
version: v1.4.0
|
||||
subpackages:
|
||||
- i18n
|
||||
|
|
9
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
9
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
|
@ -103,13 +103,6 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
|
|||
// This decoder will not handle cyclic types. If a cyclic type is passed,
|
||||
// `Decode` will not terminate.
|
||||
func Decode(data string, v interface{}) (MetaData, error) {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
return MetaData{}, e("Decode of non-pointer type %s", reflect.TypeOf(v))
|
||||
}
|
||||
if rv.IsNil() {
|
||||
return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v))
|
||||
}
|
||||
p, err := parse(data)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
|
@ -118,7 +111,7 @@ func Decode(data string, v interface{}) (MetaData, error) {
|
|||
p.mapping, p.types, p.ordered,
|
||||
make(map[string]bool, len(p.ordered)), nil,
|
||||
}
|
||||
return md, md.unify(p.mapping, indirect(rv))
|
||||
return md, md.unify(p.mapping, rvalue(v))
|
||||
}
|
||||
|
||||
// DecodeFile is just like Decode, except it will automatically read the
|
||||
|
|
208
vendor/github.com/BurntSushi/toml/decode_test.go
generated
vendored
208
vendor/github.com/BurntSushi/toml/decode_test.go
generated
vendored
|
@ -3,13 +3,15 @@ package toml
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFlags(0)
|
||||
}
|
||||
|
||||
func TestDecodeSimple(t *testing.T) {
|
||||
var testSimple = `
|
||||
age = 250
|
||||
|
@ -181,49 +183,6 @@ name = "Born in the USA"
|
|||
}
|
||||
}
|
||||
|
||||
func TestTableNesting(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
t string
|
||||
want []string
|
||||
}{
|
||||
{"[a.b.c]", []string{"a", "b", "c"}},
|
||||
{`[a."b.c"]`, []string{"a", "b.c"}},
|
||||
{`[a.'b.c']`, []string{"a", "b.c"}},
|
||||
{`[a.' b ']`, []string{"a", " b "}},
|
||||
{"[ d.e.f ]", []string{"d", "e", "f"}},
|
||||
{"[ g . h . i ]", []string{"g", "h", "i"}},
|
||||
{`[ j . "ʞ" . 'l' ]`, []string{"j", "ʞ", "l"}},
|
||||
} {
|
||||
var m map[string]interface{}
|
||||
if _, err := Decode(tt.t, &m); err != nil {
|
||||
t.Errorf("Decode(%q): got error: %s", tt.t, err)
|
||||
continue
|
||||
}
|
||||
if keys := extractNestedKeys(m); !reflect.DeepEqual(keys, tt.want) {
|
||||
t.Errorf("Decode(%q): got nested keys %#v; want %#v",
|
||||
tt.t, keys, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func extractNestedKeys(v map[string]interface{}) []string {
|
||||
var result []string
|
||||
for {
|
||||
if len(v) != 1 {
|
||||
return result
|
||||
}
|
||||
for k, m := range v {
|
||||
result = append(result, k)
|
||||
var ok bool
|
||||
v, ok = m.(map[string]interface{})
|
||||
if !ok {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Case insensitive matching tests.
|
||||
// A bit more comprehensive than needed given the current implementation,
|
||||
// but implementations change.
|
||||
|
@ -343,54 +302,14 @@ Description = "da base"
|
|||
}
|
||||
}
|
||||
|
||||
func TestDecodeDatetime(t *testing.T) {
|
||||
const noTimestamp = "2006-01-02T15:04:05"
|
||||
for _, tt := range []struct {
|
||||
s string
|
||||
t string
|
||||
format string
|
||||
}{
|
||||
{"1979-05-27T07:32:00Z", "1979-05-27T07:32:00Z", time.RFC3339},
|
||||
{"1979-05-27T00:32:00-07:00", "1979-05-27T00:32:00-07:00", time.RFC3339},
|
||||
{
|
||||
"1979-05-27T00:32:00.999999-07:00",
|
||||
"1979-05-27T00:32:00.999999-07:00",
|
||||
time.RFC3339,
|
||||
},
|
||||
{"1979-05-27T07:32:00", "1979-05-27T07:32:00", noTimestamp},
|
||||
{
|
||||
"1979-05-27T00:32:00.999999",
|
||||
"1979-05-27T00:32:00.999999",
|
||||
noTimestamp,
|
||||
},
|
||||
{"1979-05-27", "1979-05-27T00:00:00", noTimestamp},
|
||||
} {
|
||||
var x struct{ D time.Time }
|
||||
input := "d = " + tt.s
|
||||
if _, err := Decode(input, &x); err != nil {
|
||||
t.Errorf("Decode(%q): got error: %s", input, err)
|
||||
continue
|
||||
}
|
||||
want, err := time.ParseInLocation(tt.format, tt.t, time.Local)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !x.D.Equal(want) {
|
||||
t.Errorf("Decode(%q): got %s; want %s", input, x.D, want)
|
||||
}
|
||||
func TestDecodeBadTimestamp(t *testing.T) {
|
||||
var x struct {
|
||||
T time.Time
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeBadDatetime(t *testing.T) {
|
||||
var x struct{ T time.Time }
|
||||
for _, s := range []string{
|
||||
"123",
|
||||
"2006-01-50T00:00:00Z",
|
||||
"2006-01-30T00:00",
|
||||
"2006-01-30T",
|
||||
"T = 123", "T = 2006-01-50T00:00:00Z", "T = 2006-01-30T00:00:00",
|
||||
} {
|
||||
input := "T = " + s
|
||||
if _, err := Decode(input, &x); err == nil {
|
||||
if _, err := Decode(s, &x); err == nil {
|
||||
t.Errorf("Expected invalid DateTime error for %q", s)
|
||||
}
|
||||
}
|
||||
|
@ -484,111 +403,6 @@ func TestDecodeSizedInts(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDecodeInts(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
s string
|
||||
want int64
|
||||
}{
|
||||
{"0", 0},
|
||||
{"+99", 99},
|
||||
{"-10", -10},
|
||||
{"1_234_567", 1234567},
|
||||
{"1_2_3_4", 1234},
|
||||
{"-9_223_372_036_854_775_808", math.MinInt64},
|
||||
{"9_223_372_036_854_775_807", math.MaxInt64},
|
||||
} {
|
||||
var x struct{ N int64 }
|
||||
input := "n = " + tt.s
|
||||
if _, err := Decode(input, &x); err != nil {
|
||||
t.Errorf("Decode(%q): got error: %s", input, err)
|
||||
continue
|
||||
}
|
||||
if x.N != tt.want {
|
||||
t.Errorf("Decode(%q): got %d; want %d", input, x.N, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeFloats(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
s string
|
||||
want float64
|
||||
}{
|
||||
{"+1.0", 1},
|
||||
{"3.1415", 3.1415},
|
||||
{"-0.01", -0.01},
|
||||
{"5e+22", 5e22},
|
||||
{"1e6", 1e6},
|
||||
{"-2E-2", -2e-2},
|
||||
{"6.626e-34", 6.626e-34},
|
||||
{"9_224_617.445_991_228_313", 9224617.445991228313},
|
||||
{"9_876.54_32e1_0", 9876.5432e10},
|
||||
} {
|
||||
var x struct{ N float64 }
|
||||
input := "n = " + tt.s
|
||||
if _, err := Decode(input, &x); err != nil {
|
||||
t.Errorf("Decode(%q): got error: %s", input, err)
|
||||
continue
|
||||
}
|
||||
if x.N != tt.want {
|
||||
t.Errorf("Decode(%q): got %d; want %d", input, x.N, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeMalformedNumbers(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
s string
|
||||
want string
|
||||
}{
|
||||
{"++99", "Expected a digit"},
|
||||
{"0..1", "must be followed by one or more digits"},
|
||||
{"0.1.2", "Invalid float value"},
|
||||
{"1e2.3", "Invalid float value"},
|
||||
{"1e2e3", "Invalid float value"},
|
||||
{"_123", "Expected value"},
|
||||
{"123_", "surrounded by digits"},
|
||||
{"1._23", "surrounded by digits"},
|
||||
{"1e__23", "surrounded by digits"},
|
||||
{"123.", "must be followed by one or more digits"},
|
||||
{"1.e2", "must be followed by one or more digits"},
|
||||
} {
|
||||
var x struct{ N interface{} }
|
||||
input := "n = " + tt.s
|
||||
_, err := Decode(input, &x)
|
||||
if err == nil {
|
||||
t.Errorf("Decode(%q): got nil, want error containing %q",
|
||||
input, tt.want)
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.want) {
|
||||
t.Errorf("Decode(%q): got %q, want error containing %q",
|
||||
input, err, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeBadValues(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
v interface{}
|
||||
want string
|
||||
}{
|
||||
{3, "non-pointer type"},
|
||||
{(*int)(nil), "nil"},
|
||||
} {
|
||||
_, err := Decode(`x = 3`, tt.v)
|
||||
if err == nil {
|
||||
t.Errorf("Decode(%v): got nil; want error containing %q",
|
||||
tt.v, tt.want)
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.want) {
|
||||
t.Errorf("Decode(%v): got %q; want error containing %q",
|
||||
tt.v, err, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshaler(t *testing.T) {
|
||||
|
||||
var tomlBlob = `
|
||||
|
@ -623,7 +437,7 @@ name = "Rice"
|
|||
`
|
||||
m := &menu{}
|
||||
if _, err := Decode(tomlBlob, m); err != nil {
|
||||
t.Fatal(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if len(m.Dishes) != 2 {
|
||||
|
@ -659,7 +473,7 @@ name = "Rice"
|
|||
// test on a value - must be passed as *
|
||||
o := menu{}
|
||||
if _, err := Decode(tomlBlob, &o); err != nil {
|
||||
t.Fatal(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
58
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
58
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
|
@ -315,16 +315,10 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
|
|||
t := f.Type
|
||||
switch t.Kind() {
|
||||
case reflect.Struct:
|
||||
// Treat anonymous struct fields with
|
||||
// tag names as though they are not
|
||||
// anonymous, like encoding/json does.
|
||||
if getOptions(f.Tag).name == "" {
|
||||
addFields(t, frv, f.Index)
|
||||
continue
|
||||
}
|
||||
addFields(t, frv, f.Index)
|
||||
continue
|
||||
case reflect.Ptr:
|
||||
if t.Elem().Kind() == reflect.Struct &&
|
||||
getOptions(f.Tag).name == "" {
|
||||
if t.Elem().Kind() == reflect.Struct {
|
||||
if !frv.IsNil() {
|
||||
addFields(t.Elem(), frv.Elem(), f.Index)
|
||||
}
|
||||
|
@ -353,18 +347,17 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
|
|||
continue
|
||||
}
|
||||
|
||||
opts := getOptions(sft.Tag)
|
||||
if opts.skip {
|
||||
tag := sft.Tag.Get("toml")
|
||||
if tag == "-" {
|
||||
continue
|
||||
}
|
||||
keyName := sft.Name
|
||||
if opts.name != "" {
|
||||
keyName = opts.name
|
||||
keyName, opts := getOptions(tag)
|
||||
if keyName == "" {
|
||||
keyName = sft.Name
|
||||
}
|
||||
if opts.omitempty && isEmpty(sf) {
|
||||
if _, ok := opts["omitempty"]; ok && isEmpty(sf) {
|
||||
continue
|
||||
}
|
||||
if opts.omitzero && isZero(sf) {
|
||||
} else if _, ok := opts["omitzero"]; ok && isZero(sf) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -458,30 +451,17 @@ func tomlArrayType(rv reflect.Value) tomlType {
|
|||
return firstType
|
||||
}
|
||||
|
||||
type tagOptions struct {
|
||||
skip bool // "-"
|
||||
name string
|
||||
omitempty bool
|
||||
omitzero bool
|
||||
}
|
||||
|
||||
func getOptions(tag reflect.StructTag) tagOptions {
|
||||
t := tag.Get("toml")
|
||||
if t == "-" {
|
||||
return tagOptions{skip: true}
|
||||
}
|
||||
var opts tagOptions
|
||||
parts := strings.Split(t, ",")
|
||||
opts.name = parts[0]
|
||||
for _, s := range parts[1:] {
|
||||
switch s {
|
||||
case "omitempty":
|
||||
opts.omitempty = true
|
||||
case "omitzero":
|
||||
opts.omitzero = true
|
||||
func getOptions(keyName string) (string, map[string]struct{}) {
|
||||
opts := make(map[string]struct{})
|
||||
ss := strings.Split(keyName, ",")
|
||||
name := ss[0]
|
||||
if len(ss) > 1 {
|
||||
for _, opt := range ss {
|
||||
opts[opt] = struct{}{}
|
||||
}
|
||||
}
|
||||
return opts
|
||||
|
||||
return name, opts
|
||||
}
|
||||
|
||||
func isZero(rv reflect.Value) bool {
|
||||
|
|
41
vendor/github.com/BurntSushi/toml/encode_test.go
generated
vendored
41
vendor/github.com/BurntSushi/toml/encode_test.go
generated
vendored
|
@ -36,7 +36,7 @@ func TestEncodeRoundTrip(t *testing.T) {
|
|||
}
|
||||
var outputs Config
|
||||
if _, err := Decode(firstBuffer.String(), &outputs); err != nil {
|
||||
t.Logf("Could not decode:\n-----\n%s\n-----\n",
|
||||
log.Printf("Could not decode:\n-----\n%s\n-----\n",
|
||||
firstBuffer.String())
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -515,44 +515,19 @@ func TestEncodeOmitemptyWithEmptyName(t *testing.T) {
|
|||
v, expected, nil)
|
||||
}
|
||||
|
||||
func TestEncodeAnonymousStruct(t *testing.T) {
|
||||
type Inner struct{ N int }
|
||||
type Outer0 struct{ Inner }
|
||||
type Outer1 struct {
|
||||
Inner `toml:"inner"`
|
||||
}
|
||||
|
||||
v0 := Outer0{Inner{3}}
|
||||
expected := "N = 3\n"
|
||||
encodeExpected(t, "embedded anonymous untagged struct", v0, expected, nil)
|
||||
|
||||
v1 := Outer1{Inner{3}}
|
||||
expected = "[inner]\n N = 3\n"
|
||||
encodeExpected(t, "embedded anonymous tagged struct", v1, expected, nil)
|
||||
}
|
||||
|
||||
func TestEncodeAnonymousStructPointerField(t *testing.T) {
|
||||
type Inner struct{ N int }
|
||||
type Outer0 struct{ *Inner }
|
||||
type Outer1 struct {
|
||||
*Inner `toml:"inner"`
|
||||
type Sub struct{}
|
||||
type simple struct {
|
||||
*Sub
|
||||
}
|
||||
|
||||
v0 := Outer0{}
|
||||
value := simple{}
|
||||
expected := ""
|
||||
encodeExpected(t, "nil anonymous untagged struct pointer field", v0, expected, nil)
|
||||
encodeExpected(t, "nil anonymous struct pointer field", value, expected, nil)
|
||||
|
||||
v0 = Outer0{&Inner{3}}
|
||||
expected = "N = 3\n"
|
||||
encodeExpected(t, "non-nil anonymous untagged struct pointer field", v0, expected, nil)
|
||||
|
||||
v1 := Outer1{}
|
||||
value = simple{Sub: &Sub{}}
|
||||
expected = ""
|
||||
encodeExpected(t, "nil anonymous tagged struct pointer field", v1, expected, nil)
|
||||
|
||||
v1 = Outer1{&Inner{3}}
|
||||
expected = "[inner]\n N = 3\n"
|
||||
encodeExpected(t, "non-nil anonymous tagged struct pointer field", v1, expected, nil)
|
||||
encodeExpected(t, "non-nil anonymous struct pointer field", value, expected, nil)
|
||||
}
|
||||
|
||||
func TestEncodeIgnoredFields(t *testing.T) {
|
||||
|
|
225
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
225
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
|
@ -3,7 +3,6 @@ package toml
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
|
@ -167,19 +166,6 @@ func (lx *lexer) peek() rune {
|
|||
return r
|
||||
}
|
||||
|
||||
// skip ignores all input that matches the given predicate.
|
||||
func (lx *lexer) skip(pred func(rune) bool) {
|
||||
for {
|
||||
r := lx.next()
|
||||
if pred(r) {
|
||||
continue
|
||||
}
|
||||
lx.backup()
|
||||
lx.ignore()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// errorf stops all lexing by emitting an error and returning `nil`.
|
||||
// Note that any value that is a character is escaped if it's a special
|
||||
// character (new lines, tabs, etc.).
|
||||
|
@ -275,7 +261,6 @@ func lexArrayTableEnd(lx *lexer) stateFn {
|
|||
}
|
||||
|
||||
func lexTableNameStart(lx *lexer) stateFn {
|
||||
lx.skip(isWhitespace)
|
||||
switch r := lx.peek(); {
|
||||
case r == tableEnd || r == eof:
|
||||
return lx.errorf("Unexpected end of table name. (Table names cannot " +
|
||||
|
@ -292,22 +277,24 @@ func lexTableNameStart(lx *lexer) stateFn {
|
|||
}
|
||||
}
|
||||
|
||||
// lexBareTableName lexes the name of a table. It assumes that at least one
|
||||
// lexTableName lexes the name of a table. It assumes that at least one
|
||||
// valid character for the table has already been read.
|
||||
func lexBareTableName(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isBareKeyChar(r) {
|
||||
switch r := lx.next(); {
|
||||
case isBareKeyChar(r):
|
||||
return lexBareTableName
|
||||
case r == tableSep || r == tableEnd:
|
||||
lx.backup()
|
||||
lx.emitTrim(itemText)
|
||||
return lexTableNameEnd
|
||||
default:
|
||||
return lx.errorf("Bare keys cannot contain %q.", r)
|
||||
}
|
||||
lx.backup()
|
||||
lx.emit(itemText)
|
||||
return lexTableNameEnd
|
||||
}
|
||||
|
||||
// lexTableNameEnd reads the end of a piece of a table name, optionally
|
||||
// consuming whitespace.
|
||||
func lexTableNameEnd(lx *lexer) stateFn {
|
||||
lx.skip(isWhitespace)
|
||||
switch r := lx.next(); {
|
||||
case isWhitespace(r):
|
||||
return lexTableNameEnd
|
||||
|
@ -351,12 +338,11 @@ func lexBareKey(lx *lexer) stateFn {
|
|||
case isBareKeyChar(r):
|
||||
return lexBareKey
|
||||
case isWhitespace(r):
|
||||
lx.backup()
|
||||
lx.emit(itemText)
|
||||
lx.emitTrim(itemText)
|
||||
return lexKeyEnd
|
||||
case r == keySep:
|
||||
lx.backup()
|
||||
lx.emit(itemText)
|
||||
lx.emitTrim(itemText)
|
||||
return lexKeyEnd
|
||||
default:
|
||||
return lx.errorf("Bare keys cannot contain %q.", r)
|
||||
|
@ -385,19 +371,16 @@ func lexValue(lx *lexer) stateFn {
|
|||
// In array syntax, the array states are responsible for ignoring new
|
||||
// lines.
|
||||
r := lx.next()
|
||||
switch {
|
||||
case isWhitespace(r):
|
||||
if isWhitespace(r) {
|
||||
return lexSkip(lx, lexValue)
|
||||
case isDigit(r):
|
||||
lx.backup() // avoid an extra state and use the same as above
|
||||
return lexNumberOrDateStart
|
||||
}
|
||||
switch r {
|
||||
case arrayStart:
|
||||
|
||||
switch {
|
||||
case r == arrayStart:
|
||||
lx.ignore()
|
||||
lx.emit(itemArray)
|
||||
return lexArrayValue
|
||||
case stringStart:
|
||||
case r == stringStart:
|
||||
if lx.accept(stringStart) {
|
||||
if lx.accept(stringStart) {
|
||||
lx.ignore() // Ignore """
|
||||
|
@ -407,7 +390,7 @@ func lexValue(lx *lexer) stateFn {
|
|||
}
|
||||
lx.ignore() // ignore the '"'
|
||||
return lexString
|
||||
case rawStringStart:
|
||||
case r == rawStringStart:
|
||||
if lx.accept(rawStringStart) {
|
||||
if lx.accept(rawStringStart) {
|
||||
lx.ignore() // Ignore """
|
||||
|
@ -417,19 +400,18 @@ func lexValue(lx *lexer) stateFn {
|
|||
}
|
||||
lx.ignore() // ignore the "'"
|
||||
return lexRawString
|
||||
case '+', '-':
|
||||
case r == 't':
|
||||
return lexTrue
|
||||
case r == 'f':
|
||||
return lexFalse
|
||||
case r == '-':
|
||||
return lexNumberStart
|
||||
case '.': // special error case, be kind to users
|
||||
case isDigit(r):
|
||||
lx.backup() // avoid an extra state and use the same as above
|
||||
return lexNumberOrDateStart
|
||||
case r == '.': // special error case, be kind to users
|
||||
return lx.errorf("Floats must start with a digit, not '.'.")
|
||||
}
|
||||
if unicode.IsLetter(r) {
|
||||
// Be permissive here; lexBool will give a nice error if the
|
||||
// user wrote something like
|
||||
// x = foo
|
||||
// (i.e. not 'true' or 'false' but is something else word-like.)
|
||||
lx.backup()
|
||||
return lexBool
|
||||
}
|
||||
return lx.errorf("Expected value but found %q instead.", r)
|
||||
}
|
||||
|
||||
|
@ -636,36 +618,33 @@ func lexLongUnicodeEscape(lx *lexer) stateFn {
|
|||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexNumberOrDateStart consumes either an integer, a float, or datetime.
|
||||
// lexNumberOrDateStart consumes either a (positive) integer, float or
|
||||
// datetime. It assumes that NO negative sign has been consumed.
|
||||
func lexNumberOrDateStart(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isDigit(r) {
|
||||
return lexNumberOrDate
|
||||
if !isDigit(r) {
|
||||
if r == '.' {
|
||||
return lx.errorf("Floats must start with a digit, not '.'.")
|
||||
} else {
|
||||
return lx.errorf("Expected a digit but got %q.", r)
|
||||
}
|
||||
}
|
||||
switch r {
|
||||
case '_':
|
||||
return lexNumber
|
||||
case 'e', 'E':
|
||||
return lexFloat
|
||||
case '.':
|
||||
return lx.errorf("Floats must start with a digit, not '.'.")
|
||||
}
|
||||
return lx.errorf("Expected a digit but got %q.", r)
|
||||
return lexNumberOrDate
|
||||
}
|
||||
|
||||
// lexNumberOrDate consumes either an integer, float or datetime.
|
||||
// lexNumberOrDate consumes either a (positive) integer, float or datetime.
|
||||
func lexNumberOrDate(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isDigit(r) {
|
||||
switch {
|
||||
case r == '-':
|
||||
if lx.pos-lx.start != 5 {
|
||||
return lx.errorf("All ISO8601 dates must be in full Zulu form.")
|
||||
}
|
||||
return lexDateAfterYear
|
||||
case isDigit(r):
|
||||
return lexNumberOrDate
|
||||
}
|
||||
switch r {
|
||||
case '-':
|
||||
return lexDatetime
|
||||
case '_':
|
||||
return lexNumber
|
||||
case '.', 'e', 'E':
|
||||
return lexFloat
|
||||
case r == '.':
|
||||
return lexFloatStart
|
||||
}
|
||||
|
||||
lx.backup()
|
||||
|
@ -673,28 +652,39 @@ func lexNumberOrDate(lx *lexer) stateFn {
|
|||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexDatetime consumes a Datetime, to a first approximation.
|
||||
// The parser validates that it matches one of the accepted formats.
|
||||
func lexDatetime(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isDigit(r) {
|
||||
return lexDatetime
|
||||
// lexDateAfterYear consumes a full Zulu Datetime in ISO8601 format.
|
||||
// It assumes that "YYYY-" has already been consumed.
|
||||
func lexDateAfterYear(lx *lexer) stateFn {
|
||||
formats := []rune{
|
||||
// digits are '0'.
|
||||
// everything else is direct equality.
|
||||
'0', '0', '-', '0', '0',
|
||||
'T',
|
||||
'0', '0', ':', '0', '0', ':', '0', '0',
|
||||
'Z',
|
||||
}
|
||||
switch r {
|
||||
case '-', 'T', ':', '.', 'Z':
|
||||
return lexDatetime
|
||||
for _, f := range formats {
|
||||
r := lx.next()
|
||||
if f == '0' {
|
||||
if !isDigit(r) {
|
||||
return lx.errorf("Expected digit in ISO8601 datetime, "+
|
||||
"but found %q instead.", r)
|
||||
}
|
||||
} else if f != r {
|
||||
return lx.errorf("Expected %q in ISO8601 datetime, "+
|
||||
"but found %q instead.", f, r)
|
||||
}
|
||||
}
|
||||
|
||||
lx.backup()
|
||||
lx.emit(itemDatetime)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexNumberStart consumes either an integer or a float. It assumes that a sign
|
||||
// has already been read, but that *no* digits have been consumed.
|
||||
// lexNumberStart will move to the appropriate integer or float states.
|
||||
// lexNumberStart consumes either an integer or a float. It assumes that
|
||||
// a negative sign has already been read, but that *no* digits have been
|
||||
// consumed. lexNumberStart will move to the appropriate integer or float
|
||||
// states.
|
||||
func lexNumberStart(lx *lexer) stateFn {
|
||||
// We MUST see a digit. Even floats have to start with a digit.
|
||||
// we MUST see a digit. Even floats have to start with a digit.
|
||||
r := lx.next()
|
||||
if !isDigit(r) {
|
||||
if r == '.' {
|
||||
|
@ -709,14 +699,11 @@ func lexNumberStart(lx *lexer) stateFn {
|
|||
// lexNumber consumes an integer or a float after seeing the first digit.
|
||||
func lexNumber(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isDigit(r) {
|
||||
switch {
|
||||
case isDigit(r):
|
||||
return lexNumber
|
||||
}
|
||||
switch r {
|
||||
case '_':
|
||||
return lexNumber
|
||||
case '.', 'e', 'E':
|
||||
return lexFloat
|
||||
case r == '.':
|
||||
return lexFloatStart
|
||||
}
|
||||
|
||||
lx.backup()
|
||||
|
@ -724,42 +711,60 @@ func lexNumber(lx *lexer) stateFn {
|
|||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexFloat consumes the elements of a float. It allows any sequence of
|
||||
// float-like characters, so floats emitted by the lexer are only a first
|
||||
// approximation and must be validated by the parser.
|
||||
// lexFloatStart starts the consumption of digits of a float after a '.'.
|
||||
// Namely, at least one digit is required.
|
||||
func lexFloatStart(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if !isDigit(r) {
|
||||
return lx.errorf("Floats must have a digit after the '.', but got "+
|
||||
"%q instead.", r)
|
||||
}
|
||||
return lexFloat
|
||||
}
|
||||
|
||||
// lexFloat consumes the digits of a float after a '.'.
|
||||
// Assumes that one digit has been consumed after a '.' already.
|
||||
func lexFloat(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isDigit(r) {
|
||||
return lexFloat
|
||||
}
|
||||
switch r {
|
||||
case '_', '.', '-', '+', 'e', 'E':
|
||||
return lexFloat
|
||||
}
|
||||
|
||||
lx.backup()
|
||||
lx.emit(itemFloat)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexBool consumes a bool string: 'true' or 'false.
|
||||
func lexBool(lx *lexer) stateFn {
|
||||
var rs []rune
|
||||
for {
|
||||
r := lx.next()
|
||||
if r == eof || isWhitespace(r) || isNL(r) {
|
||||
lx.backup()
|
||||
break
|
||||
// lexConst consumes the s[1:] in s. It assumes that s[0] has already been
|
||||
// consumed.
|
||||
func lexConst(lx *lexer, s string) stateFn {
|
||||
for i := range s[1:] {
|
||||
if r := lx.next(); r != rune(s[i+1]) {
|
||||
return lx.errorf("Expected %q, but found %q instead.", s[:i+1],
|
||||
s[:i]+string(r))
|
||||
}
|
||||
rs = append(rs, r)
|
||||
}
|
||||
s := string(rs)
|
||||
switch s {
|
||||
case "true", "false":
|
||||
lx.emit(itemBool)
|
||||
return lx.pop()
|
||||
return nil
|
||||
}
|
||||
|
||||
// lexTrue consumes the "rue" in "true". It assumes that 't' has already
|
||||
// been consumed.
|
||||
func lexTrue(lx *lexer) stateFn {
|
||||
if fn := lexConst(lx, "true"); fn != nil {
|
||||
return fn
|
||||
}
|
||||
return lx.errorf("Expected value but found %q instead.", s)
|
||||
lx.emit(itemBool)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexFalse consumes the "alse" in "false". It assumes that 'f' has already
|
||||
// been consumed.
|
||||
func lexFalse(lx *lexer) stateFn {
|
||||
if fn := lexConst(lx, "false"); fn != nil {
|
||||
return fn
|
||||
}
|
||||
lx.emit(itemBool)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexCommentStart begins the lexing of a comment. It will emit
|
||||
|
|
98
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
98
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
|
@ -2,6 +2,7 @@ package toml
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -80,7 +81,7 @@ func (p *parser) next() item {
|
|||
}
|
||||
|
||||
func (p *parser) bug(format string, v ...interface{}) {
|
||||
panic(fmt.Sprintf("BUG: "+format+"\n\n", v...))
|
||||
log.Panicf("BUG: %s\n\n", fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
func (p *parser) expect(typ itemType) item {
|
||||
|
@ -178,18 +179,10 @@ func (p *parser) value(it item) (interface{}, tomlType) {
|
|||
}
|
||||
p.bug("Expected boolean value, but got '%s'.", it.val)
|
||||
case itemInteger:
|
||||
if !numUnderscoresOK(it.val) {
|
||||
p.panicf("Invalid integer %q: underscores must be surrounded by digits",
|
||||
it.val)
|
||||
}
|
||||
val := strings.Replace(it.val, "_", "", -1)
|
||||
num, err := strconv.ParseInt(val, 10, 64)
|
||||
num, err := strconv.ParseInt(it.val, 10, 64)
|
||||
if err != nil {
|
||||
// Distinguish integer values. Normally, it'd be a bug if the lexer
|
||||
// provides an invalid integer, but it's possible that the number is
|
||||
// out of range of valid values (which the lexer cannot determine).
|
||||
// So mark the former as a bug but the latter as a legitimate user
|
||||
// error.
|
||||
// See comment below for floats describing why we make a
|
||||
// distinction between a bug and a user error.
|
||||
if e, ok := err.(*strconv.NumError); ok &&
|
||||
e.Err == strconv.ErrRange {
|
||||
|
||||
|
@ -201,57 +194,29 @@ func (p *parser) value(it item) (interface{}, tomlType) {
|
|||
}
|
||||
return num, p.typeOfPrimitive(it)
|
||||
case itemFloat:
|
||||
parts := strings.FieldsFunc(it.val, func(r rune) bool {
|
||||
switch r {
|
||||
case '.', 'e', 'E':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
for _, part := range parts {
|
||||
if !numUnderscoresOK(part) {
|
||||
p.panicf("Invalid float %q: underscores must be "+
|
||||
"surrounded by digits", it.val)
|
||||
}
|
||||
}
|
||||
if !numPeriodsOK(it.val) {
|
||||
// As a special case, numbers like '123.' or '1.e2',
|
||||
// which are valid as far as Go/strconv are concerned,
|
||||
// must be rejected because TOML says that a fractional
|
||||
// part consists of '.' followed by 1+ digits.
|
||||
p.panicf("Invalid float %q: '.' must be followed "+
|
||||
"by one or more digits", it.val)
|
||||
}
|
||||
val := strings.Replace(it.val, "_", "", -1)
|
||||
num, err := strconv.ParseFloat(val, 64)
|
||||
num, err := strconv.ParseFloat(it.val, 64)
|
||||
if err != nil {
|
||||
// Distinguish float values. Normally, it'd be a bug if the lexer
|
||||
// provides an invalid float, but it's possible that the float is
|
||||
// out of range of valid values (which the lexer cannot determine).
|
||||
// So mark the former as a bug but the latter as a legitimate user
|
||||
// error.
|
||||
//
|
||||
// This is also true for integers.
|
||||
if e, ok := err.(*strconv.NumError); ok &&
|
||||
e.Err == strconv.ErrRange {
|
||||
|
||||
p.panicf("Float '%s' is out of the range of 64-bit "+
|
||||
"IEEE-754 floating-point numbers.", it.val)
|
||||
} else {
|
||||
p.panicf("Invalid float value: %q", it.val)
|
||||
p.bug("Expected float value, but got '%s'.", it.val)
|
||||
}
|
||||
}
|
||||
return num, p.typeOfPrimitive(it)
|
||||
case itemDatetime:
|
||||
var t time.Time
|
||||
var ok bool
|
||||
var err error
|
||||
for _, format := range []string{
|
||||
"2006-01-02T15:04:05Z07:00",
|
||||
"2006-01-02T15:04:05",
|
||||
"2006-01-02",
|
||||
} {
|
||||
t, err = time.ParseInLocation(format, it.val, time.Local)
|
||||
if err == nil {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
p.panicf("Invalid TOML Datetime: %q.", it.val)
|
||||
t, err := time.Parse("2006-01-02T15:04:05Z", it.val)
|
||||
if err != nil {
|
||||
p.panicf("Invalid RFC3339 Zulu DateTime: '%s'.", it.val)
|
||||
}
|
||||
return t, p.typeOfPrimitive(it)
|
||||
case itemArray:
|
||||
|
@ -274,35 +239,6 @@ func (p *parser) value(it item) (interface{}, tomlType) {
|
|||
panic("unreachable")
|
||||
}
|
||||
|
||||
// numUnderscoresOK checks whether each underscore in s is surrounded by
|
||||
// characters that are not underscores.
|
||||
func numUnderscoresOK(s string) bool {
|
||||
accept := false
|
||||
for _, r := range s {
|
||||
if r == '_' {
|
||||
if !accept {
|
||||
return false
|
||||
}
|
||||
accept = false
|
||||
continue
|
||||
}
|
||||
accept = true
|
||||
}
|
||||
return accept
|
||||
}
|
||||
|
||||
// numPeriodsOK checks whether every period in s is followed by a digit.
|
||||
func numPeriodsOK(s string) bool {
|
||||
period := false
|
||||
for _, r := range s {
|
||||
if period && !isDigit(r) {
|
||||
return false
|
||||
}
|
||||
period = r == '.'
|
||||
}
|
||||
return !period
|
||||
}
|
||||
|
||||
// establishContext sets the current context of the parser,
|
||||
// where the context is either a hash or an array of hashes. Which one is
|
||||
// set depends on the value of the `array` parameter.
|
||||
|
|
9
vendor/github.com/BurntSushi/toml/type_fields.go
generated
vendored
9
vendor/github.com/BurntSushi/toml/type_fields.go
generated
vendored
|
@ -95,8 +95,8 @@ func typeFields(t reflect.Type) []field {
|
|||
if sf.PkgPath != "" && !sf.Anonymous { // unexported
|
||||
continue
|
||||
}
|
||||
opts := getOptions(sf.Tag)
|
||||
if opts.skip {
|
||||
name, _ := getOptions(sf.Tag.Get("toml"))
|
||||
if name == "-" {
|
||||
continue
|
||||
}
|
||||
index := make([]int, len(f.index)+1)
|
||||
|
@ -110,9 +110,8 @@ func typeFields(t reflect.Type) []field {
|
|||
}
|
||||
|
||||
// Record found field and index sequence.
|
||||
if opts.name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||
tagged := opts.name != ""
|
||||
name := opts.name
|
||||
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||
tagged := name != ""
|
||||
if name == "" {
|
||||
name = sf.Name
|
||||
}
|
||||
|
|
1
vendor/github.com/Sirupsen/logrus/.travis.yml
generated
vendored
1
vendor/github.com/Sirupsen/logrus/.travis.yml
generated
vendored
|
@ -3,7 +3,6 @@ go:
|
|||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- tip
|
||||
install:
|
||||
- go get -t ./...
|
||||
|
|
4
vendor/github.com/Sirupsen/logrus/README.md
generated
vendored
4
vendor/github.com/Sirupsen/logrus/README.md
generated
vendored
|
@ -218,7 +218,6 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
|
|||
| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
|
||||
| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
|
||||
| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
|
||||
| [Influxus] (http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB] (http://influxdata.com/) |
|
||||
| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
|
||||
| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
|
||||
| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
|
||||
|
@ -227,8 +226,7 @@ Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/v
|
|||
| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
|
||||
| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
|
||||
| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
|
||||
| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
|
||||
| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
|
||||
|
||||
|
||||
#### Level logging
|
||||
|
||||
|
|
15
vendor/github.com/Sirupsen/logrus/formatter.go
generated
vendored
15
vendor/github.com/Sirupsen/logrus/formatter.go
generated
vendored
|
@ -31,15 +31,18 @@ type Formatter interface {
|
|||
// It's not exported because it's still using Data in an opinionated way. It's to
|
||||
// avoid code duplication between the two default formatters.
|
||||
func prefixFieldClashes(data Fields) {
|
||||
if t, ok := data["time"]; ok {
|
||||
data["fields.time"] = t
|
||||
_, ok := data["time"]
|
||||
if ok {
|
||||
data["fields.time"] = data["time"]
|
||||
}
|
||||
|
||||
if m, ok := data["msg"]; ok {
|
||||
data["fields.msg"] = m
|
||||
_, ok = data["msg"]
|
||||
if ok {
|
||||
data["fields.msg"] = data["msg"]
|
||||
}
|
||||
|
||||
if l, ok := data["level"]; ok {
|
||||
data["fields.level"] = l
|
||||
_, ok = data["level"]
|
||||
if ok {
|
||||
data["fields.level"] = data["level"]
|
||||
}
|
||||
}
|
||||
|
|
8
vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go
generated
vendored
8
vendor/github.com/Sirupsen/logrus/formatters/logstash/logstash.go
generated
vendored
|
@ -24,13 +24,11 @@ func (f *LogstashFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
|||
|
||||
fields["@version"] = 1
|
||||
|
||||
timeStampFormat := f.TimestampFormat
|
||||
|
||||
if timeStampFormat == "" {
|
||||
timeStampFormat = logrus.DefaultTimestampFormat
|
||||
if f.TimestampFormat == "" {
|
||||
f.TimestampFormat = logrus.DefaultTimestampFormat
|
||||
}
|
||||
|
||||
fields["@timestamp"] = entry.Time.Format(timeStampFormat)
|
||||
fields["@timestamp"] = entry.Time.Format(f.TimestampFormat)
|
||||
|
||||
// set message field
|
||||
v, ok := entry.Data["message"]
|
||||
|
|
8
vendor/github.com/Sirupsen/logrus/text_formatter.go
generated
vendored
8
vendor/github.com/Sirupsen/logrus/text_formatter.go
generated
vendored
|
@ -128,10 +128,10 @@ func needsQuoting(text string) bool {
|
|||
(ch >= 'A' && ch <= 'Z') ||
|
||||
(ch >= '0' && ch <= '9') ||
|
||||
ch == '-' || ch == '.') {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
|
||||
|
@ -141,14 +141,14 @@ func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interf
|
|||
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
if !needsQuoting(value) {
|
||||
if needsQuoting(value) {
|
||||
b.WriteString(value)
|
||||
} else {
|
||||
fmt.Fprintf(b, "%q", value)
|
||||
}
|
||||
case error:
|
||||
errmsg := value.Error()
|
||||
if !needsQuoting(errmsg) {
|
||||
if needsQuoting(errmsg) {
|
||||
b.WriteString(errmsg)
|
||||
} else {
|
||||
fmt.Fprintf(b, "%q", value)
|
||||
|
|
28
vendor/github.com/Sirupsen/logrus/writer.go
generated
vendored
28
vendor/github.com/Sirupsen/logrus/writer.go
generated
vendored
|
@ -7,40 +7,18 @@ import (
|
|||
)
|
||||
|
||||
func (logger *Logger) Writer() *io.PipeWriter {
|
||||
return logger.WriterLevel(InfoLevel)
|
||||
}
|
||||
|
||||
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
|
||||
reader, writer := io.Pipe()
|
||||
|
||||
var printFunc func(args ...interface{})
|
||||
switch level {
|
||||
case DebugLevel:
|
||||
printFunc = logger.Debug
|
||||
case InfoLevel:
|
||||
printFunc = logger.Info
|
||||
case WarnLevel:
|
||||
printFunc = logger.Warn
|
||||
case ErrorLevel:
|
||||
printFunc = logger.Error
|
||||
case FatalLevel:
|
||||
printFunc = logger.Fatal
|
||||
case PanicLevel:
|
||||
printFunc = logger.Panic
|
||||
default:
|
||||
printFunc = logger.Print
|
||||
}
|
||||
|
||||
go logger.writerScanner(reader, printFunc)
|
||||
go logger.writerScanner(reader)
|
||||
runtime.SetFinalizer(writer, writerFinalizer)
|
||||
|
||||
return writer
|
||||
}
|
||||
|
||||
func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) {
|
||||
func (logger *Logger) writerScanner(reader *io.PipeReader) {
|
||||
scanner := bufio.NewScanner(reader)
|
||||
for scanner.Scan() {
|
||||
printFunc(scanner.Text())
|
||||
logger.Print(scanner.Text())
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
logger.Errorf("Error while reading from Writer: %s", err)
|
||||
|
|
6
vendor/github.com/antonholmquist/jason/README.md
generated
vendored
6
vendor/github.com/antonholmquist/jason/README.md
generated
vendored
|
@ -45,7 +45,7 @@ v, err := jason.NewObjectFromBytes(b)
|
|||
|
||||
```
|
||||
|
||||
If the root object is unknown or not an object, use `NewValueFromBytes` instead. It can then be typecasted using one of the conversion methods provided by the library, for instance `Array()` or `String()`.
|
||||
If the root object is not an array, use this method instead. It can then be cased to the expected type with one of the As-Methods.
|
||||
|
||||
```go
|
||||
v, err := jason.NewValueFromBytes(b)
|
||||
|
@ -174,7 +174,7 @@ func main() {
|
|||
|
||||
## Documentation
|
||||
|
||||
Documentation can be found on godoc:
|
||||
Documentation can be found a godoc:
|
||||
|
||||
https://godoc.org/github.com/antonholmquist/jason
|
||||
|
||||
|
@ -191,7 +191,7 @@ Go 1.1 and up.
|
|||
|
||||
## Where does the name come from?
|
||||
|
||||
I remembered it from an email one of our projects managers sent a couple of years ago.
|
||||
I remebered it from an email one of our projects managers sent a couple of years ago.
|
||||
|
||||
> "Don't worry. We can handle both XML and Jason"
|
||||
|
||||
|
|
114
vendor/github.com/antonholmquist/jason/jason.go
generated
vendored
114
vendor/github.com/antonholmquist/jason/jason.go
generated
vendored
|
@ -50,33 +50,9 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Error values returned when validation functions fail
|
||||
var (
|
||||
ErrNotNull = errors.New("is not null")
|
||||
ErrNotArray = errors.New("Not an array")
|
||||
ErrNotNumber = errors.New("not a number")
|
||||
ErrNotBool = errors.New("no bool")
|
||||
ErrNotObject = errors.New("not an object")
|
||||
ErrNotObjectArray = errors.New("not an object array")
|
||||
ErrNotString = errors.New("not a string")
|
||||
)
|
||||
|
||||
type KeyNotFoundError struct {
|
||||
Key string
|
||||
}
|
||||
|
||||
func (k KeyNotFoundError) Error() string {
|
||||
if k.Key != "" {
|
||||
return fmt.Sprintf("key '%s' not found", k.Key)
|
||||
}
|
||||
|
||||
return "key not found"
|
||||
}
|
||||
|
||||
// Value represents an arbitrary JSON value.
|
||||
// It may contain a bool, number, string, object, array or null.
|
||||
type Value struct {
|
||||
|
@ -145,11 +121,6 @@ func (v *Value) Marshal() ([]byte, error) {
|
|||
return json.Marshal(v.data)
|
||||
}
|
||||
|
||||
// Get the interyling data as interface
|
||||
func (v *Value) Interface() interface{} {
|
||||
return v.data
|
||||
}
|
||||
|
||||
// Private Get
|
||||
func (v *Value) get(key string) (*Value, error) {
|
||||
|
||||
|
@ -161,7 +132,7 @@ func (v *Value) get(key string) (*Value, error) {
|
|||
if ok {
|
||||
return child, nil
|
||||
} else {
|
||||
return nil, KeyNotFoundError{key}
|
||||
return nil, errors.New("key not found")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,6 +182,8 @@ func (v *Object) GetObject(keys ...string) (*Object, error) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into a string.
|
||||
|
@ -225,6 +198,8 @@ func (v *Object) GetString(keys ...string) (string, error) {
|
|||
} else {
|
||||
return child.String()
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into null.
|
||||
|
@ -260,6 +235,8 @@ func (v *Object) GetNumber(keys ...string) (json.Number, error) {
|
|||
return n, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into a float64.
|
||||
|
@ -281,6 +258,8 @@ func (v *Object) GetFloat64(keys ...string) (float64, error) {
|
|||
return n, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into a float64.
|
||||
|
@ -302,20 +281,8 @@ func (v *Object) GetInt64(keys ...string) (int64, error) {
|
|||
return n, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into a float64.
|
||||
// Returns error if the value is not a json number.
|
||||
// Example:
|
||||
// v, err := GetInterface("address", "anything")
|
||||
func (v *Object) GetInterface(keys ...string) (interface{}, error) {
|
||||
child, err := v.getPath(keys)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return child.Interface(), nil
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into a bool.
|
||||
|
@ -350,6 +317,8 @@ func (v *Object) GetValueArray(keys ...string) ([]*Value, error) {
|
|||
return child.Array()
|
||||
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into an array of objects.
|
||||
|
@ -388,6 +357,8 @@ func (v *Object) GetObjectArray(keys ...string) ([]*Object, error) {
|
|||
return typedArray, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into an array of string.
|
||||
|
@ -427,6 +398,7 @@ func (v *Object) GetStringArray(keys ...string) ([]string, error) {
|
|||
return typedArray, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into an array of numbers.
|
||||
|
@ -464,6 +436,7 @@ func (v *Object) GetNumberArray(keys ...string) ([]json.Number, error) {
|
|||
return typedArray, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into an array of floats.
|
||||
|
@ -496,6 +469,7 @@ func (v *Object) GetFloat64Array(keys ...string) ([]float64, error) {
|
|||
return typedArray, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into an array of ints.
|
||||
|
@ -528,6 +502,7 @@ func (v *Object) GetInt64Array(keys ...string) ([]int64, error) {
|
|||
return typedArray, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into an array of bools.
|
||||
|
@ -560,6 +535,7 @@ func (v *Object) GetBooleanArray(keys ...string) ([]bool, error) {
|
|||
return typedArray, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gets the value at key path and attempts to typecast the value into an array of nulls.
|
||||
|
@ -592,6 +568,8 @@ func (v *Object) GetNullArray(keys ...string) (int64, error) {
|
|||
return length, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Returns an error if the value is not actually null
|
||||
|
@ -609,7 +587,7 @@ func (v *Value) Null() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
return ErrNotNull
|
||||
return errors.New("is not null")
|
||||
|
||||
}
|
||||
|
||||
|
@ -640,7 +618,7 @@ func (v *Value) Array() ([]*Value, error) {
|
|||
return slice, nil
|
||||
}
|
||||
|
||||
return slice, ErrNotArray
|
||||
return slice, errors.New("Not an array")
|
||||
|
||||
}
|
||||
|
||||
|
@ -662,7 +640,7 @@ func (v *Value) Number() (json.Number, error) {
|
|||
return v.data.(json.Number), nil
|
||||
}
|
||||
|
||||
return "", ErrNotNumber
|
||||
return "", errors.New("not a number")
|
||||
}
|
||||
|
||||
// Attempts to typecast the current value into a float64.
|
||||
|
@ -711,7 +689,7 @@ func (v *Value) Boolean() (bool, error) {
|
|||
return v.data.(bool), nil
|
||||
}
|
||||
|
||||
return false, ErrNotBool
|
||||
return false, errors.New("no bool")
|
||||
}
|
||||
|
||||
// Attempts to typecast the current value into an object.
|
||||
|
@ -736,6 +714,7 @@ func (v *Value) Object() (*Object, error) {
|
|||
m := make(map[string]*Value)
|
||||
|
||||
if valid {
|
||||
|
||||
for key, element := range v.data.(map[string]interface{}) {
|
||||
m[key] = &Value{element, true}
|
||||
|
||||
|
@ -748,44 +727,7 @@ func (v *Value) Object() (*Object, error) {
|
|||
return obj, nil
|
||||
}
|
||||
|
||||
return nil, ErrNotObject
|
||||
}
|
||||
|
||||
// Attempts to typecast the current value into an object arrau.
|
||||
// Returns error if the current value is not an array of json objects
|
||||
// Example:
|
||||
// friendObjects, err := friendValues.ObjectArray()
|
||||
func (v *Value) ObjectArray() ([]*Object, error) {
|
||||
|
||||
var valid bool
|
||||
|
||||
// Check the type of this data
|
||||
switch v.data.(type) {
|
||||
case []interface{}:
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
|
||||
// Unsure if this is a good way to use slices, it's probably not
|
||||
var slice []*Object
|
||||
|
||||
if valid {
|
||||
|
||||
for _, element := range v.data.([]interface{}) {
|
||||
childValue := Value{element, true}
|
||||
childObject, err := childValue.Object()
|
||||
|
||||
if err != nil {
|
||||
return nil, ErrNotObjectArray
|
||||
}
|
||||
slice = append(slice, childObject)
|
||||
}
|
||||
|
||||
return slice, nil
|
||||
}
|
||||
|
||||
return nil, ErrNotObjectArray
|
||||
|
||||
return nil, errors.New("not an object")
|
||||
}
|
||||
|
||||
// Attempts to typecast the current value into a string.
|
||||
|
@ -806,7 +748,7 @@ func (v *Value) String() (string, error) {
|
|||
return v.data.(string), nil
|
||||
}
|
||||
|
||||
return "", ErrNotString
|
||||
return "", errors.New("not a string")
|
||||
}
|
||||
|
||||
// Returns the value a json formatted string.
|
||||
|
|
66
vendor/github.com/antonholmquist/jason/jason_test.go
generated
vendored
66
vendor/github.com/antonholmquist/jason/jason_test.go
generated
vendored
|
@ -73,19 +73,12 @@ func TestFirst(t *testing.T) {
|
|||
//log.Println("s: ", s.String())
|
||||
|
||||
_, err = j.GetNumber("age")
|
||||
log.Println("error: ", err)
|
||||
assert.True(err == nil, "age should be a number")
|
||||
|
||||
n, err := j.GetInt64("age")
|
||||
assert.True(n == 29 && err == nil, "age mismatch")
|
||||
|
||||
ageInterface, err := j.GetInterface("age")
|
||||
assert.True(ageInterface != nil, "should be defined")
|
||||
assert.True(err == nil, "age interface error")
|
||||
|
||||
invalidInterface, err := j.GetInterface("not_existing")
|
||||
assert.True(invalidInterface == nil, "should not give error here")
|
||||
assert.True(err != nil, "should give error here")
|
||||
|
||||
age, err := j.GetValue("age")
|
||||
assert.True(age != nil && err == nil, "age should exist")
|
||||
|
||||
|
@ -127,13 +120,6 @@ func TestFirst(t *testing.T) {
|
|||
assert.True(err == nil, "List2 should not return error on AsArray")
|
||||
assert.True(len(list2Array) == 2, "List2 should should have length 2")
|
||||
|
||||
list2Value, err := j.GetValue("list2")
|
||||
assert.True(err == nil, "List2 should not return error on value")
|
||||
|
||||
list2ObjectArray, err := list2Value.ObjectArray()
|
||||
assert.True(err == nil, "list2Value should not return error on ObjectArray")
|
||||
assert.True(len(list2ObjectArray) == 2, "list2ObjectArray should should have length 2")
|
||||
|
||||
for _, elementValue := range list2Array {
|
||||
//assert.True(element.IsObject() == true, "first fail")
|
||||
|
||||
|
@ -243,53 +229,3 @@ func TestSecond(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
json := `
|
||||
{
|
||||
"string": "hello",
|
||||
"number": 1,
|
||||
"array": [1,2,3]
|
||||
}`
|
||||
|
||||
errstr := "expected an error getting %s, but got '%s'"
|
||||
|
||||
j, err := NewObjectFromBytes([]byte(json))
|
||||
if err != nil {
|
||||
t.Fatal("failed to parse json")
|
||||
}
|
||||
|
||||
if _, err = j.GetObject("string"); err != ErrNotObject {
|
||||
t.Errorf(errstr, "object", err)
|
||||
}
|
||||
|
||||
if err = j.GetNull("string"); err != ErrNotNull {
|
||||
t.Errorf(errstr, "null", err)
|
||||
}
|
||||
|
||||
if _, err = j.GetStringArray("string"); err != ErrNotArray {
|
||||
t.Errorf(errstr, "array", err)
|
||||
}
|
||||
|
||||
if _, err = j.GetStringArray("array"); err != ErrNotString {
|
||||
t.Errorf(errstr, "string array", err)
|
||||
}
|
||||
|
||||
if _, err = j.GetNumber("array"); err != ErrNotNumber {
|
||||
t.Errorf(errstr, "number", err)
|
||||
}
|
||||
|
||||
if _, err = j.GetBoolean("array"); err != ErrNotBool {
|
||||
t.Errorf(errstr, "boolean", err)
|
||||
}
|
||||
|
||||
if _, err = j.GetString("number"); err != ErrNotString {
|
||||
t.Errorf(errstr, "string", err)
|
||||
}
|
||||
|
||||
_, err = j.GetString("not_found")
|
||||
if e, ok := err.(KeyNotFoundError); !ok {
|
||||
t.Errorf(errstr, "key not found error", e)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
6
vendor/github.com/nicksnyder/go-i18n/.gitignore
generated
vendored
Normal file
6
vendor/github.com/nicksnyder/go-i18n/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
*.a
|
||||
_*
|
||||
output/
|
||||
.DS_Store
|
||||
*.test
|
||||
*.swp
|
8
vendor/github.com/nicksnyder/go-i18n/.travis.yml
generated
vendored
Normal file
8
vendor/github.com/nicksnyder/go-i18n/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
language: go
|
||||
sudo: false
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- tip
|
5
vendor/github.com/nicksnyder/go-i18n/CHANGELOG
generated
vendored
Normal file
5
vendor/github.com/nicksnyder/go-i18n/CHANGELOG
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
Feb 24, 2015
|
||||
- Add Korean
|
||||
|
||||
Feb 18, 2015
|
||||
- Added ParseTranslationFileBytes so translation files may be loaded from an arbitrary serialization format, such as go-bindata.
|
19
vendor/github.com/nicksnyder/go-i18n/LICENSE
generated
vendored
Normal file
19
vendor/github.com/nicksnyder/go-i18n/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2014 Nick Snyder https://github.com/nicksnyder
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
130
vendor/github.com/nicksnyder/go-i18n/README.md
generated
vendored
Normal file
130
vendor/github.com/nicksnyder/go-i18n/README.md
generated
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
go-i18n [![Build Status](https://secure.travis-ci.org/nicksnyder/go-i18n.png?branch=master)](http://travis-ci.org/nicksnyder/go-i18n)
|
||||
=======
|
||||
|
||||
go-i18n is a Go [package](#i18n-package) and a [command](#goi18n-command) that helps you translate Go programs into multiple languages.
|
||||
* Supports [pluralized strings](http://cldr.unicode.org/index/cldr-spec/plural-rules) for all 200+ languages in the [Unicode Common Locale Data Repository (CLDR)](http://www.unicode.org/cldr/charts/28/supplemental/language_plural_rules.html).
|
||||
* Code and tests are [automatically generated](https://github.com/nicksnyder/go-i18n/tree/master/i18n/language/codegen) from [CLDR data](http://cldr.unicode.org/index/downloads)
|
||||
* Supports strings with named variables using [text/template](http://golang.org/pkg/text/template/) syntax.
|
||||
* Translation files are simple JSON or YAML.
|
||||
* [Documented](http://godoc.org/github.com/nicksnyder/go-i18n) and [tested](https://travis-ci.org/nicksnyder/go-i18n)!
|
||||
|
||||
Package i18n [![GoDoc](http://godoc.org/github.com/nicksnyder/go-i18n?status.png)](http://godoc.org/github.com/nicksnyder/go-i18n/i18n)
|
||||
------------
|
||||
|
||||
The i18n package provides runtime APIs for fetching translated strings.
|
||||
|
||||
Command goi18n [![GoDoc](http://godoc.org/github.com/nicksnyder/go-i18n?status.png)](http://godoc.org/github.com/nicksnyder/go-i18n/goi18n)
|
||||
--------------
|
||||
|
||||
The goi18n command provides functionality for managing the translation process.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Make sure you have [setup GOPATH](http://golang.org/doc/code.html#GOPATH).
|
||||
|
||||
go get -u github.com/nicksnyder/go-i18n/goi18n
|
||||
goi18n -help
|
||||
|
||||
Workflow
|
||||
--------
|
||||
|
||||
A typical workflow looks like this:
|
||||
|
||||
1. Add a new string to your source code.
|
||||
|
||||
```go
|
||||
T("settings_title")
|
||||
```
|
||||
|
||||
2. Add the string to en-US.all.json
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "settings_title",
|
||||
"translation": "Settings"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
3. Run goi18n
|
||||
|
||||
```
|
||||
goi18n path/to/*.all.json
|
||||
```
|
||||
|
||||
4. Send `path/to/*.untranslated.json` to get translated.
|
||||
5. Run goi18n again to merge the translations
|
||||
|
||||
```sh
|
||||
goi18n path/to/*.all.json path/to/*.untranslated.json
|
||||
```
|
||||
|
||||
Translation files
|
||||
-----------------
|
||||
|
||||
A translation file stores translated and untranslated strings.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"one": "{{.Count}} day",
|
||||
"other": "{{.Count}} days"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "my_height_in_meters",
|
||||
"translation": {
|
||||
"one": "I am {{.Count}} meter tall.",
|
||||
"other": "I am {{.Count}} meters tall."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "Hello {{.Person}}"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": "Hello world"
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"one": "You have {{.Count}} unread email.",
|
||||
"other": "You have {{.Count}} unread emails."
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Contributions
|
||||
-------------
|
||||
|
||||
If you would like to submit a pull request, please
|
||||
|
||||
1. Write tests
|
||||
2. Format code with [goimports](https://github.com/bradfitz/goimports).
|
||||
3. Read the [common code review comments](https://github.com/golang/go/wiki/CodeReviewComments).
|
||||
|
||||
License
|
||||
-------
|
||||
go-i18n is available under the MIT license. See the [LICENSE](LICENSE) file for more info.
|
59
vendor/github.com/nicksnyder/go-i18n/goi18n/doc.go
generated
vendored
Normal file
59
vendor/github.com/nicksnyder/go-i18n/goi18n/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
// The goi18n command formats and merges translation files.
|
||||
//
|
||||
// go get -u github.com/nicksnyder/go-i18n/goi18n
|
||||
// goi18n -help
|
||||
//
|
||||
// Help documentation:
|
||||
//
|
||||
// goi18n formats and merges translation files.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// goi18n [options] [files...]
|
||||
//
|
||||
// Translation files:
|
||||
//
|
||||
// A translation file contains the strings and translations for a single language.
|
||||
//
|
||||
// Translation file names must have a suffix of a supported format (e.g. .json) and
|
||||
// contain a valid language tag as defined by RFC 5646 (e.g. en-us, fr, zh-hant, etc.).
|
||||
//
|
||||
// For each language represented by at least one input translation file, goi18n will produce 2 output files:
|
||||
//
|
||||
// xx-yy.all.format
|
||||
// This file contains all strings for the language (translated and untranslated).
|
||||
// Use this file when loading strings at runtime.
|
||||
//
|
||||
// xx-yy.untranslated.format
|
||||
// This file contains the strings that have not been translated for this language.
|
||||
// The translations for the strings in this file will be extracted from the source language.
|
||||
// After they are translated, merge them back into xx-yy.all.format using goi18n.
|
||||
//
|
||||
// Merging:
|
||||
//
|
||||
// goi18n will merge multiple translation files for the same language.
|
||||
// Duplicate translations will be merged into the existing translation.
|
||||
// Non-empty fields in the duplicate translation will overwrite those fields in the existing translation.
|
||||
// Empty fields in the duplicate translation are ignored.
|
||||
//
|
||||
// Adding a new language:
|
||||
//
|
||||
// To produce translation files for a new language, create an empty translation file with the
|
||||
// appropriate name and pass it in to goi18n.
|
||||
//
|
||||
// Options:
|
||||
//
|
||||
// -sourceLanguage tag
|
||||
// goi18n uses the strings from this language to seed the translations for other languages.
|
||||
// Default: en-us
|
||||
//
|
||||
// -outdir directory
|
||||
// goi18n writes the output translation files to this directory.
|
||||
// Default: .
|
||||
//
|
||||
// -format format
|
||||
// goi18n encodes the output translation files in this format.
|
||||
// Supported formats: json, yaml
|
||||
// Default: json
|
||||
//
|
||||
package main
|
10
vendor/github.com/nicksnyder/go-i18n/goi18n/gendoc.sh
generated
vendored
Normal file
10
vendor/github.com/nicksnyder/go-i18n/goi18n/gendoc.sh
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
go install
|
||||
echo "// The goi18n command formats and merges translation files." > doc.go
|
||||
echo "//" >> doc.go
|
||||
echo "// go get -u github.com/nicksnyder/go-i18n/goi18n" >> doc.go
|
||||
echo "// goi18n -help" >> doc.go
|
||||
echo "//" >> doc.go
|
||||
echo "// Help documentation:" >> doc.go
|
||||
echo "//" >> doc.go
|
||||
goi18n -help | sed -e 's/^/\/\/ /' >> doc.go
|
||||
echo "package main" >> doc.go
|
82
vendor/github.com/nicksnyder/go-i18n/goi18n/goi18n.go
generated
vendored
Normal file
82
vendor/github.com/nicksnyder/go-i18n/goi18n/goi18n.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func usage() {
|
||||
fmt.Printf(`goi18n formats and merges translation files.
|
||||
|
||||
Usage:
|
||||
|
||||
goi18n [options] [files...]
|
||||
|
||||
Translation files:
|
||||
|
||||
A translation file contains the strings and translations for a single language.
|
||||
|
||||
Translation file names must have a suffix of a supported format (e.g. .json) and
|
||||
contain a valid language tag as defined by RFC 5646 (e.g. en-us, fr, zh-hant, etc.).
|
||||
|
||||
For each language represented by at least one input translation file, goi18n will produce 2 output files:
|
||||
|
||||
xx-yy.all.format
|
||||
This file contains all strings for the language (translated and untranslated).
|
||||
Use this file when loading strings at runtime.
|
||||
|
||||
xx-yy.untranslated.format
|
||||
This file contains the strings that have not been translated for this language.
|
||||
The translations for the strings in this file will be extracted from the source language.
|
||||
After they are translated, merge them back into xx-yy.all.format using goi18n.
|
||||
|
||||
Merging:
|
||||
|
||||
goi18n will merge multiple translation files for the same language.
|
||||
Duplicate translations will be merged into the existing translation.
|
||||
Non-empty fields in the duplicate translation will overwrite those fields in the existing translation.
|
||||
Empty fields in the duplicate translation are ignored.
|
||||
|
||||
Adding a new language:
|
||||
|
||||
To produce translation files for a new language, create an empty translation file with the
|
||||
appropriate name and pass it in to goi18n.
|
||||
|
||||
Options:
|
||||
|
||||
-sourceLanguage tag
|
||||
goi18n uses the strings from this language to seed the translations for other languages.
|
||||
Default: en-us
|
||||
|
||||
-outdir directory
|
||||
goi18n writes the output translation files to this directory.
|
||||
Default: .
|
||||
|
||||
-format format
|
||||
goi18n encodes the output translation files in this format.
|
||||
Supported formats: json, yaml
|
||||
Default: json
|
||||
|
||||
`)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
sourceLanguage := flag.String("sourceLanguage", "en-us", "")
|
||||
outdir := flag.String("outdir", ".", "")
|
||||
format := flag.String("format", "json", "")
|
||||
flag.Parse()
|
||||
|
||||
mc := &mergeCommand{
|
||||
translationFiles: flag.Args(),
|
||||
sourceLanguageTag: *sourceLanguage,
|
||||
outdir: *outdir,
|
||||
format: *format,
|
||||
}
|
||||
if err := mc.execute(); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
127
vendor/github.com/nicksnyder/go-i18n/goi18n/merge.go
generated
vendored
Normal file
127
vendor/github.com/nicksnyder/go-i18n/goi18n/merge.go
generated
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/nicksnyder/go-i18n/i18n/bundle"
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
"github.com/nicksnyder/go-i18n/i18n/translation"
|
||||
)
|
||||
|
||||
type mergeCommand struct {
|
||||
translationFiles []string
|
||||
sourceLanguageTag string
|
||||
outdir string
|
||||
format string
|
||||
}
|
||||
|
||||
func (mc *mergeCommand) execute() error {
|
||||
if len(mc.translationFiles) < 1 {
|
||||
return fmt.Errorf("need at least one translation file to parse")
|
||||
}
|
||||
|
||||
if lang := language.Parse(mc.sourceLanguageTag); lang == nil {
|
||||
return fmt.Errorf("invalid source locale: %s", mc.sourceLanguageTag)
|
||||
}
|
||||
|
||||
marshal, err := newMarshalFunc(mc.format)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle := bundle.New()
|
||||
for _, tf := range mc.translationFiles {
|
||||
if err := bundle.LoadTranslationFile(tf); err != nil {
|
||||
return fmt.Errorf("failed to load translation file %s because %s\n", tf, err)
|
||||
}
|
||||
}
|
||||
|
||||
translations := bundle.Translations()
|
||||
sourceLanguageTag := language.NormalizeTag(mc.sourceLanguageTag)
|
||||
sourceTranslations := translations[sourceLanguageTag]
|
||||
if sourceTranslations == nil {
|
||||
return fmt.Errorf("no translations found for source locale %s", sourceLanguageTag)
|
||||
}
|
||||
for translationID, src := range sourceTranslations {
|
||||
for _, localeTranslations := range translations {
|
||||
if dst := localeTranslations[translationID]; dst == nil || reflect.TypeOf(src) != reflect.TypeOf(dst) {
|
||||
localeTranslations[translationID] = src.UntranslatedCopy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for localeID, localeTranslations := range translations {
|
||||
lang := language.MustParse(localeID)[0]
|
||||
all := filter(localeTranslations, func(t translation.Translation) translation.Translation {
|
||||
return t.Normalize(lang)
|
||||
})
|
||||
if err := mc.writeFile("all", all, localeID, marshal); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
untranslated := filter(localeTranslations, func(t translation.Translation) translation.Translation {
|
||||
if t.Incomplete(lang) {
|
||||
return t.Normalize(lang).Backfill(sourceTranslations[t.ID()])
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err := mc.writeFile("untranslated", untranslated, localeID, marshal); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type marshalFunc func(interface{}) ([]byte, error)
|
||||
|
||||
func (mc *mergeCommand) writeFile(label string, translations []translation.Translation, localeID string, marshal marshalFunc) error {
|
||||
sort.Sort(translation.SortableByID(translations))
|
||||
buf, err := marshal(marshalInterface(translations))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal %s strings to %s because %s", localeID, mc.format, err)
|
||||
}
|
||||
filename := filepath.Join(mc.outdir, fmt.Sprintf("%s.%s.%s", localeID, label, mc.format))
|
||||
if err := ioutil.WriteFile(filename, buf, 0666); err != nil {
|
||||
return fmt.Errorf("failed to write %s because %s", filename, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func filter(translations map[string]translation.Translation, filter func(translation.Translation) translation.Translation) []translation.Translation {
|
||||
filtered := make([]translation.Translation, 0, len(translations))
|
||||
for _, translation := range translations {
|
||||
if t := filter(translation); t != nil {
|
||||
filtered = append(filtered, t)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
|
||||
}
|
||||
|
||||
func newMarshalFunc(format string) (marshalFunc, error) {
|
||||
switch format {
|
||||
case "json":
|
||||
return func(v interface{}) ([]byte, error) {
|
||||
return json.MarshalIndent(v, "", " ")
|
||||
}, nil
|
||||
case "yaml":
|
||||
return func(v interface{}) ([]byte, error) {
|
||||
return yaml.Marshal(v)
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported format: %s\n", format)
|
||||
}
|
||||
|
||||
func marshalInterface(translations []translation.Translation) []interface{} {
|
||||
mi := make([]interface{}, len(translations))
|
||||
for i, translation := range translations {
|
||||
mi[i] = translation.MarshalInterface()
|
||||
}
|
||||
return mi
|
||||
}
|
74
vendor/github.com/nicksnyder/go-i18n/goi18n/merge_test.go
generated
vendored
Normal file
74
vendor/github.com/nicksnyder/go-i18n/goi18n/merge_test.go
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMergeExecuteJSON(t *testing.T) {
|
||||
files := []string{
|
||||
"testdata/input/en-us.one.json",
|
||||
"testdata/input/en-us.two.json",
|
||||
"testdata/input/fr-fr.json",
|
||||
"testdata/input/ar-ar.one.json",
|
||||
"testdata/input/ar-ar.two.json",
|
||||
}
|
||||
testMergeExecute(t, files)
|
||||
}
|
||||
|
||||
func TestMergeExecuteYAML(t *testing.T) {
|
||||
files := []string{
|
||||
"testdata/input/yaml/en-us.one.yaml",
|
||||
"testdata/input/yaml/en-us.two.json",
|
||||
"testdata/input/yaml/fr-fr.json",
|
||||
"testdata/input/yaml/ar-ar.one.json",
|
||||
"testdata/input/yaml/ar-ar.two.json",
|
||||
}
|
||||
testMergeExecute(t, files)
|
||||
}
|
||||
|
||||
func testMergeExecute(t *testing.T, files []string) {
|
||||
resetDir(t, "testdata/output")
|
||||
|
||||
mc := &mergeCommand{
|
||||
translationFiles: files,
|
||||
sourceLanguageTag: "en-us",
|
||||
outdir: "testdata/output",
|
||||
format: "json",
|
||||
}
|
||||
if err := mc.execute(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expectEqualFiles(t, "testdata/output/en-us.all.json", "testdata/expected/en-us.all.json")
|
||||
expectEqualFiles(t, "testdata/output/ar-ar.all.json", "testdata/expected/ar-ar.all.json")
|
||||
expectEqualFiles(t, "testdata/output/fr-fr.all.json", "testdata/expected/fr-fr.all.json")
|
||||
expectEqualFiles(t, "testdata/output/en-us.untranslated.json", "testdata/expected/en-us.untranslated.json")
|
||||
expectEqualFiles(t, "testdata/output/ar-ar.untranslated.json", "testdata/expected/ar-ar.untranslated.json")
|
||||
expectEqualFiles(t, "testdata/output/fr-fr.untranslated.json", "testdata/expected/fr-fr.untranslated.json")
|
||||
}
|
||||
|
||||
func resetDir(t *testing.T, dir string) {
|
||||
if err := os.RemoveAll(dir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Mkdir(dir, 0777); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func expectEqualFiles(t *testing.T, expectedName, actualName string) {
|
||||
actual, err := ioutil.ReadFile(actualName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected, err := ioutil.ReadFile(expectedName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(actual, expected) {
|
||||
t.Fatalf("contents of files did not match: %s, %s", expectedName, actualName)
|
||||
}
|
||||
}
|
30
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/en-us.yaml
generated
vendored
Normal file
30
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/en-us.yaml
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
- id: program_greeting
|
||||
translation: "Hello world"
|
||||
|
||||
- id: person_greeting
|
||||
translation: "Hello {{.Person}}"
|
||||
|
||||
- id: my_height_in_meters
|
||||
translation:
|
||||
one: "I am {{.Count}} meter tall."
|
||||
other: "I am {{.Count}} meters tall."
|
||||
|
||||
- id: your_unread_email_count
|
||||
translation:
|
||||
one: "You have {{.Count}} unread email."
|
||||
other: "You have {{.Count}} unread emails."
|
||||
|
||||
- id: person_unread_email_count
|
||||
translation:
|
||||
one: "{{.Person}} has {{.Count}} unread email."
|
||||
other: "{{.Person}} has {{.Count}} unread emails."
|
||||
|
||||
- id: person_unread_email_count_timeframe
|
||||
translation:
|
||||
one: "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}."
|
||||
other: "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
|
||||
- id: d_days
|
||||
translation:
|
||||
one: "{{.Count}} day"
|
||||
other: "{{.Count}} days"
|
65
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/ar-ar.all.json
generated
vendored
Normal file
65
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/ar-ar.all.json
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"few": "new arabic few translation of d_days",
|
||||
"many": "arabic many translation of d_days",
|
||||
"one": "arabic one translation of d_days",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "my_height_in_meters",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "new arabic translation of person_greeting"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"few": "arabic few translation of person_unread_email_count",
|
||||
"many": "arabic many translation of person_unread_email_count",
|
||||
"one": "arabic one translation of person_unread_email_count",
|
||||
"other": "arabic other translation of person_unread_email_count",
|
||||
"two": "arabic two translation of person_unread_email_count",
|
||||
"zero": "arabic zero translation of person_unread_email_count"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": ""
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
}
|
||||
]
|
50
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/ar-ar.untranslated.json
generated
vendored
Normal file
50
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/ar-ar.untranslated.json
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"few": "new arabic few translation of d_days",
|
||||
"many": "arabic many translation of d_days",
|
||||
"one": "arabic one translation of d_days",
|
||||
"other": "{{.Count}} days",
|
||||
"two": "{{.Count}} days",
|
||||
"zero": "{{.Count}} days"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "my_height_in_meters",
|
||||
"translation": {
|
||||
"few": "I am {{.Count}} meters tall.",
|
||||
"many": "I am {{.Count}} meters tall.",
|
||||
"one": "I am {{.Count}} meters tall.",
|
||||
"other": "I am {{.Count}} meters tall.",
|
||||
"two": "I am {{.Count}} meters tall.",
|
||||
"zero": "I am {{.Count}} meters tall."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"few": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}.",
|
||||
"many": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}.",
|
||||
"one": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}.",
|
||||
"two": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}.",
|
||||
"zero": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": "Hello world"
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"few": "You have {{.Count}} unread emails.",
|
||||
"many": "You have {{.Count}} unread emails.",
|
||||
"one": "You have {{.Count}} unread emails.",
|
||||
"other": "You have {{.Count}} unread emails.",
|
||||
"two": "You have {{.Count}} unread emails.",
|
||||
"zero": "You have {{.Count}} unread emails."
|
||||
}
|
||||
}
|
||||
]
|
45
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/en-us.all.json
generated
vendored
Normal file
45
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/en-us.all.json
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"one": "{{.Count}} day",
|
||||
"other": "{{.Count}} days"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "my_height_in_meters",
|
||||
"translation": {
|
||||
"one": "I am {{.Count}} meter tall.",
|
||||
"other": "I am {{.Count}} meters tall."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "Hello {{.Person}}"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": "Hello world"
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"one": "You have {{.Count}} unread email.",
|
||||
"other": "You have {{.Count}} unread emails."
|
||||
}
|
||||
}
|
||||
]
|
1
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/en-us.untranslated.json
generated
vendored
Normal file
1
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/en-us.untranslated.json
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
[]
|
45
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/fr-fr.all.json
generated
vendored
Normal file
45
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/fr-fr.all.json
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"one": "",
|
||||
"other": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "my_height_in_meters",
|
||||
"translation": {
|
||||
"one": "",
|
||||
"other": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": ""
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"one": "",
|
||||
"other": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"one": "",
|
||||
"other": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": ""
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"one": "",
|
||||
"other": ""
|
||||
}
|
||||
}
|
||||
]
|
45
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/fr-fr.untranslated.json
generated
vendored
Normal file
45
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/expected/fr-fr.untranslated.json
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"one": "{{.Count}} days",
|
||||
"other": "{{.Count}} days"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "my_height_in_meters",
|
||||
"translation": {
|
||||
"one": "I am {{.Count}} meters tall.",
|
||||
"other": "I am {{.Count}} meters tall."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "Hello {{.Person}}"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread emails.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": "Hello world"
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"one": "You have {{.Count}} unread emails.",
|
||||
"other": "You have {{.Count}} unread emails."
|
||||
}
|
||||
}
|
||||
]
|
54
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/ar-ar.one.json
generated
vendored
Normal file
54
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/ar-ar.one.json
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"few": "arabic few translation of d_days",
|
||||
"many": "arabic many translation of d_days",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "arabic translation of person_greeting"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"few": "arabic few translation of person_unread_email_count",
|
||||
"many": "arabic many translation of person_unread_email_count",
|
||||
"one": "arabic one translation of person_unread_email_count",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": ""
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
}
|
||||
]
|
54
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/ar-ar.two.json
generated
vendored
Normal file
54
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/ar-ar.two.json
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"few": "new arabic few translation of d_days",
|
||||
"many": "",
|
||||
"one": "arabic one translation of d_days",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "new arabic translation of person_greeting"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "arabic other translation of person_unread_email_count",
|
||||
"two": "arabic two translation of person_unread_email_count",
|
||||
"zero": "arabic zero translation of person_unread_email_count"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": ""
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
}
|
||||
]
|
30
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/en-us.one.json
generated
vendored
Normal file
30
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/en-us.one.json
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
[
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": "Hello world"
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"one": "You have {{.Count}} unread email.",
|
||||
"other": "You have {{.Count}} unread emails."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "my_height_in_meters",
|
||||
"translation": {
|
||||
"one": "I am {{.Count}} meter tall.",
|
||||
"other": "I am {{.Count}} meters tall."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": "this should get overwritten"
|
||||
}
|
||||
]
|
26
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/en-us.two.json
generated
vendored
Normal file
26
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/en-us.two.json
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
[
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "Hello {{.Person}}"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"one": "{{.Count}} day",
|
||||
"other": "{{.Count}} days"
|
||||
}
|
||||
}
|
||||
]
|
0
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/fr-fr.json
generated
vendored
Normal file
0
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/fr-fr.json
generated
vendored
Normal file
54
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/ar-ar.one.json
generated
vendored
Normal file
54
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/ar-ar.one.json
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"few": "arabic few translation of d_days",
|
||||
"many": "arabic many translation of d_days",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "arabic translation of person_greeting"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"few": "arabic few translation of person_unread_email_count",
|
||||
"many": "arabic many translation of person_unread_email_count",
|
||||
"one": "arabic one translation of person_unread_email_count",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": ""
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
}
|
||||
]
|
54
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/ar-ar.two.json
generated
vendored
Normal file
54
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/ar-ar.two.json
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
[
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"few": "new arabic few translation of d_days",
|
||||
"many": "",
|
||||
"one": "arabic one translation of d_days",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "new arabic translation of person_greeting"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "arabic other translation of person_unread_email_count",
|
||||
"two": "arabic two translation of person_unread_email_count",
|
||||
"zero": "arabic zero translation of person_unread_email_count"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "program_greeting",
|
||||
"translation": ""
|
||||
},
|
||||
{
|
||||
"id": "your_unread_email_count",
|
||||
"translation": {
|
||||
"few": "",
|
||||
"many": "",
|
||||
"one": "",
|
||||
"other": "",
|
||||
"two": "",
|
||||
"zero": ""
|
||||
}
|
||||
}
|
||||
]
|
19
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/en-us.one.yaml
generated
vendored
Normal file
19
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/en-us.one.yaml
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
- id: program_greeting
|
||||
translation: Hello world
|
||||
|
||||
- id: your_unread_email_count
|
||||
translation:
|
||||
one: You have {{.Count}} unread email.
|
||||
other: You have {{.Count}} unread emails.
|
||||
|
||||
- id: my_height_in_meters
|
||||
translation:
|
||||
one: I am {{.Count}} meter tall.
|
||||
other: I am {{.Count}} meters tall.
|
||||
|
||||
- id: person_unread_email_count_timeframe
|
||||
translation:
|
||||
one: "{{.Person}} has {{.Count}} unread email in the past {{.Timeframe}}."
|
||||
|
||||
- id: d_days
|
||||
translation: this should get overwritten
|
26
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/en-us.two.json
generated
vendored
Normal file
26
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/en-us.two.json
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
[
|
||||
{
|
||||
"id": "person_greeting",
|
||||
"translation": "Hello {{.Person}}"
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count",
|
||||
"translation": {
|
||||
"one": "{{.Person}} has {{.Count}} unread email.",
|
||||
"other": "{{.Person}} has {{.Count}} unread emails."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "person_unread_email_count_timeframe",
|
||||
"translation": {
|
||||
"other": "{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "d_days",
|
||||
"translation": {
|
||||
"one": "{{.Count}} day",
|
||||
"other": "{{.Count}} days"
|
||||
}
|
||||
}
|
||||
]
|
0
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/fr-fr.json
generated
vendored
Normal file
0
vendor/github.com/nicksnyder/go-i18n/goi18n/testdata/input/yaml/fr-fr.json
generated
vendored
Normal file
315
vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle.go
generated
vendored
Normal file
315
vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle.go
generated
vendored
Normal file
|
@ -0,0 +1,315 @@
|
|||
// Package bundle manages translations for multiple languages.
|
||||
package bundle
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
|
||||
"path/filepath"
|
||||
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
"github.com/nicksnyder/go-i18n/i18n/translation"
|
||||
)
|
||||
|
||||
// TranslateFunc is a copy of i18n.TranslateFunc to avoid a circular dependency.
|
||||
type TranslateFunc func(translationID string, args ...interface{}) string
|
||||
|
||||
// Bundle stores the translations for multiple languages.
|
||||
type Bundle struct {
|
||||
// The primary translations for a language tag and translation id.
|
||||
translations map[string]map[string]translation.Translation
|
||||
|
||||
// Translations that can be used when an exact language match is not possible.
|
||||
fallbackTranslations map[string]map[string]translation.Translation
|
||||
}
|
||||
|
||||
// New returns an empty bundle.
|
||||
func New() *Bundle {
|
||||
return &Bundle{
|
||||
translations: make(map[string]map[string]translation.Translation),
|
||||
fallbackTranslations: make(map[string]map[string]translation.Translation),
|
||||
}
|
||||
}
|
||||
|
||||
// MustLoadTranslationFile is similar to LoadTranslationFile
|
||||
// except it panics if an error happens.
|
||||
func (b *Bundle) MustLoadTranslationFile(filename string) {
|
||||
if err := b.LoadTranslationFile(filename); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// LoadTranslationFile loads the translations from filename into memory.
|
||||
//
|
||||
// The language that the translations are associated with is parsed from the filename (e.g. en-US.json).
|
||||
//
|
||||
// Generally you should load translation files once during your program's initialization.
|
||||
func (b *Bundle) LoadTranslationFile(filename string) error {
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.ParseTranslationFileBytes(filename, buf)
|
||||
}
|
||||
|
||||
// ParseTranslationFileBytes is similar to LoadTranslationFile except it parses the bytes in buf.
|
||||
//
|
||||
// It is useful for parsing translation files embedded with go-bindata.
|
||||
func (b *Bundle) ParseTranslationFileBytes(filename string, buf []byte) error {
|
||||
basename := filepath.Base(filename)
|
||||
langs := language.Parse(basename)
|
||||
switch l := len(langs); {
|
||||
case l == 0:
|
||||
return fmt.Errorf("no language found in %q", basename)
|
||||
case l > 1:
|
||||
return fmt.Errorf("multiple languages found in filename %q: %v; expected one", basename, langs)
|
||||
}
|
||||
translations, err := parseTranslations(filename, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.AddTranslation(langs[0], translations...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseTranslations(filename string, buf []byte) ([]translation.Translation, error) {
|
||||
var unmarshalFunc func([]byte, interface{}) error
|
||||
switch format := filepath.Ext(filename); format {
|
||||
case ".json":
|
||||
unmarshalFunc = json.Unmarshal
|
||||
case ".yaml":
|
||||
unmarshalFunc = yaml.Unmarshal
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported file extension %s", format)
|
||||
}
|
||||
|
||||
var translationsData []map[string]interface{}
|
||||
if len(buf) > 0 {
|
||||
if err := unmarshalFunc(buf, &translationsData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
translations := make([]translation.Translation, 0, len(translationsData))
|
||||
for i, translationData := range translationsData {
|
||||
t, err := translation.NewTranslation(translationData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse translation #%d in %s because %s\n%v", i, filename, err, translationData)
|
||||
}
|
||||
translations = append(translations, t)
|
||||
}
|
||||
return translations, nil
|
||||
}
|
||||
|
||||
// AddTranslation adds translations for a language.
|
||||
//
|
||||
// It is useful if your translations are in a format not supported by LoadTranslationFile.
|
||||
func (b *Bundle) AddTranslation(lang *language.Language, translations ...translation.Translation) {
|
||||
if b.translations[lang.Tag] == nil {
|
||||
b.translations[lang.Tag] = make(map[string]translation.Translation, len(translations))
|
||||
}
|
||||
currentTranslations := b.translations[lang.Tag]
|
||||
for _, newTranslation := range translations {
|
||||
if currentTranslation := currentTranslations[newTranslation.ID()]; currentTranslation != nil {
|
||||
currentTranslations[newTranslation.ID()] = currentTranslation.Merge(newTranslation)
|
||||
} else {
|
||||
currentTranslations[newTranslation.ID()] = newTranslation
|
||||
}
|
||||
}
|
||||
|
||||
// lang can provide translations for less specific language tags.
|
||||
for _, tag := range lang.MatchingTags() {
|
||||
b.fallbackTranslations[tag] = currentTranslations
|
||||
}
|
||||
}
|
||||
|
||||
// Translations returns all translations in the bundle.
|
||||
func (b *Bundle) Translations() map[string]map[string]translation.Translation {
|
||||
return b.translations
|
||||
}
|
||||
|
||||
// LanguageTags returns the tags of all languages that that have been added.
|
||||
func (b *Bundle) LanguageTags() []string {
|
||||
var tags []string
|
||||
for k := range b.translations {
|
||||
tags = append(tags, k)
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
// LanguageTranslationIDs returns the ids of all translations that have been added for a given language.
|
||||
func (b *Bundle) LanguageTranslationIDs(languageTag string) []string {
|
||||
var ids []string
|
||||
for id := range b.translations[languageTag] {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
// MustTfunc is similar to Tfunc except it panics if an error happens.
|
||||
func (b *Bundle) MustTfunc(pref string, prefs ...string) TranslateFunc {
|
||||
tfunc, err := b.Tfunc(pref, prefs...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tfunc
|
||||
}
|
||||
|
||||
// MustTfuncAndLanguage is similar to TfuncAndLanguage except it panics if an error happens.
|
||||
func (b *Bundle) MustTfuncAndLanguage(pref string, prefs ...string) (TranslateFunc, *language.Language) {
|
||||
tfunc, language, err := b.TfuncAndLanguage(pref, prefs...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tfunc, language
|
||||
}
|
||||
|
||||
// Tfunc is similar to TfuncAndLanguage except is doesn't return the Language.
|
||||
func (b *Bundle) Tfunc(pref string, prefs ...string) (TranslateFunc, error) {
|
||||
tfunc, _, err := b.TfuncAndLanguage(pref, prefs...)
|
||||
return tfunc, err
|
||||
}
|
||||
|
||||
// TfuncAndLanguage returns a TranslateFunc for the first Language that
|
||||
// has a non-zero number of translations in the bundle.
|
||||
//
|
||||
// The returned Language matches the the first language preference that could be satisfied,
|
||||
// but this may not strictly match the language of the translations used to satisfy that preference.
|
||||
//
|
||||
// For example, the user may request "zh". If there are no translations for "zh" but there are translations
|
||||
// for "zh-cn", then the translations for "zh-cn" will be used but the returned Language will be "zh".
|
||||
//
|
||||
// It can parse languages from Accept-Language headers (RFC 2616),
|
||||
// but it assumes weights are monotonically decreasing.
|
||||
func (b *Bundle) TfuncAndLanguage(pref string, prefs ...string) (TranslateFunc, *language.Language, error) {
|
||||
lang := b.supportedLanguage(pref, prefs...)
|
||||
var err error
|
||||
if lang == nil {
|
||||
err = fmt.Errorf("no supported languages found %#v", append(prefs, pref))
|
||||
}
|
||||
return func(translationID string, args ...interface{}) string {
|
||||
return b.translate(lang, translationID, args...)
|
||||
}, lang, err
|
||||
}
|
||||
|
||||
// supportedLanguage returns the first language which
|
||||
// has a non-zero number of translations in the bundle.
|
||||
func (b *Bundle) supportedLanguage(pref string, prefs ...string) *language.Language {
|
||||
lang := b.translatedLanguage(pref)
|
||||
if lang == nil {
|
||||
for _, pref := range prefs {
|
||||
lang = b.translatedLanguage(pref)
|
||||
if lang != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return lang
|
||||
}
|
||||
|
||||
func (b *Bundle) translatedLanguage(src string) *language.Language {
|
||||
langs := language.Parse(src)
|
||||
for _, lang := range langs {
|
||||
if len(b.translations[lang.Tag]) > 0 ||
|
||||
len(b.fallbackTranslations[lang.Tag]) > 0 {
|
||||
return lang
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bundle) translate(lang *language.Language, translationID string, args ...interface{}) string {
|
||||
if lang == nil {
|
||||
return translationID
|
||||
}
|
||||
|
||||
translations := b.translations[lang.Tag]
|
||||
if translations == nil {
|
||||
translations = b.fallbackTranslations[lang.Tag]
|
||||
if translations == nil {
|
||||
return translationID
|
||||
}
|
||||
}
|
||||
|
||||
translation := translations[translationID]
|
||||
if translation == nil {
|
||||
return translationID
|
||||
}
|
||||
|
||||
var data interface{}
|
||||
var count interface{}
|
||||
if argc := len(args); argc > 0 {
|
||||
if isNumber(args[0]) {
|
||||
count = args[0]
|
||||
if argc > 1 {
|
||||
data = args[1]
|
||||
}
|
||||
} else {
|
||||
data = args[0]
|
||||
}
|
||||
}
|
||||
|
||||
if count != nil {
|
||||
if data == nil {
|
||||
data = map[string]interface{}{"Count": count}
|
||||
} else {
|
||||
dataMap := toMap(data)
|
||||
dataMap["Count"] = count
|
||||
data = dataMap
|
||||
}
|
||||
}
|
||||
|
||||
p, _ := lang.Plural(count)
|
||||
template := translation.Template(p)
|
||||
if template == nil {
|
||||
return translationID
|
||||
}
|
||||
|
||||
s := template.Execute(data)
|
||||
if s == "" {
|
||||
return translationID
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func isNumber(n interface{}) bool {
|
||||
switch n.(type) {
|
||||
case int, int8, int16, int32, int64, string:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func toMap(input interface{}) map[string]interface{} {
|
||||
if data, ok := input.(map[string]interface{}); ok {
|
||||
return data
|
||||
}
|
||||
v := reflect.ValueOf(input)
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr:
|
||||
return toMap(v.Elem().Interface())
|
||||
case reflect.Struct:
|
||||
return structToMap(v)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Converts the top level of a struct to a map[string]interface{}.
|
||||
// Code inspired by github.com/fatih/structs.
|
||||
func structToMap(v reflect.Value) map[string]interface{} {
|
||||
out := make(map[string]interface{})
|
||||
t := v.Type()
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
if field.PkgPath != "" {
|
||||
// unexported field. skip.
|
||||
continue
|
||||
}
|
||||
out[field.Name] = v.FieldByName(field.Name).Interface()
|
||||
}
|
||||
return out
|
||||
}
|
289
vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle_test.go
generated
vendored
Normal file
289
vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle_test.go
generated
vendored
Normal file
|
@ -0,0 +1,289 @@
|
|||
package bundle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
"github.com/nicksnyder/go-i18n/i18n/translation"
|
||||
)
|
||||
|
||||
func TestMustLoadTranslationFile(t *testing.T) {
|
||||
t.Skipf("not implemented")
|
||||
}
|
||||
|
||||
func TestLoadTranslationFile(t *testing.T) {
|
||||
t.Skipf("not implemented")
|
||||
}
|
||||
|
||||
func TestParseTranslationFileBytes(t *testing.T) {
|
||||
t.Skipf("not implemented")
|
||||
}
|
||||
|
||||
func TestAddTranslation(t *testing.T) {
|
||||
t.Skipf("not implemented")
|
||||
}
|
||||
|
||||
func TestMustTfunc(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("expected MustTfunc to panic")
|
||||
}
|
||||
}()
|
||||
New().MustTfunc("invalid")
|
||||
}
|
||||
|
||||
func TestLanguageTagsAndTranslationIDs(t *testing.T) {
|
||||
b := New()
|
||||
translationID := "translation_id"
|
||||
englishLanguage := languageWithTag("en-US")
|
||||
frenchLanguage := languageWithTag("fr-FR")
|
||||
spanishLanguage := languageWithTag("es")
|
||||
addFakeTranslation(t, b, englishLanguage, "English"+translationID)
|
||||
addFakeTranslation(t, b, frenchLanguage, translationID)
|
||||
addFakeTranslation(t, b, spanishLanguage, translationID)
|
||||
|
||||
tags := b.LanguageTags()
|
||||
sort.Strings(tags)
|
||||
compareTo := []string{englishLanguage.Tag, spanishLanguage.Tag, frenchLanguage.Tag}
|
||||
if !reflect.DeepEqual(tags, compareTo) {
|
||||
t.Errorf("LanguageTags() = %#v; expected: %#v", tags, compareTo)
|
||||
}
|
||||
|
||||
ids := b.LanguageTranslationIDs(englishLanguage.Tag)
|
||||
sort.Strings(ids)
|
||||
compareTo = []string{"English" + translationID}
|
||||
if !reflect.DeepEqual(ids, compareTo) {
|
||||
t.Errorf("LanguageTranslationIDs() = %#v; expected: %#v", ids, compareTo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTfuncAndLanguage(t *testing.T) {
|
||||
b := New()
|
||||
translationID := "translation_id"
|
||||
englishLanguage := languageWithTag("en-US")
|
||||
frenchLanguage := languageWithTag("fr-FR")
|
||||
spanishLanguage := languageWithTag("es")
|
||||
chineseLanguage := languageWithTag("zh-hans-cn")
|
||||
englishTranslation := addFakeTranslation(t, b, englishLanguage, translationID)
|
||||
frenchTranslation := addFakeTranslation(t, b, frenchLanguage, translationID)
|
||||
spanishTranslation := addFakeTranslation(t, b, spanishLanguage, translationID)
|
||||
chineseTranslation := addFakeTranslation(t, b, chineseLanguage, translationID)
|
||||
|
||||
tests := []struct {
|
||||
languageIDs []string
|
||||
result string
|
||||
expectedLanguage *language.Language
|
||||
}{
|
||||
{
|
||||
[]string{"invalid"},
|
||||
translationID,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
[]string{"invalid", "invalid2"},
|
||||
translationID,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
[]string{"invalid", "en-US"},
|
||||
englishTranslation,
|
||||
englishLanguage,
|
||||
},
|
||||
{
|
||||
[]string{"en-US", "invalid"},
|
||||
englishTranslation,
|
||||
englishLanguage,
|
||||
},
|
||||
{
|
||||
[]string{"en-US", "fr-FR"},
|
||||
englishTranslation,
|
||||
englishLanguage,
|
||||
},
|
||||
{
|
||||
[]string{"invalid", "es"},
|
||||
spanishTranslation,
|
||||
spanishLanguage,
|
||||
},
|
||||
{
|
||||
[]string{"zh-CN,fr-XX,es"},
|
||||
spanishTranslation,
|
||||
spanishLanguage,
|
||||
},
|
||||
{
|
||||
[]string{"fr"},
|
||||
frenchTranslation,
|
||||
|
||||
// The language is still "fr" even though the translation is provided by "fr-FR"
|
||||
languageWithTag("fr"),
|
||||
},
|
||||
{
|
||||
[]string{"zh"},
|
||||
chineseTranslation,
|
||||
|
||||
// The language is still "zh" even though the translation is provided by "zh-hans-cn"
|
||||
languageWithTag("zh"),
|
||||
},
|
||||
{
|
||||
[]string{"zh-hans"},
|
||||
chineseTranslation,
|
||||
|
||||
// The language is still "zh-hans" even though the translation is provided by "zh-hans-cn"
|
||||
languageWithTag("zh-hans"),
|
||||
},
|
||||
{
|
||||
[]string{"zh-hans-cn"},
|
||||
chineseTranslation,
|
||||
languageWithTag("zh-hans-cn"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
tf, lang, err := b.TfuncAndLanguage(test.languageIDs[0], test.languageIDs[1:]...)
|
||||
if err != nil && test.expectedLanguage != nil {
|
||||
t.Errorf("Tfunc(%v) = error{%q}; expected no error", test.languageIDs, err)
|
||||
}
|
||||
if err == nil && test.expectedLanguage == nil {
|
||||
t.Errorf("Tfunc(%v) = nil error; expected error", test.languageIDs)
|
||||
}
|
||||
if result := tf(translationID); result != test.result {
|
||||
t.Errorf("translation %d was %s; expected %s", i, result, test.result)
|
||||
}
|
||||
if (lang == nil && test.expectedLanguage != nil) ||
|
||||
(lang != nil && test.expectedLanguage == nil) ||
|
||||
(lang != nil && test.expectedLanguage != nil && lang.String() != test.expectedLanguage.String()) {
|
||||
t.Errorf("lang %d was %s; expected %s", i, lang, test.expectedLanguage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addFakeTranslation(t *testing.T, b *Bundle, lang *language.Language, translationID string) string {
|
||||
translation := fakeTranslation(lang, translationID)
|
||||
b.AddTranslation(lang, testNewTranslation(t, map[string]interface{}{
|
||||
"id": translationID,
|
||||
"translation": translation,
|
||||
}))
|
||||
return translation
|
||||
}
|
||||
|
||||
func fakeTranslation(lang *language.Language, translationID string) string {
|
||||
return fmt.Sprintf("%s(%s)", lang.Tag, translationID)
|
||||
}
|
||||
|
||||
func testNewTranslation(t *testing.T, data map[string]interface{}) translation.Translation {
|
||||
translation, err := translation.NewTranslation(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return translation
|
||||
}
|
||||
|
||||
func languageWithTag(tag string) *language.Language {
|
||||
return language.MustParse(tag)[0]
|
||||
}
|
||||
|
||||
func createBenchmarkTranslateFunc(b *testing.B, translationTemplate interface{}, count interface{}, expected string) func(data interface{}) {
|
||||
bundle := New()
|
||||
lang := "en-US"
|
||||
translationID := "translation_id"
|
||||
translation, err := translation.NewTranslation(map[string]interface{}{
|
||||
"id": translationID,
|
||||
"translation": translationTemplate,
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
bundle.AddTranslation(languageWithTag(lang), translation)
|
||||
tf, err := bundle.Tfunc(lang)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
return func(data interface{}) {
|
||||
var result string
|
||||
if count == nil {
|
||||
result = tf(translationID, data)
|
||||
} else {
|
||||
result = tf(translationID, count, data)
|
||||
}
|
||||
if result != expected {
|
||||
b.Fatalf("expected %q, got %q", expected, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createBenchmarkPluralTranslateFunc(b *testing.B) func(data interface{}) {
|
||||
translationTemplate := map[string]interface{}{
|
||||
"one": "{{.Person}} is {{.Count}} year old.",
|
||||
"other": "{{.Person}} is {{.Count}} years old.",
|
||||
}
|
||||
count := 26
|
||||
expected := "Bob is 26 years old."
|
||||
return createBenchmarkTranslateFunc(b, translationTemplate, count, expected)
|
||||
}
|
||||
|
||||
func createBenchmarkNonPluralTranslateFunc(b *testing.B) func(data interface{}) {
|
||||
translationTemplate := "Hi {{.Person}}!"
|
||||
expected := "Hi Bob!"
|
||||
return createBenchmarkTranslateFunc(b, translationTemplate, nil, expected)
|
||||
}
|
||||
|
||||
func BenchmarkTranslateNonPluralWithMap(b *testing.B) {
|
||||
data := map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
}
|
||||
tf := createBenchmarkNonPluralTranslateFunc(b)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tf(data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTranslateNonPluralWithStruct(b *testing.B) {
|
||||
data := struct{ Person string }{Person: "Bob"}
|
||||
tf := createBenchmarkNonPluralTranslateFunc(b)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tf(data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTranslateNonPluralWithStructPointer(b *testing.B) {
|
||||
data := &struct{ Person string }{Person: "Bob"}
|
||||
tf := createBenchmarkNonPluralTranslateFunc(b)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tf(data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTranslatePluralWithMap(b *testing.B) {
|
||||
data := map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
}
|
||||
tf := createBenchmarkPluralTranslateFunc(b)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tf(data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTranslatePluralWithStruct(b *testing.B) {
|
||||
data := struct{ Person string }{Person: "Bob"}
|
||||
tf := createBenchmarkPluralTranslateFunc(b)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tf(data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTranslatePluralWithStructPointer(b *testing.B) {
|
||||
data := &struct{ Person string }{Person: "Bob"}
|
||||
tf := createBenchmarkPluralTranslateFunc(b)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tf(data)
|
||||
}
|
||||
}
|
63
vendor/github.com/nicksnyder/go-i18n/i18n/example_test.go
generated
vendored
Normal file
63
vendor/github.com/nicksnyder/go-i18n/i18n/example_test.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
package i18n_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nicksnyder/go-i18n/i18n"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
i18n.MustLoadTranslationFile("../goi18n/testdata/expected/en-us.all.json")
|
||||
|
||||
T, _ := i18n.Tfunc("en-US")
|
||||
|
||||
bobMap := map[string]interface{}{"Person": "Bob"}
|
||||
bobStruct := struct{ Person string }{Person: "Bob"}
|
||||
|
||||
fmt.Println(T("program_greeting"))
|
||||
fmt.Println(T("person_greeting", bobMap))
|
||||
fmt.Println(T("person_greeting", bobStruct))
|
||||
|
||||
fmt.Println(T("your_unread_email_count", 0))
|
||||
fmt.Println(T("your_unread_email_count", 1))
|
||||
fmt.Println(T("your_unread_email_count", 2))
|
||||
fmt.Println(T("my_height_in_meters", "1.7"))
|
||||
|
||||
fmt.Println(T("person_unread_email_count", 0, bobMap))
|
||||
fmt.Println(T("person_unread_email_count", 1, bobMap))
|
||||
fmt.Println(T("person_unread_email_count", 2, bobMap))
|
||||
fmt.Println(T("person_unread_email_count", 0, bobStruct))
|
||||
fmt.Println(T("person_unread_email_count", 1, bobStruct))
|
||||
fmt.Println(T("person_unread_email_count", 2, bobStruct))
|
||||
|
||||
fmt.Println(T("person_unread_email_count_timeframe", 3, map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
"Timeframe": T("d_days", 0),
|
||||
}))
|
||||
fmt.Println(T("person_unread_email_count_timeframe", 3, map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
"Timeframe": T("d_days", 1),
|
||||
}))
|
||||
fmt.Println(T("person_unread_email_count_timeframe", 3, map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
"Timeframe": T("d_days", 2),
|
||||
}))
|
||||
|
||||
// Output:
|
||||
// Hello world
|
||||
// Hello Bob
|
||||
// Hello Bob
|
||||
// You have 0 unread emails.
|
||||
// You have 1 unread email.
|
||||
// You have 2 unread emails.
|
||||
// I am 1.7 meters tall.
|
||||
// Bob has 0 unread emails.
|
||||
// Bob has 1 unread email.
|
||||
// Bob has 2 unread emails.
|
||||
// Bob has 0 unread emails.
|
||||
// Bob has 1 unread email.
|
||||
// Bob has 2 unread emails.
|
||||
// Bob has 3 unread emails in the past 0 days.
|
||||
// Bob has 3 unread emails in the past 1 day.
|
||||
// Bob has 3 unread emails in the past 2 days.
|
||||
}
|
63
vendor/github.com/nicksnyder/go-i18n/i18n/exampletemplate_test.go
generated
vendored
Normal file
63
vendor/github.com/nicksnyder/go-i18n/i18n/exampletemplate_test.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
package i18n_test
|
||||
|
||||
import (
|
||||
"github.com/nicksnyder/go-i18n/i18n"
|
||||
"os"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var funcMap = map[string]interface{}{
|
||||
"T": i18n.IdentityTfunc,
|
||||
}
|
||||
|
||||
var tmpl = template.Must(template.New("").Funcs(funcMap).Parse(`
|
||||
{{T "program_greeting"}}
|
||||
{{T "person_greeting" .}}
|
||||
{{T "your_unread_email_count" 0}}
|
||||
{{T "your_unread_email_count" 1}}
|
||||
{{T "your_unread_email_count" 2}}
|
||||
{{T "person_unread_email_count" 0 .}}
|
||||
{{T "person_unread_email_count" 1 .}}
|
||||
{{T "person_unread_email_count" 2 .}}
|
||||
`))
|
||||
|
||||
func Example_template() {
|
||||
i18n.MustLoadTranslationFile("../goi18n/testdata/expected/en-us.all.json")
|
||||
|
||||
T, _ := i18n.Tfunc("en-US")
|
||||
tmpl.Funcs(map[string]interface{}{
|
||||
"T": T,
|
||||
})
|
||||
|
||||
tmpl.Execute(os.Stdout, map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
"Timeframe": T("d_days", 1),
|
||||
})
|
||||
|
||||
tmpl.Execute(os.Stdout, struct {
|
||||
Person string
|
||||
Timeframe string
|
||||
}{
|
||||
Person: "Bob",
|
||||
Timeframe: T("d_days", 1),
|
||||
})
|
||||
|
||||
// Output:
|
||||
// Hello world
|
||||
// Hello Bob
|
||||
// You have 0 unread emails.
|
||||
// You have 1 unread email.
|
||||
// You have 2 unread emails.
|
||||
// Bob has 0 unread emails.
|
||||
// Bob has 1 unread email.
|
||||
// Bob has 2 unread emails.
|
||||
//
|
||||
// Hello world
|
||||
// Hello Bob
|
||||
// You have 0 unread emails.
|
||||
// You have 1 unread email.
|
||||
// You have 2 unread emails.
|
||||
// Bob has 0 unread emails.
|
||||
// Bob has 1 unread email.
|
||||
// Bob has 2 unread emails.
|
||||
}
|
62
vendor/github.com/nicksnyder/go-i18n/i18n/exampleyaml_test.go
generated
vendored
Normal file
62
vendor/github.com/nicksnyder/go-i18n/i18n/exampleyaml_test.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
package i18n_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/nicksnyder/go-i18n/i18n"
|
||||
)
|
||||
|
||||
func ExampleYAML() {
|
||||
i18n.MustLoadTranslationFile("../goi18n/testdata/en-us.yaml")
|
||||
|
||||
T, _ := i18n.Tfunc("en-US")
|
||||
|
||||
bobMap := map[string]interface{}{"Person": "Bob"}
|
||||
bobStruct := struct{ Person string }{Person: "Bob"}
|
||||
|
||||
fmt.Println(T("program_greeting"))
|
||||
fmt.Println(T("person_greeting", bobMap))
|
||||
fmt.Println(T("person_greeting", bobStruct))
|
||||
|
||||
fmt.Println(T("your_unread_email_count", 0))
|
||||
fmt.Println(T("your_unread_email_count", 1))
|
||||
fmt.Println(T("your_unread_email_count", 2))
|
||||
fmt.Println(T("my_height_in_meters", "1.7"))
|
||||
|
||||
fmt.Println(T("person_unread_email_count", 0, bobMap))
|
||||
fmt.Println(T("person_unread_email_count", 1, bobMap))
|
||||
fmt.Println(T("person_unread_email_count", 2, bobMap))
|
||||
fmt.Println(T("person_unread_email_count", 0, bobStruct))
|
||||
fmt.Println(T("person_unread_email_count", 1, bobStruct))
|
||||
fmt.Println(T("person_unread_email_count", 2, bobStruct))
|
||||
|
||||
fmt.Println(T("person_unread_email_count_timeframe", 3, map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
"Timeframe": T("d_days", 0),
|
||||
}))
|
||||
fmt.Println(T("person_unread_email_count_timeframe", 3, map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
"Timeframe": T("d_days", 1),
|
||||
}))
|
||||
fmt.Println(T("person_unread_email_count_timeframe", 3, map[string]interface{}{
|
||||
"Person": "Bob",
|
||||
"Timeframe": T("d_days", 2),
|
||||
}))
|
||||
|
||||
// Output:
|
||||
// Hello world
|
||||
// Hello Bob
|
||||
// Hello Bob
|
||||
// You have 0 unread emails.
|
||||
// You have 1 unread email.
|
||||
// You have 2 unread emails.
|
||||
// I am 1.7 meters tall.
|
||||
// Bob has 0 unread emails.
|
||||
// Bob has 1 unread email.
|
||||
// Bob has 2 unread emails.
|
||||
// Bob has 0 unread emails.
|
||||
// Bob has 1 unread email.
|
||||
// Bob has 2 unread emails.
|
||||
// Bob has 3 unread emails in the past 0 days.
|
||||
// Bob has 3 unread emails in the past 1 day.
|
||||
// Bob has 3 unread emails in the past 2 days.
|
||||
}
|
152
vendor/github.com/nicksnyder/go-i18n/i18n/i18n.go
generated
vendored
Normal file
152
vendor/github.com/nicksnyder/go-i18n/i18n/i18n.go
generated
vendored
Normal file
|
@ -0,0 +1,152 @@
|
|||
// Package i18n supports string translations with variable substitution and CLDR pluralization.
|
||||
// It is intended to be used in conjunction with the goi18n command, although that is not strictly required.
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
// Your Go program should load translations during its initialization.
|
||||
// i18n.MustLoadTranslationFile("path/to/fr-FR.all.json")
|
||||
// If your translations are in a file format not supported by (Must)?LoadTranslationFile,
|
||||
// then you can use the AddTranslation function to manually add translations.
|
||||
//
|
||||
// Fetching a translation
|
||||
//
|
||||
// Use Tfunc or MustTfunc to fetch a TranslateFunc that will return the translated string for a specific language.
|
||||
// func handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
// cookieLang := r.Cookie("lang")
|
||||
// acceptLang := r.Header.Get("Accept-Language")
|
||||
// defaultLang = "en-US" // known valid language
|
||||
// T, err := i18n.Tfunc(cookieLang, acceptLang, defaultLang)
|
||||
// fmt.Println(T("Hello world"))
|
||||
// }
|
||||
//
|
||||
// Usually it is a good idea to identify strings by a generic id rather than the English translation,
|
||||
// but the rest of this documentation will continue to use the English translation for readability.
|
||||
// T("Hello world") // ok
|
||||
// T("programGreeting") // better!
|
||||
//
|
||||
// Variables
|
||||
//
|
||||
// TranslateFunc supports strings that have variables using the text/template syntax.
|
||||
// T("Hello {{.Person}}", map[string]interface{}{
|
||||
// "Person": "Bob",
|
||||
// })
|
||||
//
|
||||
// Pluralization
|
||||
//
|
||||
// TranslateFunc supports the pluralization of strings using the CLDR pluralization rules defined here:
|
||||
// http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
|
||||
// T("You have {{.Count}} unread emails.", 2)
|
||||
// T("I am {{.Count}} meters tall.", "1.7")
|
||||
//
|
||||
// Plural strings may also have variables.
|
||||
// T("{{.Person}} has {{.Count}} unread emails", 2, map[string]interface{}{
|
||||
// "Person": "Bob",
|
||||
// })
|
||||
//
|
||||
// Sentences with multiple plural components can be supported with nesting.
|
||||
// T("{{.Person}} has {{.Count}} unread emails in the past {{.Timeframe}}.", 3, map[string]interface{}{
|
||||
// "Person": "Bob",
|
||||
// "Timeframe": T("{{.Count}} days", 2),
|
||||
// })
|
||||
//
|
||||
// Templates
|
||||
//
|
||||
// You can use the .Funcs() method of a text/template or html/template to register a TranslateFunc
|
||||
// for usage inside of that template.
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"github.com/nicksnyder/go-i18n/i18n/bundle"
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
"github.com/nicksnyder/go-i18n/i18n/translation"
|
||||
)
|
||||
|
||||
// TranslateFunc returns the translation of the string identified by translationID.
|
||||
//
|
||||
// If there is no translation for translationID, then the translationID itself is returned.
|
||||
// This makes it easy to identify missing translations in your app.
|
||||
//
|
||||
// If translationID is a non-plural form, then the first variadic argument may be a map[string]interface{}
|
||||
// or struct that contains template data.
|
||||
//
|
||||
// If translationID is a plural form, then the first variadic argument must be an integer type
|
||||
// (int, int8, int16, int32, int64) or a float formatted as a string (e.g. "123.45").
|
||||
// The second variadic argument may be a map[string]interface{} or struct that contains template data.
|
||||
type TranslateFunc func(translationID string, args ...interface{}) string
|
||||
|
||||
// IdentityTfunc returns a TranslateFunc that always returns the translationID passed to it.
|
||||
//
|
||||
// It is a useful placeholder when parsing a text/template or html/template
|
||||
// before the actual Tfunc is available.
|
||||
func IdentityTfunc() TranslateFunc {
|
||||
return func(translationID string, args ...interface{}) string {
|
||||
return translationID
|
||||
}
|
||||
}
|
||||
|
||||
var defaultBundle = bundle.New()
|
||||
|
||||
// MustLoadTranslationFile is similar to LoadTranslationFile
|
||||
// except it panics if an error happens.
|
||||
func MustLoadTranslationFile(filename string) {
|
||||
defaultBundle.MustLoadTranslationFile(filename)
|
||||
}
|
||||
|
||||
// LoadTranslationFile loads the translations from filename into memory.
|
||||
//
|
||||
// The language that the translations are associated with is parsed from the filename (e.g. en-US.json).
|
||||
//
|
||||
// Generally you should load translation files once during your program's initialization.
|
||||
func LoadTranslationFile(filename string) error {
|
||||
return defaultBundle.LoadTranslationFile(filename)
|
||||
}
|
||||
|
||||
// ParseTranslationFileBytes is similar to LoadTranslationFile except it parses the bytes in buf.
|
||||
//
|
||||
// It is useful for parsing translation files embedded with go-bindata.
|
||||
func ParseTranslationFileBytes(filename string, buf []byte) error {
|
||||
return defaultBundle.ParseTranslationFileBytes(filename, buf)
|
||||
}
|
||||
|
||||
// AddTranslation adds translations for a language.
|
||||
//
|
||||
// It is useful if your translations are in a format not supported by LoadTranslationFile.
|
||||
func AddTranslation(lang *language.Language, translations ...translation.Translation) {
|
||||
defaultBundle.AddTranslation(lang, translations...)
|
||||
}
|
||||
|
||||
// LanguageTags returns the tags of all languages that have been added.
|
||||
func LanguageTags() []string {
|
||||
return defaultBundle.LanguageTags()
|
||||
}
|
||||
|
||||
// LanguageTranslationIDs returns the ids of all translations that have been added for a given language.
|
||||
func LanguageTranslationIDs(languageTag string) []string {
|
||||
return defaultBundle.LanguageTranslationIDs(languageTag)
|
||||
}
|
||||
|
||||
// MustTfunc is similar to Tfunc except it panics if an error happens.
|
||||
func MustTfunc(languageSource string, languageSources ...string) TranslateFunc {
|
||||
return TranslateFunc(defaultBundle.MustTfunc(languageSource, languageSources...))
|
||||
}
|
||||
|
||||
// Tfunc returns a TranslateFunc that will be bound to the first language which
|
||||
// has a non-zero number of translations.
|
||||
//
|
||||
// It can parse languages from Accept-Language headers (RFC 2616).
|
||||
func Tfunc(languageSource string, languageSources ...string) (TranslateFunc, error) {
|
||||
tfunc, err := defaultBundle.Tfunc(languageSource, languageSources...)
|
||||
return TranslateFunc(tfunc), err
|
||||
}
|
||||
|
||||
// MustTfuncAndLanguage is similar to TfuncAndLanguage except it panics if an error happens.
|
||||
func MustTfuncAndLanguage(languageSource string, languageSources ...string) (TranslateFunc, *language.Language) {
|
||||
tfunc, lang := defaultBundle.MustTfuncAndLanguage(languageSource, languageSources...)
|
||||
return TranslateFunc(tfunc), lang
|
||||
}
|
||||
|
||||
// TfuncAndLanguage is similar to Tfunc except it also returns the language which TranslateFunc is bound to.
|
||||
func TfuncAndLanguage(languageSource string, languageSources ...string) (TranslateFunc, *language.Language, error) {
|
||||
tfunc, lang, err := defaultBundle.TfuncAndLanguage(languageSource, languageSources...)
|
||||
return TranslateFunc(tfunc), lang, err
|
||||
}
|
5
vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/generate.sh
generated
vendored
Normal file
5
vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/generate.sh
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
go build && ./codegen -cout ../pluralspec_gen.go -tout ../pluralspec_gen_test.go && \
|
||||
gofmt -w=true ../pluralspec_gen.go && \
|
||||
gofmt -w=true ../pluralspec_gen_test.go && \
|
||||
rm codegen
|
132
vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/main.go
generated
vendored
Normal file
132
vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/main.go
generated
vendored
Normal file
|
@ -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)
|
||||
}
|
230
vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/plurals.xml
generated
vendored
Normal file
230
vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/plurals.xml
generated
vendored
Normal file
|
@ -0,0 +1,230 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE supplementalData SYSTEM "../../common/dtd/ldmlSupplemental.dtd">
|
||||
<!--
|
||||
Copyright © 1991-2015 Unicode, Inc.
|
||||
CLDR data files are interpreted according to the LDML specification (http://unicode.org/reports/tr35/)
|
||||
For terms of use, see http://www.unicode.org/copyright.html
|
||||
-->
|
||||
<supplementalData>
|
||||
<version number="$Revision: 12002 $"/>
|
||||
<plurals type="cardinal">
|
||||
<!-- For a canonicalized list, use GeneratedPluralSamples -->
|
||||
|
||||
<!-- 1: other -->
|
||||
|
||||
<pluralRules locales="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">
|
||||
<pluralRule count="other"> @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 2: one,other -->
|
||||
|
||||
<pluralRules locales="am as bn fa gu hi kn mr zu">
|
||||
<pluralRule count="one">i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="ff fr hy kab">
|
||||
<pluralRule count="one">i = 0,1 @integer 0, 1 @decimal 0.0~1.5</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="ast ca de en et fi fy gl it ji nl sv sw ur yi">
|
||||
<pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="si">
|
||||
<pluralRule count="one">n = 0,1 or i = 0 and f = 1 @integer 0, 1 @decimal 0.0, 0.1, 1.0, 0.00, 0.01, 1.00, 0.000, 0.001, 1.000, 0.0000, 0.0001, 1.0000</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.2~0.9, 1.1~1.8, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="ak bh guw ln mg nso pa ti wa">
|
||||
<pluralRule count="one">n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="tzm">
|
||||
<pluralRule count="one">n = 0..1 or n = 11..99 @integer 0, 1, 11~24 @decimal 0.0, 1.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~10, 100~106, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="pt">
|
||||
<pluralRule count="one">n = 0..2 and n != 2 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="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">
|
||||
<pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="pt_PT">
|
||||
<pluralRule count="one">n = 1 and v = 0 @integer 1</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="da">
|
||||
<pluralRule count="one">n = 1 or t != 0 and i = 0,1 @integer 1 @decimal 0.1~1.6</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 2.0~3.4, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="is">
|
||||
<pluralRule count="one">t = 0 and i % 10 = 1 and i % 100 != 11 or t != 0 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1~1.6, 10.1, 100.1, 1000.1, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="mk">
|
||||
<pluralRule count="one">v = 0 and i % 10 = 1 or f % 10 = 1 @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 2~10, 12~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.2~1.0, 1.2~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="fil tl">
|
||||
<pluralRule count="one">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 @integer 0~3, 5, 7, 8, 10~13, 15, 17, 18, 20, 21, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.3, 0.5, 0.7, 0.8, 1.0~1.3, 1.5, 1.7, 1.8, 2.0, 2.1, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 4, 6, 9, 14, 16, 19, 24, 26, 104, 1004, … @decimal 0.4, 0.6, 0.9, 1.4, 1.6, 1.9, 2.4, 2.6, 10.4, 100.4, 1000.4, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 3: zero,one,other -->
|
||||
|
||||
<pluralRules locales="lv prg">
|
||||
<pluralRule count="zero">n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19 @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
<pluralRule count="one">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 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.0, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~9, 22~29, 102, 1002, … @decimal 0.2~0.9, 1.2~1.9, 10.2, 100.2, 1000.2, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="lag">
|
||||
<pluralRule count="zero">n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000</pluralRule>
|
||||
<pluralRule count="one">i = 0,1 and n != 0 @integer 1 @decimal 0.1~1.6</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="ksh">
|
||||
<pluralRule count="zero">n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000</pluralRule>
|
||||
<pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
|
||||
<pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 3: one,two,other -->
|
||||
|
||||
<pluralRules locales="iu kw naq se sma smi smj smn sms">
|
||||
<pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
|
||||
<pluralRule count="two">n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 3~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 3: one,few,other -->
|
||||
|
||||
<pluralRules locales="shi">
|
||||
<pluralRule count="one">i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04</pluralRule>
|
||||
<pluralRule count="few">n = 2..10 @integer 2~10 @decimal 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00</pluralRule>
|
||||
<pluralRule count="other"> @integer 11~26, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~1.9, 2.1~2.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="mo ro">
|
||||
<pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
|
||||
<pluralRule count="few">v != 0 or n = 0 or n != 1 and n % 100 = 1..19 @integer 0, 2~16, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 20~35, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="bs hr sh sr">
|
||||
<pluralRule count="one">v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …</pluralRule>
|
||||
<pluralRule count="few">v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.2~0.4, 1.2~1.4, 2.2~2.4, 3.2~3.4, 4.2~4.4, 5.2, 10.2, 100.2, 1000.2, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 4: one,two,few,other -->
|
||||
|
||||
<pluralRules locales="gd">
|
||||
<pluralRule count="one">n = 1,11 @integer 1, 11 @decimal 1.0, 11.0, 1.00, 11.00, 1.000, 11.000, 1.0000</pluralRule>
|
||||
<pluralRule count="two">n = 2,12 @integer 2, 12 @decimal 2.0, 12.0, 2.00, 12.00, 2.000, 12.000, 2.0000</pluralRule>
|
||||
<pluralRule count="few">n = 3..10,13..19 @integer 3~10, 13~19 @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 3.00</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 20~34, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="sl">
|
||||
<pluralRule count="one">v = 0 and i % 100 = 1 @integer 1, 101, 201, 301, 401, 501, 601, 701, 1001, …</pluralRule>
|
||||
<pluralRule count="two">v = 0 and i % 100 = 2 @integer 2, 102, 202, 302, 402, 502, 602, 702, 1002, …</pluralRule>
|
||||
<pluralRule count="few">v = 0 and i % 100 = 3..4 or v != 0 @integer 3, 4, 103, 104, 203, 204, 303, 304, 403, 404, 503, 504, 603, 604, 703, 704, 1003, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="dsb hsb">
|
||||
<pluralRule count="one">v = 0 and i % 100 = 1 or f % 100 = 1 @integer 1, 101, 201, 301, 401, 501, 601, 701, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …</pluralRule>
|
||||
<pluralRule count="two">v = 0 and i % 100 = 2 or f % 100 = 2 @integer 2, 102, 202, 302, 402, 502, 602, 702, 1002, … @decimal 0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2, 10.2, 100.2, 1000.2, …</pluralRule>
|
||||
<pluralRule count="few">v = 0 and i % 100 = 3..4 or f % 100 = 3..4 @integer 3, 4, 103, 104, 203, 204, 303, 304, 403, 404, 503, 504, 603, 604, 703, 704, 1003, … @decimal 0.3, 0.4, 1.3, 1.4, 2.3, 2.4, 3.3, 3.4, 4.3, 4.4, 5.3, 5.4, 6.3, 6.4, 7.3, 7.4, 10.3, 100.3, 1000.3, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 4: one,two,many,other -->
|
||||
|
||||
<pluralRules locales="he iw">
|
||||
<pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
|
||||
<pluralRule count="two">i = 2 and v = 0 @integer 2</pluralRule>
|
||||
<pluralRule count="many">v = 0 and n != 0..10 and n % 10 = 0 @integer 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 3~17, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 4: one,few,many,other -->
|
||||
|
||||
<pluralRules locales="cs sk">
|
||||
<pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
|
||||
<pluralRule count="few">i = 2..4 and v = 0 @integer 2~4</pluralRule>
|
||||
<pluralRule count="many">v != 0 @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="pl">
|
||||
<pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
|
||||
<pluralRule count="few">v = 0 and i % 10 = 2..4 and i % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, …</pluralRule>
|
||||
<pluralRule count="many">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 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
|
||||
<pluralRule count="other"> @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="be">
|
||||
<pluralRule count="one">n % 10 = 1 and n % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, …</pluralRule>
|
||||
<pluralRule count="few">n % 10 = 2..4 and n % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 2.0, 3.0, 4.0, 22.0, 23.0, 24.0, 32.0, 33.0, 102.0, 1002.0, …</pluralRule>
|
||||
<pluralRule count="many">n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
<pluralRule count="other"> @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="lt">
|
||||
<pluralRule count="one">n % 10 = 1 and n % 100 != 11..19 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, …</pluralRule>
|
||||
<pluralRule count="few">n % 10 = 2..9 and n % 100 != 11..19 @integer 2~9, 22~29, 102, 1002, … @decimal 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 22.0, 102.0, 1002.0, …</pluralRule>
|
||||
<pluralRule count="many">f != 0 @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="mt">
|
||||
<pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
|
||||
<pluralRule count="few">n = 0 or n % 100 = 2..10 @integer 0, 2~10, 102~107, 1002, … @decimal 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 102.0, 1002.0, …</pluralRule>
|
||||
<pluralRule count="many">n % 100 = 11..19 @integer 11~19, 111~117, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 20~35, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="ru uk">
|
||||
<pluralRule count="one">v = 0 and i % 10 = 1 and i % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …</pluralRule>
|
||||
<pluralRule count="few">v = 0 and i % 10 = 2..4 and i % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, …</pluralRule>
|
||||
<pluralRule count="many">v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
|
||||
<pluralRule count="other"> @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 5: one,two,few,many,other -->
|
||||
|
||||
<pluralRules locales="br">
|
||||
<pluralRule count="one">n % 10 = 1 and n % 100 != 11,71,91 @integer 1, 21, 31, 41, 51, 61, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 81.0, 101.0, 1001.0, …</pluralRule>
|
||||
<pluralRule count="two">n % 10 = 2 and n % 100 != 12,72,92 @integer 2, 22, 32, 42, 52, 62, 82, 102, 1002, … @decimal 2.0, 22.0, 32.0, 42.0, 52.0, 62.0, 82.0, 102.0, 1002.0, …</pluralRule>
|
||||
<pluralRule count="few">n % 10 = 3..4,9 and n % 100 != 10..19,70..79,90..99 @integer 3, 4, 9, 23, 24, 29, 33, 34, 39, 43, 44, 49, 103, 1003, … @decimal 3.0, 4.0, 9.0, 23.0, 24.0, 29.0, 33.0, 34.0, 103.0, 1003.0, …</pluralRule>
|
||||
<pluralRule count="many">n != 0 and n % 1000000 = 0 @integer 1000000, … @decimal 1000000.0, 1000000.00, 1000000.000, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 5~8, 10~20, 100, 1000, 10000, 100000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="ga">
|
||||
<pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
|
||||
<pluralRule count="two">n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000</pluralRule>
|
||||
<pluralRule count="few">n = 3..6 @integer 3~6 @decimal 3.0, 4.0, 5.0, 6.0, 3.00, 4.00, 5.00, 6.00, 3.000, 4.000, 5.000, 6.000, 3.0000, 4.0000, 5.0000, 6.0000</pluralRule>
|
||||
<pluralRule count="many">n = 7..10 @integer 7~10 @decimal 7.0, 8.0, 9.0, 10.0, 7.00, 8.00, 9.00, 10.00, 7.000, 8.000, 9.000, 10.000, 7.0000, 8.0000, 9.0000, 10.0000</pluralRule>
|
||||
<pluralRule count="other"> @integer 0, 11~25, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="gv">
|
||||
<pluralRule count="one">v = 0 and i % 10 = 1 @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, …</pluralRule>
|
||||
<pluralRule count="two">v = 0 and i % 10 = 2 @integer 2, 12, 22, 32, 42, 52, 62, 72, 102, 1002, …</pluralRule>
|
||||
<pluralRule count="few">v = 0 and i % 100 = 0,20,40,60,80 @integer 0, 20, 40, 60, 80, 100, 120, 140, 1000, 10000, 100000, 1000000, …</pluralRule>
|
||||
<pluralRule count="many">v != 0 @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 3~10, 13~19, 23, 103, 1003, …</pluralRule>
|
||||
</pluralRules>
|
||||
|
||||
<!-- 6: zero,one,two,few,many,other -->
|
||||
|
||||
<pluralRules locales="ar">
|
||||
<pluralRule count="zero">n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000</pluralRule>
|
||||
<pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
|
||||
<pluralRule count="two">n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000</pluralRule>
|
||||
<pluralRule count="few">n % 100 = 3..10 @integer 3~10, 103~110, 1003, … @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 103.0, 1003.0, …</pluralRule>
|
||||
<pluralRule count="many">n % 100 = 11..99 @integer 11~26, 111, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, …</pluralRule>
|
||||
<pluralRule count="other"> @integer 100~102, 200~202, 300~302, 400~402, 500~502, 600, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
<pluralRules locales="cy">
|
||||
<pluralRule count="zero">n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000</pluralRule>
|
||||
<pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
|
||||
<pluralRule count="two">n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000</pluralRule>
|
||||
<pluralRule count="few">n = 3 @integer 3 @decimal 3.0, 3.00, 3.000, 3.0000</pluralRule>
|
||||
<pluralRule count="many">n = 6 @integer 6 @decimal 6.0, 6.00, 6.000, 6.0000</pluralRule>
|
||||
<pluralRule count="other"> @integer 4, 5, 7~20, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
|
||||
</pluralRules>
|
||||
</plurals>
|
||||
</supplementalData>
|
143
vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/xml.go
generated
vendored
Normal file
143
vendor/github.com/nicksnyder/go-i18n/i18n/language/codegen/xml.go
generated
vendored
Normal file
|
@ -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")
|
||||
}
|
99
vendor/github.com/nicksnyder/go-i18n/i18n/language/language.go
generated
vendored
Normal file
99
vendor/github.com/nicksnyder/go-i18n/i18n/language/language.go
generated
vendored
Normal file
|
@ -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)
|
||||
}
|
85
vendor/github.com/nicksnyder/go-i18n/i18n/language/language_test.go
generated
vendored
Normal file
85
vendor/github.com/nicksnyder/go-i18n/i18n/language/language_test.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
package language
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
src string
|
||||
lang []*Language
|
||||
}{
|
||||
{"en", []*Language{{"en", pluralSpecs["en"]}}},
|
||||
{"en-US", []*Language{{"en-us", pluralSpecs["en"]}}},
|
||||
{"en_US", []*Language{{"en-us", pluralSpecs["en"]}}},
|
||||
{"en-GB", []*Language{{"en-gb", pluralSpecs["en"]}}},
|
||||
{"zh-CN", []*Language{{"zh-cn", pluralSpecs["zh"]}}},
|
||||
{"zh-TW", []*Language{{"zh-tw", pluralSpecs["zh"]}}},
|
||||
{"pt-BR", []*Language{{"pt-br", pluralSpecs["pt"]}}},
|
||||
{"pt_BR", []*Language{{"pt-br", pluralSpecs["pt"]}}},
|
||||
{"pt-PT", []*Language{{"pt-pt", pluralSpecs["pt-pt"]}}},
|
||||
{"pt_PT", []*Language{{"pt-pt", pluralSpecs["pt-pt"]}}},
|
||||
{"zh-Hans-CN", []*Language{{"zh-hans-cn", pluralSpecs["zh"]}}},
|
||||
{"zh-Hant-TW", []*Language{{"zh-hant-tw", pluralSpecs["zh"]}}},
|
||||
{"en-US-en-US", []*Language{{"en-us-en-us", pluralSpecs["en"]}}},
|
||||
{".en-US..en-US.", []*Language{{"en-us", pluralSpecs["en"]}}},
|
||||
{
|
||||
"it, xx-zz, xx-ZZ, zh, en-gb;q=0.8, en;q=0.7, es-ES;q=0.6, de-xx",
|
||||
[]*Language{
|
||||
{"it", pluralSpecs["it"]},
|
||||
{"zh", pluralSpecs["zh"]},
|
||||
{"en-gb", pluralSpecs["en"]},
|
||||
{"en", pluralSpecs["en"]},
|
||||
{"es-es", pluralSpecs["es"]},
|
||||
{"de-xx", pluralSpecs["de"]},
|
||||
},
|
||||
},
|
||||
{
|
||||
"it-qq,xx,xx-zz,xx-ZZ,zh,en-gb;q=0.8,en;q=0.7,es-ES;q=0.6,de-xx",
|
||||
[]*Language{
|
||||
{"it-qq", pluralSpecs["it"]},
|
||||
{"zh", pluralSpecs["zh"]},
|
||||
{"en-gb", pluralSpecs["en"]},
|
||||
{"en", pluralSpecs["en"]},
|
||||
{"es-es", pluralSpecs["es"]},
|
||||
{"de-xx", pluralSpecs["de"]},
|
||||
},
|
||||
},
|
||||
{"en.json", []*Language{{"en", pluralSpecs["en"]}}},
|
||||
{"en-US.json", []*Language{{"en-us", pluralSpecs["en"]}}},
|
||||
{"en-us.json", []*Language{{"en-us", pluralSpecs["en"]}}},
|
||||
{"en-xx.json", []*Language{{"en-xx", pluralSpecs["en"]}}},
|
||||
{"xx-Yyen-US", nil},
|
||||
{"en US", nil},
|
||||
{"", nil},
|
||||
{"-", nil},
|
||||
{"_", nil},
|
||||
{"-en", nil},
|
||||
{"_en", nil},
|
||||
{"-en-", nil},
|
||||
{"_en_", nil},
|
||||
{"xx", nil},
|
||||
}
|
||||
for _, test := range tests {
|
||||
lang := Parse(test.src)
|
||||
if !reflect.DeepEqual(lang, test.lang) {
|
||||
t.Errorf("Parse(%q) = %s expected %s", test.src, lang, test.lang)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchingTags(t *testing.T) {
|
||||
tests := []struct {
|
||||
lang *Language
|
||||
matches []string
|
||||
}{
|
||||
{&Language{"zh-hans-cn", nil}, []string{"zh", "zh-hans", "zh-hans-cn"}},
|
||||
{&Language{"foo", nil}, []string{"foo"}},
|
||||
}
|
||||
for _, test := range tests {
|
||||
if actual := test.lang.MatchingTags(); !reflect.DeepEqual(test.matches, actual) {
|
||||
t.Errorf("matchingTags(%q) = %q expected %q", test.lang.Tag, actual, test.matches)
|
||||
}
|
||||
}
|
||||
}
|
119
vendor/github.com/nicksnyder/go-i18n/i18n/language/operands.go
generated
vendored
Normal file
119
vendor/github.com/nicksnyder/go-i18n/i18n/language/operands.go
generated
vendored
Normal file
|
@ -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
|
||||
}
|
45
vendor/github.com/nicksnyder/go-i18n/i18n/language/operands_test.go
generated
vendored
Normal file
45
vendor/github.com/nicksnyder/go-i18n/i18n/language/operands_test.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package language
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewOperands(t *testing.T) {
|
||||
tests := []struct {
|
||||
input interface{}
|
||||
ops *operands
|
||||
err bool
|
||||
}{
|
||||
{int64(0), &operands{0.0, 0, 0, 0, 0, 0}, false},
|
||||
{int64(1), &operands{1.0, 1, 0, 0, 0, 0}, false},
|
||||
{"0", &operands{0.0, 0, 0, 0, 0, 0}, false},
|
||||
{"1", &operands{1.0, 1, 0, 0, 0, 0}, false},
|
||||
{"1.0", &operands{1.0, 1, 1, 0, 0, 0}, false},
|
||||
{"1.00", &operands{1.0, 1, 2, 0, 0, 0}, false},
|
||||
{"1.3", &operands{1.3, 1, 1, 1, 3, 3}, false},
|
||||
{"1.30", &operands{1.3, 1, 2, 1, 30, 3}, false},
|
||||
{"1.03", &operands{1.03, 1, 2, 2, 3, 3}, false},
|
||||
{"1.230", &operands{1.23, 1, 3, 2, 230, 23}, false},
|
||||
{"20.0230", &operands{20.023, 20, 4, 3, 230, 23}, false},
|
||||
{20.0230, nil, true},
|
||||
}
|
||||
for _, test := range tests {
|
||||
ops, err := newOperands(test.input)
|
||||
if err != nil && !test.err {
|
||||
t.Errorf("newOperands(%#v) unexpected error: %s", test.input, err)
|
||||
} else if err == nil && test.err {
|
||||
t.Errorf("newOperands(%#v) returned %#v; expected error", test.input, ops)
|
||||
} else if !reflect.DeepEqual(ops, test.ops) {
|
||||
t.Errorf("newOperands(%#v) returned %#v; expected %#v", test.input, ops, test.ops)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNewOperand(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := newOperands("1234.56780000"); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
40
vendor/github.com/nicksnyder/go-i18n/i18n/language/plural.go
generated
vendored
Normal file
40
vendor/github.com/nicksnyder/go-i18n/i18n/language/plural.go
generated
vendored
Normal file
|
@ -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)
|
||||
}
|
28
vendor/github.com/nicksnyder/go-i18n/i18n/language/plural_test.go
generated
vendored
Normal file
28
vendor/github.com/nicksnyder/go-i18n/i18n/language/plural_test.go
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
package language
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewPlural(t *testing.T) {
|
||||
tests := []struct {
|
||||
src string
|
||||
plural Plural
|
||||
err bool
|
||||
}{
|
||||
{"zero", Zero, false},
|
||||
{"one", One, false},
|
||||
{"two", Two, false},
|
||||
{"few", Few, false},
|
||||
{"many", Many, false},
|
||||
{"other", Other, false},
|
||||
{"asdf", Invalid, true},
|
||||
}
|
||||
for _, test := range tests {
|
||||
plural, err := NewPlural(test.src)
|
||||
wrongErr := (err != nil && !test.err) || (err == nil && test.err)
|
||||
if plural != test.plural || wrongErr {
|
||||
t.Errorf("NewPlural(%#v) returned %#v,%#v; expected %#v", test.src, plural, err, test.plural)
|
||||
}
|
||||
}
|
||||
}
|
74
vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec.go
generated
vendored
Normal file
74
vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec.go
generated
vendored
Normal file
|
@ -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
|
||||
}
|
567
vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen.go
generated
vendored
Normal file
567
vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen.go
generated
vendored
Normal file
|
@ -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
|
||||
},
|
||||
})
|
||||
}
|
645
vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen_test.go
generated
vendored
Normal file
645
vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_gen_test.go
generated
vendored
Normal file
|
@ -0,0 +1,645 @@
|
|||
package language
|
||||
|
||||
// This file is generated by i18n/language/codegen/generate.sh
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestBmBoDzIdIgIiInJaJboJvJwKdeKeaKmKoLktLoMsMyNqoRootSahSesSgThToViWoYoZh(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0~15", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []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"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAmAsBnFaGuHiKnMrZu(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"0", "1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.0~1.0", "0.00~0.04"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"1.1~2.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"am", "as", "bn", "fa", "gu", "hi", "kn", "mr", "zu"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFfFrHyKab(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"0", "1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.0~1.5"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"2.0~3.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"ff", "fr", "hy", "kab"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAstCaDeEnEtFiFyGlItJiNlSvSwUrYi(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"ast", "ca", "de", "en", "et", "fi", "fy", "gl", "it", "ji", "nl", "sv", "sw", "ur", "yi"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSi(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"0", "1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.0", "0.1", "1.0", "0.00", "0.01", "1.00", "0.000", "0.001", "1.000", "0.0000", "0.0001", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.2~0.9", "1.1~1.8", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"si"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAkBhGuwLnMgNsoPaTiWa(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"0", "1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.0", "1.0", "0.00", "1.00", "0.000", "1.000", "0.0000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"ak", "bh", "guw", "ln", "mg", "nso", "pa", "ti", "wa"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTzm(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"0", "1", "11~24"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.0", "1.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "20.0", "21.0", "22.0", "23.0", "24.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~10", "100~106", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"tzm"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPt(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"0", "1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.0", "1.0", "0.00", "1.00", "0.000", "1.000", "0.0000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"pt"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAfAsaAzBemBezBgBrxCeCggChrCkbDvEeElEoEsEuFoFurGswHaHawHuJgoJmcKaKajKcgKkKkjKlKsKsbKuKyLbLgMasMgoMlMnNahNbNdNeNnNnhNoNrNyNynOmOrOsPapPsRmRofRwkSaqSdhSehSnSoSqSsSsyStSyrTaTeTeoTigTkTnTrTsUgUzVeVoVunWaeXhXog(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "1.00", "1.000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []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"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPt_PT(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"pt_PT"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDa(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.1~1.6"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0", "2.0~3.4", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"da"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIs(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.1~1.6", "10.1", "100.1", "1000.1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"is"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMk(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "11", "21", "31", "41", "51", "61", "71", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "2~10", "12~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0", "0.2~1.0", "1.2~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"mk"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilTl(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"0~3", "5", "7", "8", "10~13", "15", "17", "18", "20", "21", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.0~0.3", "0.5", "0.7", "0.8", "1.0~1.3", "1.5", "1.7", "1.8", "2.0", "2.1", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"4", "6", "9", "14", "16", "19", "24", "26", "104", "1004"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.4", "0.6", "0.9", "1.4", "1.6", "1.9", "2.4", "2.6", "10.4", "100.4", "1000.4"})
|
||||
|
||||
locales := []string{"fil", "tl"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLvPrg(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, Zero, []string{"0", "10~20", "30", "40", "50", "60", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Zero, []string{"0.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.1", "1.0", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~9", "22~29", "102", "1002"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.2~0.9", "1.2~1.9", "10.2", "100.2", "1000.2"})
|
||||
|
||||
locales := []string{"lv", "prg"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLag(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, Zero, []string{"0"})
|
||||
tests = appendDecimalTests(tests, Zero, []string{"0.0", "0.00", "0.000", "0.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.1~1.6"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"2.0~3.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"lag"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKsh(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, Zero, []string{"0"})
|
||||
tests = appendDecimalTests(tests, Zero, []string{"0.0", "0.00", "0.000", "0.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "1.00", "1.000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"2~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"ksh"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIuKwNaqSeSmaSmiSmjSmnSms(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "1.00", "1.000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2"})
|
||||
tests = appendDecimalTests(tests, Two, []string{"2.0", "2.00", "2.000", "2.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "3~17", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"iu", "kw", "naq", "se", "sma", "smi", "smj", "smn", "sms"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShi(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"0", "1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.0~1.0", "0.00~0.04"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"2~10"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "2.00", "3.00", "4.00", "5.00", "6.00", "7.00", "8.00"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"11~26", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"1.1~1.9", "2.1~2.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"shi"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMoRo(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"0", "2~16", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"20~35", "100", "1000", "10000", "100000", "1000000"})
|
||||
|
||||
locales := []string{"mo", "ro"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBsHrShSr(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"0.2~0.4", "1.2~1.4", "2.2~2.4", "3.2~3.4", "4.2~4.4", "5.2", "10.2", "100.2", "1000.2"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0", "0.5~1.0", "1.5~2.0", "2.5~2.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"bs", "hr", "sh", "sr"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGd(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "11"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "11.0", "1.00", "11.00", "1.000", "11.000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2", "12"})
|
||||
tests = appendDecimalTests(tests, Two, []string{"2.0", "12.0", "2.00", "12.00", "2.000", "12.000", "2.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"3~10", "13~19"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "3.00"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "20~34", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~0.9", "1.1~1.6", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"gd"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSl(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "101", "201", "301", "401", "501", "601", "701", "1001"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2", "102", "202", "302", "402", "502", "602", "702", "1002"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"3", "4", "103", "104", "203", "204", "303", "304", "403", "404", "503", "504", "603", "604", "703", "704", "1003"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"})
|
||||
|
||||
locales := []string{"sl"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDsbHsb(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "101", "201", "301", "401", "501", "601", "701", "1001"})
|
||||
tests = appendDecimalTests(tests, One, []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2", "102", "202", "302", "402", "502", "602", "702", "1002"})
|
||||
tests = appendDecimalTests(tests, Two, []string{"0.2", "1.2", "2.2", "3.2", "4.2", "5.2", "6.2", "7.2", "10.2", "100.2", "1000.2"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"3", "4", "103", "104", "203", "204", "303", "304", "403", "404", "503", "504", "603", "604", "703", "704", "1003"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"0.3", "0.4", "1.3", "1.4", "2.3", "2.4", "3.3", "3.4", "4.3", "4.4", "5.3", "5.4", "6.3", "6.4", "7.3", "7.4", "10.3", "100.3", "1000.3"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0", "0.5~1.0", "1.5~2.0", "2.5~2.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"dsb", "hsb"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeIw(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"20", "30", "40", "50", "60", "70", "80", "90", "100", "1000", "10000", "100000", "1000000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "3~17", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"he", "iw"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCsSk(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"2~4"})
|
||||
|
||||
tests = appendDecimalTests(tests, Many, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"})
|
||||
|
||||
locales := []string{"cs", "sk"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPl(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"})
|
||||
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"pl"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBe(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "71.0", "81.0", "101.0", "1001.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"2.0", "3.0", "4.0", "22.0", "23.0", "24.0", "32.0", "33.0", "102.0", "1002.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Many, []string{"0.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "11.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.1~0.9", "1.1~1.7", "10.1", "100.1", "1000.1"})
|
||||
|
||||
locales := []string{"be"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLt(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "71.0", "81.0", "101.0", "1001.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"2~9", "22~29", "102", "1002"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "22.0", "102.0", "1002.0"})
|
||||
|
||||
tests = appendDecimalTests(tests, Many, []string{"0.1~0.9", "1.1~1.7", "10.1", "100.1", "1000.1"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "10~20", "30", "40", "50", "60", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"lt"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMt(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "1.00", "1.000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"0", "2~10", "102~107", "1002"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"0.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "10.0", "102.0", "1002.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"11~19", "111~117", "1011"})
|
||||
tests = appendDecimalTests(tests, Many, []string{"11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "111.0", "1011.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"20~35", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.1~0.9", "1.1~1.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"mt"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRuUk(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"})
|
||||
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"ru", "uk"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBr(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "21", "31", "41", "51", "61", "81", "101", "1001"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "81.0", "101.0", "1001.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2", "22", "32", "42", "52", "62", "82", "102", "1002"})
|
||||
tests = appendDecimalTests(tests, Two, []string{"2.0", "22.0", "32.0", "42.0", "52.0", "62.0", "82.0", "102.0", "1002.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"3", "4", "9", "23", "24", "29", "33", "34", "39", "43", "44", "49", "103", "1003"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"3.0", "4.0", "9.0", "23.0", "24.0", "29.0", "33.0", "34.0", "103.0", "1003.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"1000000"})
|
||||
tests = appendDecimalTests(tests, Many, []string{"1000000.0", "1000000.00", "1000000.000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "5~8", "10~20", "100", "1000", "10000", "100000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0"})
|
||||
|
||||
locales := []string{"br"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGa(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "1.00", "1.000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2"})
|
||||
tests = appendDecimalTests(tests, Two, []string{"2.0", "2.00", "2.000", "2.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"3~6"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"3.0", "4.0", "5.0", "6.0", "3.00", "4.00", "5.00", "6.00", "3.000", "4.000", "5.000", "6.000", "3.0000", "4.0000", "5.0000", "6.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"7~10"})
|
||||
tests = appendDecimalTests(tests, Many, []string{"7.0", "8.0", "9.0", "10.0", "7.00", "8.00", "9.00", "10.00", "7.000", "8.000", "9.000", "10.000", "7.0000", "8.0000", "9.0000", "10.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"0", "11~25", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.0~0.9", "1.1~1.6", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"ga"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGv(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1", "11", "21", "31", "41", "51", "61", "71", "101", "1001"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2", "12", "22", "32", "42", "52", "62", "72", "102", "1002"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"0", "20", "40", "60", "80", "100", "120", "140", "1000", "10000", "100000", "1000000"})
|
||||
|
||||
tests = appendDecimalTests(tests, Many, []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"3~10", "13~19", "23", "103", "1003"})
|
||||
|
||||
locales := []string{"gv"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAr(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, Zero, []string{"0"})
|
||||
tests = appendDecimalTests(tests, Zero, []string{"0.0", "0.00", "0.000", "0.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "1.00", "1.000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2"})
|
||||
tests = appendDecimalTests(tests, Two, []string{"2.0", "2.00", "2.000", "2.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"3~10", "103~110", "1003"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "103.0", "1003.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"11~26", "111", "1011"})
|
||||
tests = appendDecimalTests(tests, Many, []string{"11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "111.0", "1011.0"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"100~102", "200~202", "300~302", "400~402", "500~502", "600", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.1~0.9", "1.1~1.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"ar"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCy(t *testing.T) {
|
||||
var tests []pluralTest
|
||||
|
||||
tests = appendIntegerTests(tests, Zero, []string{"0"})
|
||||
tests = appendDecimalTests(tests, Zero, []string{"0.0", "0.00", "0.000", "0.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, One, []string{"1"})
|
||||
tests = appendDecimalTests(tests, One, []string{"1.0", "1.00", "1.000", "1.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Two, []string{"2"})
|
||||
tests = appendDecimalTests(tests, Two, []string{"2.0", "2.00", "2.000", "2.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Few, []string{"3"})
|
||||
tests = appendDecimalTests(tests, Few, []string{"3.0", "3.00", "3.000", "3.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Many, []string{"6"})
|
||||
tests = appendDecimalTests(tests, Many, []string{"6.0", "6.00", "6.000", "6.0000"})
|
||||
|
||||
tests = appendIntegerTests(tests, Other, []string{"4", "5", "7~20", "100", "1000", "10000", "100000", "1000000"})
|
||||
tests = appendDecimalTests(tests, Other, []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"})
|
||||
|
||||
locales := []string{"cy"}
|
||||
for _, locale := range locales {
|
||||
runTests(t, locale, tests)
|
||||
}
|
||||
}
|
733
vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_test.go
generated
vendored
Normal file
733
vendor/github.com/nicksnyder/go-i18n/i18n/language/pluralspec_test.go
generated
vendored
Normal file
|
@ -0,0 +1,733 @@
|
|||
package language
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const onePlusEpsilon = "1.00000000000000000000000000000001"
|
||||
|
||||
func TestGetPluralSpec(t *testing.T) {
|
||||
tests := []struct {
|
||||
src string
|
||||
spec *PluralSpec
|
||||
}{
|
||||
{"pl", pluralSpecs["pl"]},
|
||||
{"en", pluralSpecs["en"]},
|
||||
{"en-US", pluralSpecs["en"]},
|
||||
{"en_US", pluralSpecs["en"]},
|
||||
{"en-GB", pluralSpecs["en"]},
|
||||
{"zh-CN", pluralSpecs["zh"]},
|
||||
{"zh-TW", pluralSpecs["zh"]},
|
||||
{"pt-BR", pluralSpecs["pt"]},
|
||||
{"pt_BR", pluralSpecs["pt"]},
|
||||
{"pt-PT", pluralSpecs["pt-pt"]},
|
||||
{"pt_PT", pluralSpecs["pt-pt"]},
|
||||
{"zh-Hans-CN", pluralSpecs["zh"]},
|
||||
{"zh-Hant-TW", pluralSpecs["zh"]},
|
||||
{"zh-CN", pluralSpecs["zh"]},
|
||||
{"zh-TW", pluralSpecs["zh"]},
|
||||
{"zh-Hans", pluralSpecs["zh"]},
|
||||
{"zh-Hant", pluralSpecs["zh"]},
|
||||
{"ko-KR", pluralSpecs["ko"]},
|
||||
{"ko_KR", pluralSpecs["ko"]},
|
||||
{"ko-KP", pluralSpecs["ko"]},
|
||||
{"ko_KP", pluralSpecs["ko"]},
|
||||
{"en-US-en-US", pluralSpecs["en"]},
|
||||
{"th", pluralSpecs["th"]},
|
||||
{"th-TH", pluralSpecs["th"]},
|
||||
{"hr", pluralSpecs["hr"]},
|
||||
{"bs", pluralSpecs["bs"]},
|
||||
{"sr", pluralSpecs["sr"]},
|
||||
{"ti", pluralSpecs["ti"]},
|
||||
{"vi", pluralSpecs["vi"]},
|
||||
{"vi-VN", pluralSpecs["vi"]},
|
||||
{"mk", pluralSpecs["mk"]},
|
||||
{"mk-MK", pluralSpecs["mk"]},
|
||||
{"lv", pluralSpecs["lv"]},
|
||||
{"lv-LV", pluralSpecs["lv"]},
|
||||
{".en-US..en-US.", nil},
|
||||
{"zh, en-gb;q=0.8, en;q=0.7", nil},
|
||||
{"zh,en-gb;q=0.8,en;q=0.7", nil},
|
||||
{"xx, en-gb;q=0.8, en;q=0.7", nil},
|
||||
{"xx,en-gb;q=0.8,en;q=0.7", nil},
|
||||
{"xx-YY,xx;q=0.8,en-US,en;q=0.8,de;q=0.6,nl;q=0.4", nil},
|
||||
{"/foo/es/en.json", nil},
|
||||
{"xx-Yyen-US", nil},
|
||||
{"en US", nil},
|
||||
{"", nil},
|
||||
{"-", nil},
|
||||
{"_", nil},
|
||||
{".", nil},
|
||||
{"-en", nil},
|
||||
{"_en", nil},
|
||||
{"-en-", nil},
|
||||
{"_en_", nil},
|
||||
{"xx", nil},
|
||||
}
|
||||
for _, test := range tests {
|
||||
spec := getPluralSpec(test.src)
|
||||
if spec != test.spec {
|
||||
t.Errorf("getPluralSpec(%q) = %q expected %q", test.src, spec, test.spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type pluralTest struct {
|
||||
num interface{}
|
||||
plural Plural
|
||||
}
|
||||
|
||||
func appendIntegerTests(tests []pluralTest, plural Plural, examples []string) []pluralTest {
|
||||
for _, ex := range expandExamples(examples) {
|
||||
i, err := strconv.ParseInt(ex, 10, 64)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tests = append(tests, pluralTest{ex, plural}, pluralTest{i, plural})
|
||||
}
|
||||
return tests
|
||||
}
|
||||
|
||||
func appendDecimalTests(tests []pluralTest, plural Plural, examples []string) []pluralTest {
|
||||
for _, ex := range expandExamples(examples) {
|
||||
tests = append(tests, pluralTest{ex, plural})
|
||||
}
|
||||
return tests
|
||||
}
|
||||
|
||||
func expandExamples(examples []string) []string {
|
||||
var expanded []string
|
||||
for _, ex := range examples {
|
||||
if parts := strings.Split(ex, "~"); len(parts) == 2 {
|
||||
for ex := parts[0]; ; ex = increment(ex) {
|
||||
expanded = append(expanded, ex)
|
||||
if ex == parts[1] {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
expanded = append(expanded, ex)
|
||||
}
|
||||
}
|
||||
return expanded
|
||||
}
|
||||
|
||||
func increment(dec string) string {
|
||||
runes := []rune(dec)
|
||||
carry := true
|
||||
for i := len(runes) - 1; carry && i >= 0; i-- {
|
||||
switch runes[i] {
|
||||
case '.':
|
||||
continue
|
||||
case '9':
|
||||
runes[i] = '0'
|
||||
default:
|
||||
runes[i]++
|
||||
carry = false
|
||||
}
|
||||
}
|
||||
if carry {
|
||||
runes = append([]rune{'1'}, runes...)
|
||||
}
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
//
|
||||
// Below here are tests that were manually written before tests were automatically generated.
|
||||
// These are kept around as sanity checks for our code generation.
|
||||
//
|
||||
|
||||
func TestArabic(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Zero},
|
||||
{"0", Zero},
|
||||
{"0.0", Zero},
|
||||
{"0.00", Zero},
|
||||
{1, One},
|
||||
{"1", One},
|
||||
{"1.0", One},
|
||||
{"1.00", One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Two},
|
||||
{"2", Two},
|
||||
{"2.0", Two},
|
||||
{"2.00", Two},
|
||||
{3, Few},
|
||||
{"3", Few},
|
||||
{"3.0", Few},
|
||||
{"3.00", Few},
|
||||
{10, Few},
|
||||
{"10", Few},
|
||||
{"10.0", Few},
|
||||
{"10.00", Few},
|
||||
{103, Few},
|
||||
{"103", Few},
|
||||
{"103.0", Few},
|
||||
{"103.00", Few},
|
||||
{110, Few},
|
||||
{"110", Few},
|
||||
{"110.0", Few},
|
||||
{"110.00", Few},
|
||||
{11, Many},
|
||||
{"11", Many},
|
||||
{"11.0", Many},
|
||||
{"11.00", Many},
|
||||
{99, Many},
|
||||
{"99", Many},
|
||||
{"99.0", Many},
|
||||
{"99.00", Many},
|
||||
{111, Many},
|
||||
{"111", Many},
|
||||
{"111.0", Many},
|
||||
{"111.00", Many},
|
||||
{199, Many},
|
||||
{"199", Many},
|
||||
{"199.0", Many},
|
||||
{"199.00", Many},
|
||||
{100, Other},
|
||||
{"100", Other},
|
||||
{"100.0", Other},
|
||||
{"100.00", Other},
|
||||
{102, Other},
|
||||
{"102", Other},
|
||||
{"102.0", Other},
|
||||
{"102.00", Other},
|
||||
{200, Other},
|
||||
{"200", Other},
|
||||
{"200.0", Other},
|
||||
{"200.00", Other},
|
||||
{202, Other},
|
||||
{"202", Other},
|
||||
{"202.0", Other},
|
||||
{"202.00", Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.1, 0.9, Other)
|
||||
tests = appendFloatTests(tests, 1.1, 1.9, Other)
|
||||
tests = appendFloatTests(tests, 2.1, 2.9, Other)
|
||||
tests = appendFloatTests(tests, 3.1, 3.9, Other)
|
||||
tests = appendFloatTests(tests, 4.1, 4.9, Other)
|
||||
runTests(t, "ar", tests)
|
||||
}
|
||||
|
||||
func TestBelarusian(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Many},
|
||||
{1, One},
|
||||
{2, Few},
|
||||
{3, Few},
|
||||
{4, Few},
|
||||
{5, Many},
|
||||
{19, Many},
|
||||
{20, Many},
|
||||
{21, One},
|
||||
{11, Many},
|
||||
{52, Few},
|
||||
{101, One},
|
||||
{"0.1", Other},
|
||||
{"0.7", Other},
|
||||
{"1.5", Other},
|
||||
{"1.0", One},
|
||||
{onePlusEpsilon, Other},
|
||||
{"2.0", Few},
|
||||
{"10.0", Many},
|
||||
}
|
||||
runTests(t, "be", tests)
|
||||
}
|
||||
|
||||
func TestBurmese(t *testing.T) {
|
||||
tests := appendIntTests(nil, 0, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "my", tests)
|
||||
}
|
||||
|
||||
func TestCatalan(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{"0", Other},
|
||||
{1, One},
|
||||
{"1", One},
|
||||
{"1.0", Other},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
{"2", Other},
|
||||
}
|
||||
tests = appendIntTests(tests, 2, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "ca", tests)
|
||||
}
|
||||
|
||||
func TestChinese(t *testing.T) {
|
||||
tests := appendIntTests(nil, 0, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "zh", tests)
|
||||
}
|
||||
|
||||
func TestCzech(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{"0", Other},
|
||||
{1, One},
|
||||
{"1", One},
|
||||
{onePlusEpsilon, Many},
|
||||
{2, Few},
|
||||
{"2", Few},
|
||||
{3, Few},
|
||||
{"3", Few},
|
||||
{4, Few},
|
||||
{"4", Few},
|
||||
{5, Other},
|
||||
{"5", Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0, 10, Many)
|
||||
runTests(t, "cs", tests)
|
||||
}
|
||||
|
||||
func TestDanish(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{onePlusEpsilon, One},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.1, 1.9, One)
|
||||
tests = appendFloatTests(tests, 2.0, 10.0, Other)
|
||||
runTests(t, "da", tests)
|
||||
}
|
||||
|
||||
func TestDutch(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.0, 10.0, Other)
|
||||
runTests(t, "nl", tests)
|
||||
}
|
||||
|
||||
func TestEnglish(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.0, 10.0, Other)
|
||||
runTests(t, "en", tests)
|
||||
}
|
||||
|
||||
func TestFrench(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, One},
|
||||
{1, One},
|
||||
{onePlusEpsilon, One},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.0, 1.9, One)
|
||||
tests = appendFloatTests(tests, 2.0, 10.0, Other)
|
||||
runTests(t, "fr", tests)
|
||||
}
|
||||
|
||||
func TestGerman(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.0, 10.0, Other)
|
||||
runTests(t, "de", tests)
|
||||
}
|
||||
|
||||
func TestIcelandic(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{2, Other},
|
||||
{11, Other},
|
||||
{21, One},
|
||||
{111, Other},
|
||||
{"0.0", Other},
|
||||
{"0.1", One},
|
||||
{"2.0", Other},
|
||||
}
|
||||
runTests(t, "is", tests)
|
||||
}
|
||||
|
||||
func TestIndonesian(t *testing.T) {
|
||||
tests := appendIntTests(nil, 0, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "id", tests)
|
||||
}
|
||||
|
||||
func TestItalian(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.0, 10.0, Other)
|
||||
runTests(t, "it", tests)
|
||||
}
|
||||
|
||||
func TestKorean(t *testing.T) {
|
||||
tests := appendIntTests(nil, 0, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "ko", tests)
|
||||
}
|
||||
|
||||
func TestLatvian(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Zero},
|
||||
{"0", Zero},
|
||||
{"0.1", One},
|
||||
{1, One},
|
||||
{"1", One},
|
||||
{onePlusEpsilon, One},
|
||||
{"10.0", Zero},
|
||||
{"10.1", One},
|
||||
{"10.2", Other},
|
||||
{21, One},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.2, 0.9, Other)
|
||||
tests = appendFloatTests(tests, 1.2, 1.9, Other)
|
||||
tests = appendIntTests(tests, 2, 9, Other)
|
||||
tests = appendIntTests(tests, 10, 20, Zero)
|
||||
tests = appendIntTests(tests, 22, 29, Other)
|
||||
runTests(t, "lv", tests)
|
||||
}
|
||||
|
||||
func TestJapanese(t *testing.T) {
|
||||
tests := appendIntTests(nil, 0, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "ja", tests)
|
||||
}
|
||||
|
||||
func TestLithuanian(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{2, Few},
|
||||
{3, Few},
|
||||
{9, Few},
|
||||
{10, Other},
|
||||
{11, Other},
|
||||
{"0.1", Many},
|
||||
{"0.7", Many},
|
||||
{"1.0", One},
|
||||
{onePlusEpsilon, Many},
|
||||
{"2.0", Few},
|
||||
{"10.0", Other},
|
||||
}
|
||||
runTests(t, "lt", tests)
|
||||
}
|
||||
|
||||
func TestMalay(t *testing.T) {
|
||||
tests := appendIntTests(nil, 0, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "ms", tests)
|
||||
}
|
||||
|
||||
func TestPolish(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Many},
|
||||
{1, One},
|
||||
{2, Few},
|
||||
{3, Few},
|
||||
{4, Few},
|
||||
{5, Many},
|
||||
{19, Many},
|
||||
{20, Many},
|
||||
{10, Many},
|
||||
{11, Many},
|
||||
{52, Few},
|
||||
{"0.1", Other},
|
||||
{"0.7", Other},
|
||||
{"1.5", Other},
|
||||
{"1.0", Other},
|
||||
{onePlusEpsilon, Other},
|
||||
{"2.0", Other},
|
||||
{"10.0", Other},
|
||||
}
|
||||
runTests(t, "pl", tests)
|
||||
}
|
||||
|
||||
func TestPortuguese(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, One},
|
||||
{"0.0", One},
|
||||
{1, One},
|
||||
{"1.0", One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.1, 0.9, Other)
|
||||
tests = appendFloatTests(tests, 1.1, 10.0, Other)
|
||||
runTests(t, "pt", tests)
|
||||
}
|
||||
|
||||
func TestMacedonian(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{"1.1", One},
|
||||
{"2.1", One},
|
||||
{onePlusEpsilon, One},
|
||||
{2, Other},
|
||||
{"2.2", Other},
|
||||
{11, One},
|
||||
}
|
||||
runTests(t, "mk", tests)
|
||||
}
|
||||
|
||||
func TestPortugueseEuropean(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{"0.0", Other},
|
||||
{"0.1", Other},
|
||||
{"0.01", Other},
|
||||
{1, One},
|
||||
{"1", One},
|
||||
{"1.1", Other},
|
||||
{"1.01", Other},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 2.0, 10.0, Other)
|
||||
runTests(t, "pt-pt", tests)
|
||||
}
|
||||
|
||||
func TestRussian(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Many},
|
||||
{1, One},
|
||||
{2, Few},
|
||||
{3, Few},
|
||||
{4, Few},
|
||||
{5, Many},
|
||||
{19, Many},
|
||||
{20, Many},
|
||||
{21, One},
|
||||
{11, Many},
|
||||
{52, Few},
|
||||
{101, One},
|
||||
{"0.1", Other},
|
||||
{"0.7", Other},
|
||||
{"1.5", Other},
|
||||
{"1.0", Other},
|
||||
{onePlusEpsilon, Other},
|
||||
{"2.0", Other},
|
||||
{"10.0", Other},
|
||||
}
|
||||
runTests(t, "ru", tests)
|
||||
}
|
||||
|
||||
func TestSpanish(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{"1", One},
|
||||
{"1.0", One},
|
||||
{"1.00", One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.0, 0.9, Other)
|
||||
tests = appendFloatTests(tests, 1.1, 10.0, Other)
|
||||
runTests(t, "es", tests)
|
||||
}
|
||||
|
||||
func TestNorweigan(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{"1", One},
|
||||
{"1.0", One},
|
||||
{"1.00", One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.0, 0.9, Other)
|
||||
tests = appendFloatTests(tests, 1.1, 10.0, Other)
|
||||
runTests(t, "no", tests)
|
||||
}
|
||||
|
||||
func TestBulgarian(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{2, Other},
|
||||
{3, Other},
|
||||
{9, Other},
|
||||
{10, Other},
|
||||
{11, Other},
|
||||
{"0.1", Other},
|
||||
{"0.7", Other},
|
||||
{"1.0", One},
|
||||
{"1.001", Other},
|
||||
{onePlusEpsilon, Other},
|
||||
{"1.1", Other},
|
||||
{"2.0", Other},
|
||||
{"10.0", Other},
|
||||
}
|
||||
runTests(t, "bg", tests)
|
||||
}
|
||||
|
||||
func TestSwedish(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
}
|
||||
tests = appendFloatTests(tests, 0.0, 10.0, Other)
|
||||
runTests(t, "sv", tests)
|
||||
}
|
||||
|
||||
func TestThai(t *testing.T) {
|
||||
tests := appendIntTests(nil, 0, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "th", tests)
|
||||
}
|
||||
|
||||
func TestVietnamese(t *testing.T) {
|
||||
tests := appendIntTests(nil, 0, 10, Other)
|
||||
tests = appendFloatTests(tests, 0, 10, Other)
|
||||
runTests(t, "vi", tests)
|
||||
}
|
||||
|
||||
func TestTurkish(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Other},
|
||||
{1, One},
|
||||
{"1", One},
|
||||
{"1.0", One},
|
||||
{"1.00", One},
|
||||
{"1.001", Other},
|
||||
{"1.100", Other},
|
||||
{"1.101", Other},
|
||||
{onePlusEpsilon, Other},
|
||||
{2, Other},
|
||||
{"0.7", Other},
|
||||
{"2.0", Other},
|
||||
}
|
||||
runTests(t, "tr", tests)
|
||||
}
|
||||
|
||||
func TestUkrainian(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, Many},
|
||||
{1, One},
|
||||
{2, Few},
|
||||
{3, Few},
|
||||
{4, Few},
|
||||
{5, Many},
|
||||
{19, Many},
|
||||
{20, Many},
|
||||
{21, One},
|
||||
{11, Many},
|
||||
{52, Few},
|
||||
{101, One},
|
||||
{"0.1", Other},
|
||||
{"0.7", Other},
|
||||
{"1.5", Other},
|
||||
{"1.0", Other},
|
||||
{onePlusEpsilon, Other},
|
||||
{"2.0", Other},
|
||||
{"10.0", Other},
|
||||
}
|
||||
runTests(t, "uk", tests)
|
||||
}
|
||||
|
||||
func TestCroatian(t *testing.T) {
|
||||
tests := makeCroatianBosnianSerbianTests()
|
||||
runTests(t, "hr", tests)
|
||||
}
|
||||
|
||||
func TestBosnian(t *testing.T) {
|
||||
tests := makeCroatianBosnianSerbianTests()
|
||||
runTests(t, "bs", tests)
|
||||
}
|
||||
|
||||
func TestSerbian(t *testing.T) {
|
||||
tests := makeCroatianBosnianSerbianTests()
|
||||
runTests(t, "sr", tests)
|
||||
}
|
||||
|
||||
func makeCroatianBosnianSerbianTests() []pluralTest {
|
||||
return []pluralTest{
|
||||
{1, One},
|
||||
{"0.1", One},
|
||||
{21, One},
|
||||
{101, One},
|
||||
{1001, One},
|
||||
{51, One},
|
||||
{"1.1", One},
|
||||
{"5.1", One},
|
||||
{"100.1", One},
|
||||
{"1000.1", One},
|
||||
{2, Few},
|
||||
{"0.2", Few},
|
||||
{22, Few},
|
||||
{"1.2", Few},
|
||||
{24, Few},
|
||||
{"2.4", Few},
|
||||
{102, Few},
|
||||
{"100.2", Few},
|
||||
{1002, Few},
|
||||
{"1000.2", Few},
|
||||
{5, Other},
|
||||
{"0.5", Other},
|
||||
{0, Other},
|
||||
{100, Other},
|
||||
{19, Other},
|
||||
{"0.0", Other},
|
||||
{"100.0", Other},
|
||||
{"1000.0", Other},
|
||||
}
|
||||
}
|
||||
|
||||
func TestTigrinya(t *testing.T) {
|
||||
tests := []pluralTest{
|
||||
{0, One},
|
||||
{1, One},
|
||||
}
|
||||
tests = appendIntTests(tests, 2, 10, Other)
|
||||
tests = appendFloatTests(tests, 1.1, 10.0, Other)
|
||||
runTests(t, "ti", tests)
|
||||
}
|
||||
|
||||
func appendIntTests(tests []pluralTest, from, to int, p Plural) []pluralTest {
|
||||
for i := from; i <= to; i++ {
|
||||
tests = append(tests, pluralTest{i, p})
|
||||
}
|
||||
return tests
|
||||
}
|
||||
|
||||
func appendFloatTests(tests []pluralTest, from, to float64, p Plural) []pluralTest {
|
||||
stride := 0.1
|
||||
format := "%.1f"
|
||||
for f := from; f < to; f += stride {
|
||||
tests = append(tests, pluralTest{fmt.Sprintf(format, f), p})
|
||||
}
|
||||
tests = append(tests, pluralTest{fmt.Sprintf(format, to), p})
|
||||
return tests
|
||||
}
|
||||
|
||||
func runTests(t *testing.T, pluralSpecID string, tests []pluralTest) {
|
||||
pluralSpecID = normalizePluralSpecID(pluralSpecID)
|
||||
if spec := pluralSpecs[pluralSpecID]; spec != nil {
|
||||
for _, test := range tests {
|
||||
if plural, err := spec.Plural(test.num); plural != test.plural {
|
||||
t.Errorf("%s: PluralCategory(%#v) returned %s, %v; expected %s", pluralSpecID, test.num, plural, err, test.plural)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t.Errorf("could not find plural spec for locale %s", pluralSpecID)
|
||||
}
|
||||
|
||||
}
|
78
vendor/github.com/nicksnyder/go-i18n/i18n/translation/plural_translation.go
generated
vendored
Normal file
78
vendor/github.com/nicksnyder/go-i18n/i18n/translation/plural_translation.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
package translation
|
||||
|
||||
import (
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
)
|
||||
|
||||
type pluralTranslation struct {
|
||||
id string
|
||||
templates map[language.Plural]*template
|
||||
}
|
||||
|
||||
func (pt *pluralTranslation) MarshalInterface() interface{} {
|
||||
return map[string]interface{}{
|
||||
"id": pt.id,
|
||||
"translation": pt.templates,
|
||||
}
|
||||
}
|
||||
|
||||
func (pt *pluralTranslation) ID() string {
|
||||
return pt.id
|
||||
}
|
||||
|
||||
func (pt *pluralTranslation) Template(pc language.Plural) *template {
|
||||
return pt.templates[pc]
|
||||
}
|
||||
|
||||
func (pt *pluralTranslation) UntranslatedCopy() Translation {
|
||||
return &pluralTranslation{pt.id, make(map[language.Plural]*template)}
|
||||
}
|
||||
|
||||
func (pt *pluralTranslation) Normalize(l *language.Language) Translation {
|
||||
// Delete plural categories that don't belong to this language.
|
||||
for pc := range pt.templates {
|
||||
if _, ok := l.Plurals[pc]; !ok {
|
||||
delete(pt.templates, pc)
|
||||
}
|
||||
}
|
||||
// Create map entries for missing valid categories.
|
||||
for pc := range l.Plurals {
|
||||
if _, ok := pt.templates[pc]; !ok {
|
||||
pt.templates[pc] = mustNewTemplate("")
|
||||
}
|
||||
}
|
||||
return pt
|
||||
}
|
||||
|
||||
func (pt *pluralTranslation) Backfill(src Translation) Translation {
|
||||
for pc, t := range pt.templates {
|
||||
if t == nil || t.src == "" {
|
||||
pt.templates[pc] = src.Template(language.Other)
|
||||
}
|
||||
}
|
||||
return pt
|
||||
}
|
||||
|
||||
func (pt *pluralTranslation) Merge(t Translation) Translation {
|
||||
other, ok := t.(*pluralTranslation)
|
||||
if !ok || pt.ID() != t.ID() {
|
||||
return t
|
||||
}
|
||||
for pluralCategory, template := range other.templates {
|
||||
if template != nil && template.src != "" {
|
||||
pt.templates[pluralCategory] = template
|
||||
}
|
||||
}
|
||||
return pt
|
||||
}
|
||||
|
||||
func (pt *pluralTranslation) Incomplete(l *language.Language) bool {
|
||||
for pc := range l.Plurals {
|
||||
if t := pt.templates[pc]; t == nil || t.src == "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var _ = Translation(&pluralTranslation{})
|
308
vendor/github.com/nicksnyder/go-i18n/i18n/translation/plural_translation_test.go
generated
vendored
Normal file
308
vendor/github.com/nicksnyder/go-i18n/i18n/translation/plural_translation_test.go
generated
vendored
Normal file
|
@ -0,0 +1,308 @@
|
|||
package translation
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
)
|
||||
|
||||
func mustTemplate(t *testing.T, src string) *template {
|
||||
tmpl, err := newTemplate(src)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return tmpl
|
||||
}
|
||||
|
||||
func pluralTranslationFixture(t *testing.T, id string, pluralCategories ...language.Plural) *pluralTranslation {
|
||||
templates := make(map[language.Plural]*template, len(pluralCategories))
|
||||
for _, pc := range pluralCategories {
|
||||
templates[pc] = mustTemplate(t, string(pc))
|
||||
}
|
||||
return &pluralTranslation{id, templates}
|
||||
}
|
||||
|
||||
func verifyDeepEqual(t *testing.T, actual, expected interface{}) {
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("\n%#v\nnot equal to expected value\n%#v", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluralTranslationMerge(t *testing.T) {
|
||||
pt := pluralTranslationFixture(t, "id", language.One, language.Other)
|
||||
oneTemplate, otherTemplate := pt.templates[language.One], pt.templates[language.Other]
|
||||
|
||||
pt.Merge(pluralTranslationFixture(t, "id"))
|
||||
verifyDeepEqual(t, pt.templates, map[language.Plural]*template{
|
||||
language.One: oneTemplate,
|
||||
language.Other: otherTemplate,
|
||||
})
|
||||
|
||||
pt2 := pluralTranslationFixture(t, "id", language.One, language.Two)
|
||||
pt.Merge(pt2)
|
||||
verifyDeepEqual(t, pt.templates, map[language.Plural]*template{
|
||||
language.One: pt2.templates[language.One],
|
||||
language.Two: pt2.templates[language.Two],
|
||||
language.Other: otherTemplate,
|
||||
})
|
||||
}
|
||||
|
||||
/* Test implementations from old idea
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
ls := &LocalizedString{
|
||||
ID: "id",
|
||||
Translation: testingTemplate(t, "translation {{.Hello}}"),
|
||||
Translations: map[language.Plural]*template{
|
||||
language.One: testingTemplate(t, "plural {{.One}}"),
|
||||
language.Other: testingTemplate(t, "plural {{.Other}}"),
|
||||
},
|
||||
}
|
||||
|
||||
c := ls.Copy()
|
||||
delete(c.Translations, language.One)
|
||||
if _, ok := ls.Translations[language.One]; !ok {
|
||||
t.Errorf("deleting plural translation from copy deleted it from the original")
|
||||
}
|
||||
c.Translations[language.Two] = testingTemplate(t, "plural {{.Two}}")
|
||||
if _, ok := ls.Translations[language.Two]; ok {
|
||||
t.Errorf("adding plural translation to copy added it to the original")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalize(t *testing.T) {
|
||||
oneTemplate := testingTemplate(t, "one {{.One}}")
|
||||
ls := &LocalizedString{
|
||||
Translation: testingTemplate(t, "single {{.Single}}"),
|
||||
Translations: map[language.Plural]*template{
|
||||
language.One: oneTemplate,
|
||||
language.Two: testingTemplate(t, "two {{.Two}}"),
|
||||
},
|
||||
}
|
||||
ls.Normalize(LanguageWithCode("en"))
|
||||
if ls.Translation != nil {
|
||||
t.Errorf("ls.Translation is %#v; expected nil", ls.Translation)
|
||||
}
|
||||
if actual := ls.Translations[language.Two]; actual != nil {
|
||||
t.Errorf("ls.Translation[language.Two] is %#v; expected nil", actual)
|
||||
}
|
||||
if actual := ls.Translations[language.One]; actual != oneTemplate {
|
||||
t.Errorf("ls.Translations[language.One] is %#v; expected %#v", actual, oneTemplate)
|
||||
}
|
||||
if _, ok := ls.Translations[language.Other]; !ok {
|
||||
t.Errorf("ls.Translations[language.Other] shouldn't be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeTranslation(t *testing.T) {
|
||||
ls := &LocalizedString{}
|
||||
|
||||
translation := testingTemplate(t, "one {{.Hello}}")
|
||||
ls.Merge(&LocalizedString{
|
||||
Translation: translation,
|
||||
})
|
||||
if ls.Translation != translation {
|
||||
t.Errorf("expected %#v; got %#v", translation, ls.Translation)
|
||||
}
|
||||
|
||||
ls.Merge(&LocalizedString{})
|
||||
if ls.Translation != translation {
|
||||
t.Errorf("expected %#v; got %#v", translation, ls.Translation)
|
||||
}
|
||||
|
||||
translation = testingTemplate(t, "two {{.Hello}}")
|
||||
ls.Merge(&LocalizedString{
|
||||
Translation: translation,
|
||||
})
|
||||
if ls.Translation != translation {
|
||||
t.Errorf("expected %#v; got %#v", translation, ls.Translation)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeTranslations(t *testing.T) {
|
||||
ls := &LocalizedString{}
|
||||
|
||||
oneTemplate := testingTemplate(t, "one {{.One}}")
|
||||
otherTemplate := testingTemplate(t, "other {{.Other}}")
|
||||
ls.Merge(&LocalizedString{
|
||||
Translations: map[language.Plural]*template{
|
||||
language.One: oneTemplate,
|
||||
language.Other: otherTemplate,
|
||||
},
|
||||
})
|
||||
if actual := ls.Translations[language.One]; actual != oneTemplate {
|
||||
t.Errorf("ls.Translations[language.One] expected %#v; got %#v", oneTemplate, actual)
|
||||
}
|
||||
if actual := ls.Translations[language.Other]; actual != otherTemplate {
|
||||
t.Errorf("ls.Translations[language.Other] expected %#v; got %#v", otherTemplate, actual)
|
||||
}
|
||||
|
||||
ls.Merge(&LocalizedString{
|
||||
Translations: map[language.Plural]*template{},
|
||||
})
|
||||
if actual := ls.Translations[language.One]; actual != oneTemplate {
|
||||
t.Errorf("ls.Translations[language.One] expected %#v; got %#v", oneTemplate, actual)
|
||||
}
|
||||
if actual := ls.Translations[language.Other]; actual != otherTemplate {
|
||||
t.Errorf("ls.Translations[language.Other] expected %#v; got %#v", otherTemplate, actual)
|
||||
}
|
||||
|
||||
twoTemplate := testingTemplate(t, "two {{.Two}}")
|
||||
otherTemplate = testingTemplate(t, "second other {{.Other}}")
|
||||
ls.Merge(&LocalizedString{
|
||||
Translations: map[language.Plural]*template{
|
||||
language.Two: twoTemplate,
|
||||
language.Other: otherTemplate,
|
||||
},
|
||||
})
|
||||
if actual := ls.Translations[language.One]; actual != oneTemplate {
|
||||
t.Errorf("ls.Translations[language.One] expected %#v; got %#v", oneTemplate, actual)
|
||||
}
|
||||
if actual := ls.Translations[language.Two]; actual != twoTemplate {
|
||||
t.Errorf("ls.Translations[language.Two] expected %#v; got %#v", twoTemplate, actual)
|
||||
}
|
||||
if actual := ls.Translations[language.Other]; actual != otherTemplate {
|
||||
t.Errorf("ls.Translations[language.Other] expected %#v; got %#v", otherTemplate, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingTranslations(t *testing.T) {
|
||||
en := LanguageWithCode("en")
|
||||
|
||||
tests := []struct {
|
||||
localizedString *LocalizedString
|
||||
language *Language
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
&LocalizedString{},
|
||||
en,
|
||||
true,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translation: testingTemplate(t, "single {{.Single}}")},
|
||||
en,
|
||||
false,
|
||||
},
|
||||
{
|
||||
&LocalizedString{
|
||||
Translation: testingTemplate(t, "single {{.Single}}"),
|
||||
Translations: map[language.Plural]*template{
|
||||
language.One: testingTemplate(t, "one {{.One}}"),
|
||||
}},
|
||||
en,
|
||||
true,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translations: map[language.Plural]*template{
|
||||
language.One: testingTemplate(t, "one {{.One}}"),
|
||||
}},
|
||||
en,
|
||||
true,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translations: map[language.Plural]*template{
|
||||
language.One: nil,
|
||||
language.Other: nil,
|
||||
}},
|
||||
en,
|
||||
true,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translations: map[language.Plural]*template{
|
||||
language.One: testingTemplate(t, ""),
|
||||
language.Other: testingTemplate(t, ""),
|
||||
}},
|
||||
en,
|
||||
true,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translations: map[language.Plural]*template{
|
||||
language.One: testingTemplate(t, "one {{.One}}"),
|
||||
language.Other: testingTemplate(t, "other {{.Other}}"),
|
||||
}},
|
||||
en,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if actual := tt.localizedString.MissingTranslations(tt.language); actual != tt.expected {
|
||||
t.Errorf("expected %t got %t for %s, %#v",
|
||||
tt.expected, actual, tt.language.code, tt.localizedString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasTranslations(t *testing.T) {
|
||||
en := LanguageWithCode("en")
|
||||
|
||||
tests := []struct {
|
||||
localizedString *LocalizedString
|
||||
language *Language
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
&LocalizedString{},
|
||||
en,
|
||||
false,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translation: testingTemplate(t, "single {{.Single}}")},
|
||||
en,
|
||||
true,
|
||||
},
|
||||
{
|
||||
&LocalizedString{
|
||||
Translation: testingTemplate(t, "single {{.Single}}"),
|
||||
Translations: map[language.Plural]*template{}},
|
||||
en,
|
||||
false,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translations: map[language.Plural]*template{
|
||||
language.One: testingTemplate(t, "one {{.One}}"),
|
||||
}},
|
||||
en,
|
||||
true,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translations: map[language.Plural]*template{
|
||||
language.Two: testingTemplate(t, "two {{.Two}}"),
|
||||
}},
|
||||
en,
|
||||
false,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translations: map[language.Plural]*template{
|
||||
language.One: nil,
|
||||
}},
|
||||
en,
|
||||
false,
|
||||
},
|
||||
{
|
||||
&LocalizedString{Translations: map[language.Plural]*template{
|
||||
language.One: testingTemplate(t, ""),
|
||||
}},
|
||||
en,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if actual := tt.localizedString.HasTranslations(tt.language); actual != tt.expected {
|
||||
t.Errorf("expected %t got %t for %s, %#v",
|
||||
tt.expected, actual, tt.language.code, tt.localizedString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testingTemplate(t *testing.T, src string) *template {
|
||||
tmpl, err := newTemplate(src)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return tmpl
|
||||
}
|
||||
*/
|
57
vendor/github.com/nicksnyder/go-i18n/i18n/translation/single_translation.go
generated
vendored
Normal file
57
vendor/github.com/nicksnyder/go-i18n/i18n/translation/single_translation.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
package translation
|
||||
|
||||
import (
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
)
|
||||
|
||||
type singleTranslation struct {
|
||||
id string
|
||||
template *template
|
||||
}
|
||||
|
||||
func (st *singleTranslation) MarshalInterface() interface{} {
|
||||
return map[string]interface{}{
|
||||
"id": st.id,
|
||||
"translation": st.template,
|
||||
}
|
||||
}
|
||||
|
||||
func (st *singleTranslation) ID() string {
|
||||
return st.id
|
||||
}
|
||||
|
||||
func (st *singleTranslation) Template(pc language.Plural) *template {
|
||||
return st.template
|
||||
}
|
||||
|
||||
func (st *singleTranslation) UntranslatedCopy() Translation {
|
||||
return &singleTranslation{st.id, mustNewTemplate("")}
|
||||
}
|
||||
|
||||
func (st *singleTranslation) Normalize(language *language.Language) Translation {
|
||||
return st
|
||||
}
|
||||
|
||||
func (st *singleTranslation) Backfill(src Translation) Translation {
|
||||
if st.template == nil || st.template.src == "" {
|
||||
st.template = src.Template(language.Other)
|
||||
}
|
||||
return st
|
||||
}
|
||||
|
||||
func (st *singleTranslation) Merge(t Translation) Translation {
|
||||
other, ok := t.(*singleTranslation)
|
||||
if !ok || st.ID() != t.ID() {
|
||||
return t
|
||||
}
|
||||
if other.template != nil && other.template.src != "" {
|
||||
st.template = other.template
|
||||
}
|
||||
return st
|
||||
}
|
||||
|
||||
func (st *singleTranslation) Incomplete(l *language.Language) bool {
|
||||
return st.template == nil || st.template.src == ""
|
||||
}
|
||||
|
||||
var _ = Translation(&singleTranslation{})
|
61
vendor/github.com/nicksnyder/go-i18n/i18n/translation/template.go
generated
vendored
Normal file
61
vendor/github.com/nicksnyder/go-i18n/i18n/translation/template.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
package translation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"strings"
|
||||
gotemplate "text/template"
|
||||
)
|
||||
|
||||
type template struct {
|
||||
tmpl *gotemplate.Template
|
||||
src string
|
||||
}
|
||||
|
||||
func newTemplate(src string) (*template, error) {
|
||||
var tmpl template
|
||||
err := tmpl.parseTemplate(src)
|
||||
return &tmpl, err
|
||||
}
|
||||
|
||||
func mustNewTemplate(src string) *template {
|
||||
t, err := newTemplate(src)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *template) String() string {
|
||||
return t.src
|
||||
}
|
||||
|
||||
func (t *template) Execute(args interface{}) string {
|
||||
if t.tmpl == nil {
|
||||
return t.src
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := t.tmpl.Execute(&buf, args); err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (t *template) MarshalText() ([]byte, error) {
|
||||
return []byte(t.src), nil
|
||||
}
|
||||
|
||||
func (t *template) UnmarshalText(src []byte) error {
|
||||
return t.parseTemplate(string(src))
|
||||
}
|
||||
|
||||
func (t *template) parseTemplate(src string) (err error) {
|
||||
t.src = src
|
||||
if strings.Contains(src, "{{") {
|
||||
t.tmpl, err = gotemplate.New(src).Parse(src)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var _ = encoding.TextMarshaler(&template{})
|
||||
var _ = encoding.TextUnmarshaler(&template{})
|
146
vendor/github.com/nicksnyder/go-i18n/i18n/translation/template_test.go
generated
vendored
Normal file
146
vendor/github.com/nicksnyder/go-i18n/i18n/translation/template_test.go
generated
vendored
Normal file
|
@ -0,0 +1,146 @@
|
|||
package translation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
//"launchpad.net/goyaml"
|
||||
"testing"
|
||||
gotemplate "text/template"
|
||||
)
|
||||
|
||||
func TestNilTemplate(t *testing.T) {
|
||||
expected := "hello"
|
||||
tmpl := &template{
|
||||
tmpl: nil,
|
||||
src: expected,
|
||||
}
|
||||
if actual := tmpl.Execute(nil); actual != expected {
|
||||
t.Errorf("Execute(nil) returned %s; expected %s", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalText(t *testing.T) {
|
||||
tmpl := &template{
|
||||
tmpl: gotemplate.Must(gotemplate.New("id").Parse("this is a {{.foo}} template")),
|
||||
src: "boom",
|
||||
}
|
||||
expectedBuf := []byte(tmpl.src)
|
||||
if buf, err := tmpl.MarshalText(); !bytes.Equal(buf, expectedBuf) || err != nil {
|
||||
t.Errorf("MarshalText() returned %#v, %#v; expected %#v, nil", buf, err, expectedBuf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalText(t *testing.T) {
|
||||
tmpl := &template{}
|
||||
tmpl.UnmarshalText([]byte("hello {{.World}}"))
|
||||
result := tmpl.Execute(map[string]string{
|
||||
"World": "world!",
|
||||
})
|
||||
expected := "hello world!"
|
||||
if result != expected {
|
||||
t.Errorf("expected %#v; got %#v", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func TestYAMLMarshal(t *testing.T) {
|
||||
src := "hello {{.World}}"
|
||||
tmpl, err := newTemplate(src)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf, err := goyaml.Marshal(tmpl)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf, []byte(src)) {
|
||||
t.Fatalf(`expected "%s"; got "%s"`, src, buf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestYAMLUnmarshal(t *testing.T) {
|
||||
buf := []byte(`Tmpl: "hello"`)
|
||||
|
||||
var out struct {
|
||||
Tmpl *template
|
||||
}
|
||||
var foo map[string]string
|
||||
if err := goyaml.Unmarshal(buf, &foo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.Tmpl == nil {
|
||||
t.Fatalf("out.Tmpl was nil")
|
||||
}
|
||||
if out.Tmpl.tmpl == nil {
|
||||
t.Fatalf("out.Tmpl.tmpl was nil")
|
||||
}
|
||||
if expected := "hello {{.World}}"; out.Tmpl.src != expected {
|
||||
t.Fatalf("expected %s; got %s", expected, out.Tmpl.src)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetYAML(t *testing.T) {
|
||||
src := "hello"
|
||||
tmpl := &template{
|
||||
tmpl: nil,
|
||||
src: src,
|
||||
}
|
||||
if tag, value := tmpl.GetYAML(); tag != "" || value != src {
|
||||
t.Errorf("GetYAML() returned (%#v, %#v); expected (%#v, %#v)", tag, value, "", src)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetYAML(t *testing.T) {
|
||||
tmpl := &template{}
|
||||
tmpl.SetYAML("tagDoesntMatter", "hello {{.World}}")
|
||||
result := tmpl.Execute(map[string]string{
|
||||
"World": "world!",
|
||||
})
|
||||
expected := "hello world!"
|
||||
if result != expected {
|
||||
t.Errorf("expected %#v; got %#v", expected, result)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func BenchmarkExecuteNilTemplate(b *testing.B) {
|
||||
template := &template{src: "hello world"}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
template.Execute(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExecuteHelloWorldTemplate(b *testing.B) {
|
||||
template, err := newTemplate("hello world")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
template.Execute(nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Executing a simple template like this is ~6x slower than Sprintf
|
||||
// but it is still only a few microseconds which should be sufficiently fast.
|
||||
// The benefit is that we have nice semantic tags in the translation.
|
||||
func BenchmarkExecuteHelloNameTemplate(b *testing.B) {
|
||||
template, err := newTemplate("hello {{.Name}}")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
template.Execute(map[string]string{
|
||||
"Name": "Nick",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSprintf(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
fmt.Sprintf("hello %s", "nick")
|
||||
}
|
||||
}
|
83
vendor/github.com/nicksnyder/go-i18n/i18n/translation/translation.go
generated
vendored
Normal file
83
vendor/github.com/nicksnyder/go-i18n/i18n/translation/translation.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
// Package translation defines the interface for a translation.
|
||||
package translation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
)
|
||||
|
||||
// Translation is the interface that represents a translated string.
|
||||
type Translation interface {
|
||||
// MarshalInterface returns the object that should be used
|
||||
// to serialize the translation.
|
||||
MarshalInterface() interface{}
|
||||
ID() string
|
||||
Template(language.Plural) *template
|
||||
UntranslatedCopy() Translation
|
||||
Normalize(language *language.Language) Translation
|
||||
Backfill(src Translation) Translation
|
||||
Merge(Translation) Translation
|
||||
Incomplete(l *language.Language) bool
|
||||
}
|
||||
|
||||
// SortableByID implements sort.Interface for a slice of translations.
|
||||
type SortableByID []Translation
|
||||
|
||||
func (a SortableByID) Len() int { return len(a) }
|
||||
func (a SortableByID) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a SortableByID) Less(i, j int) bool { return a[i].ID() < a[j].ID() }
|
||||
|
||||
// NewTranslation reflects on data to create a new Translation.
|
||||
//
|
||||
// data["id"] must be a string and data["translation"] must be either a string
|
||||
// for a non-plural translation or a map[string]interface{} for a plural translation.
|
||||
func NewTranslation(data map[string]interface{}) (Translation, error) {
|
||||
id, ok := data["id"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`missing "id" key`)
|
||||
}
|
||||
var pluralObject map[string]interface{}
|
||||
switch translation := data["translation"].(type) {
|
||||
case string:
|
||||
tmpl, err := newTemplate(translation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &singleTranslation{id, tmpl}, nil
|
||||
case map[interface{}]interface{}:
|
||||
// The YAML parser uses interface{} keys so we first convert them to string keys.
|
||||
pluralObject = make(map[string]interface{})
|
||||
for k, v := range translation {
|
||||
kStr, ok := k.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`invalid plural category type %T; expected string`, k)
|
||||
}
|
||||
pluralObject[kStr] = v
|
||||
}
|
||||
case map[string]interface{}:
|
||||
pluralObject = translation
|
||||
case nil:
|
||||
return nil, fmt.Errorf(`missing "translation" key`)
|
||||
default:
|
||||
return nil, fmt.Errorf(`unsupported type for "translation" key %T`, translation)
|
||||
}
|
||||
|
||||
templates := make(map[language.Plural]*template, len(pluralObject))
|
||||
for k, v := range pluralObject {
|
||||
pc, err := language.NewPlural(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`plural category "%s" has value of type %T; expected string`, pc, v)
|
||||
}
|
||||
tmpl, err := newTemplate(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
templates[pc] = tmpl
|
||||
}
|
||||
return &pluralTranslation{id, templates}, nil
|
||||
}
|
17
vendor/github.com/nicksnyder/go-i18n/i18n/translation/translation_test.go
generated
vendored
Normal file
17
vendor/github.com/nicksnyder/go-i18n/i18n/translation/translation_test.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
package translation
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Check this here to avoid unnecessary import of sort package.
|
||||
var _ = sort.Interface(make(SortableByID, 0, 0))
|
||||
|
||||
func TestNewSingleTranslation(t *testing.T) {
|
||||
t.Skipf("not implemented")
|
||||
}
|
||||
|
||||
func TestNewPluralTranslation(t *testing.T) {
|
||||
t.Skipf("not implemented")
|
||||
}
|
4
vendor/github.com/stretchr/testify/.travis.yml
generated
vendored
4
vendor/github.com/stretchr/testify/.travis.yml
generated
vendored
|
@ -1,15 +1,13 @@
|
|||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.1
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- tip
|
||||
|
||||
script:
|
||||
- go test -v ./...
|
||||
|
||||
|
|
2
vendor/github.com/stretchr/testify/Godeps/Godeps.json
generated
vendored
2
vendor/github.com/stretchr/testify/Godeps/Godeps.json
generated
vendored
|
@ -7,7 +7,7 @@
|
|||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||
"Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d"
|
||||
"Rev": "2df174808ee097f90d259e432cc04442cf60be21"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pmezard/go-difflib/difflib",
|
||||
|
|
2
vendor/github.com/stretchr/testify/README.md
generated
vendored
2
vendor/github.com/stretchr/testify/README.md
generated
vendored
|
@ -1,7 +1,7 @@
|
|||
Testify - Thou Shalt Write Tests
|
||||
================================
|
||||
|
||||
[![Build Status](https://travis-ci.org/stretchr/testify.svg)](https://travis-ci.org/stretchr/testify) [![Go Report Card](https://goreportcard.com/badge/github.com/stretchr/testify)](https://goreportcard.com/report/github.com/stretchr/testify) [![GoDoc](https://godoc.org/github.com/stretchr/testify?status.svg)](https://godoc.org/github.com/stretchr/testify)
|
||||
[![Build Status](https://travis-ci.org/stretchr/testify.svg)](https://travis-ci.org/stretchr/testify)
|
||||
|
||||
Go code (golang) set of packages that provide many tools for testifying that your code will behave as you intend.
|
||||
|
||||
|
|
11
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
11
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
|
@ -832,11 +832,11 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
|||
//
|
||||
// Returns whether the assertion was successful (true) or not (false).
|
||||
func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
if err != nil {
|
||||
return Fail(t, fmt.Sprintf("Received unexpected error %q", err), msgAndArgs...)
|
||||
if isNil(err) {
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
return Fail(t, fmt.Sprintf("Received unexpected error %q", err), msgAndArgs...)
|
||||
}
|
||||
|
||||
// Error asserts that a function returned an error (i.e. not `nil`).
|
||||
|
@ -850,11 +850,8 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
|||
func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||
|
||||
message := messageFromMsgAndArgs(msgAndArgs...)
|
||||
if err == nil {
|
||||
return Fail(t, "An error is expected but got nil. %s", message)
|
||||
}
|
||||
return NotNil(t, err, "An error is expected but got nil. %s", message)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// EqualError asserts that a function returned an error (i.e. not `nil`)
|
||||
|
|
32
vendor/github.com/stretchr/testify/assert/assertions_test.go
generated
vendored
32
vendor/github.com/stretchr/testify/assert/assertions_test.go
generated
vendored
|
@ -523,26 +523,8 @@ func TestNoError(t *testing.T) {
|
|||
|
||||
False(t, NoError(mockT, err), "NoError with error should return False")
|
||||
|
||||
// returning an empty error interface
|
||||
err = func() error {
|
||||
var err *customError
|
||||
if err != nil {
|
||||
t.Fatal("err should be nil here")
|
||||
}
|
||||
return err
|
||||
}()
|
||||
|
||||
if err == nil { // err is not nil here!
|
||||
t.Errorf("Error should be nil due to empty interface", err)
|
||||
}
|
||||
|
||||
False(t, NoError(mockT, err), "NoError should fail with empty error interface")
|
||||
}
|
||||
|
||||
type customError struct{}
|
||||
|
||||
func (*customError) Error() string { return "fail" }
|
||||
|
||||
func TestError(t *testing.T) {
|
||||
|
||||
mockT := new(testing.T)
|
||||
|
@ -557,20 +539,6 @@ func TestError(t *testing.T) {
|
|||
|
||||
True(t, Error(mockT, err), "Error with error should return True")
|
||||
|
||||
// returning an empty error interface
|
||||
err = func() error {
|
||||
var err *customError
|
||||
if err != nil {
|
||||
t.Fatal("err should be nil here")
|
||||
}
|
||||
return err
|
||||
}()
|
||||
|
||||
if err == nil { // err is not nil here!
|
||||
t.Errorf("Error should be nil due to empty interface", err)
|
||||
}
|
||||
|
||||
True(t, Error(mockT, err), "Error should pass with empty error interface")
|
||||
}
|
||||
|
||||
func TestEqualError(t *testing.T) {
|
||||
|
|
18
vendor/github.com/stretchr/testify/mock/mock.go
generated
vendored
18
vendor/github.com/stretchr/testify/mock/mock.go
generated
vendored
|
@ -43,9 +43,6 @@ type Call struct {
|
|||
// expectations. 0 means to always return the value.
|
||||
Repeatability int
|
||||
|
||||
// Amount of times this call has been called
|
||||
totalCalls int
|
||||
|
||||
// Holds a channel that will be used to block the Return until it either
|
||||
// recieves a message or is closed. nil means it returns immediately.
|
||||
WaitFor <-chan time.Time
|
||||
|
@ -135,7 +132,7 @@ func (c *Call) After(d time.Duration) *Call {
|
|||
// mocking a method such as unmarshalers that takes a pointer to a struct and
|
||||
// sets properties in such struct
|
||||
//
|
||||
// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(func(args Arguments) {
|
||||
// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(function(args Arguments) {
|
||||
// arg := args.Get(0).(*map[string]interface{})
|
||||
// arg["foo"] = "bar"
|
||||
// })
|
||||
|
@ -265,7 +262,7 @@ func callString(method string, arguments Arguments, includeArgumentValues bool)
|
|||
}
|
||||
|
||||
// Called tells the mock object that a method has been called, and gets an array
|
||||
// of arguments to return. Panics if the call is unexpected (i.e. not preceded by
|
||||
// of arguments to return. Panics if the call is unexpected (i.e. not preceeded by
|
||||
// appropriate .On .Return() calls)
|
||||
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
|
||||
func (m *Mock) Called(arguments ...interface{}) Arguments {
|
||||
|
@ -308,14 +305,9 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
|||
switch {
|
||||
case call.Repeatability == 1:
|
||||
call.Repeatability = -1
|
||||
call.totalCalls++
|
||||
|
||||
case call.Repeatability > 1:
|
||||
call.Repeatability--
|
||||
call.totalCalls++
|
||||
|
||||
case call.Repeatability == 0:
|
||||
call.totalCalls++
|
||||
}
|
||||
m.mutex.Unlock()
|
||||
}
|
||||
|
@ -363,7 +355,7 @@ func (m *Mock) AssertExpectations(t TestingT) bool {
|
|||
// iterate through each expectation
|
||||
expectedCalls := m.expectedCalls()
|
||||
for _, expectedCall := range expectedCalls {
|
||||
if !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
|
||||
if !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) {
|
||||
somethingMissing = true
|
||||
failedExpectations++
|
||||
t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||
|
@ -398,7 +390,6 @@ func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls
|
|||
}
|
||||
|
||||
// AssertCalled asserts that the method was called.
|
||||
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
|
||||
func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
|
||||
if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) {
|
||||
t.Logf("%v", m.expectedCalls())
|
||||
|
@ -408,7 +399,6 @@ func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interfac
|
|||
}
|
||||
|
||||
// AssertNotCalled asserts that the method was not called.
|
||||
// It can produce a false result when an argument is a pointer type and the underlying value changed after calling the mocked method.
|
||||
func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
|
||||
if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) {
|
||||
t.Logf("%v", m.expectedCalls())
|
||||
|
@ -499,7 +489,7 @@ func (f argumentMatcher) String() string {
|
|||
// and false otherwise.
|
||||
//
|
||||
// Example:
|
||||
// m.On("Do", MatchedBy(func(req *http.Request) bool { return req.Host == "example.com" }))
|
||||
// m.On("Do", func(req *http.Request) bool { return req.Host == "example.com" })
|
||||
//
|
||||
// |fn|, must be a function accepting a single argument (of the expected type)
|
||||
// which returns a bool. If |fn| doesn't match the required signature,
|
||||
|
|
62
vendor/github.com/stretchr/testify/mock/mock_test.go
generated
vendored
62
vendor/github.com/stretchr/testify/mock/mock_test.go
generated
vendored
|
@ -765,68 +765,6 @@ func Test_Mock_AssertExpectations(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func Test_Mock_AssertExpectations_Placeholder_NoArgs(t *testing.T) {
|
||||
|
||||
var mockedService = new(TestExampleImplementation)
|
||||
|
||||
mockedService.On("Test_Mock_AssertExpectations_Placeholder_NoArgs").Return(5, 6, 7).Once()
|
||||
mockedService.On("Test_Mock_AssertExpectations_Placeholder_NoArgs").Return(7, 6, 5)
|
||||
|
||||
tt := new(testing.T)
|
||||
assert.False(t, mockedService.AssertExpectations(tt))
|
||||
|
||||
// make the call now
|
||||
mockedService.Called()
|
||||
|
||||
// now assert expectations
|
||||
assert.True(t, mockedService.AssertExpectations(tt))
|
||||
|
||||
}
|
||||
|
||||
func Test_Mock_AssertExpectations_Placeholder(t *testing.T) {
|
||||
|
||||
var mockedService = new(TestExampleImplementation)
|
||||
|
||||
mockedService.On("Test_Mock_AssertExpectations_Placeholder", 1, 2, 3).Return(5, 6, 7).Once()
|
||||
mockedService.On("Test_Mock_AssertExpectations_Placeholder", 3, 2, 1).Return(7, 6, 5)
|
||||
|
||||
tt := new(testing.T)
|
||||
assert.False(t, mockedService.AssertExpectations(tt))
|
||||
|
||||
// make the call now
|
||||
mockedService.Called(1, 2, 3)
|
||||
|
||||
// now assert expectations
|
||||
assert.False(t, mockedService.AssertExpectations(tt))
|
||||
|
||||
// make call to the second expectation
|
||||
mockedService.Called(3, 2, 1)
|
||||
|
||||
// now assert expectations again
|
||||
assert.True(t, mockedService.AssertExpectations(tt))
|
||||
}
|
||||
|
||||
func Test_Mock_AssertExpectations_With_Pointers(t *testing.T) {
|
||||
|
||||
var mockedService = new(TestExampleImplementation)
|
||||
|
||||
mockedService.On("Test_Mock_AssertExpectations_With_Pointers", &struct{ Foo int }{1}).Return(1)
|
||||
mockedService.On("Test_Mock_AssertExpectations_With_Pointers", &struct{ Foo int }{2}).Return(2)
|
||||
|
||||
tt := new(testing.T)
|
||||
assert.False(t, mockedService.AssertExpectations(tt))
|
||||
|
||||
s := struct{ Foo int }{1}
|
||||
// make the calls now
|
||||
mockedService.Called(&s)
|
||||
s.Foo = 2
|
||||
mockedService.Called(&s)
|
||||
|
||||
// now assert expectations
|
||||
assert.True(t, mockedService.AssertExpectations(tt))
|
||||
|
||||
}
|
||||
|
||||
func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
|
||||
|
||||
var mockedService = new(TestExampleImplementation)
|
||||
|
|
15
vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
15
vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
|
@ -91,21 +91,6 @@ func init() {
|
|||
flagKindShift = 0
|
||||
flagRO = 1 << 5
|
||||
flagIndir = 1 << 6
|
||||
|
||||
// Commit adf9b30e5594 modified the flags to separate the
|
||||
// flagRO flag into two bits which specifies whether or not the
|
||||
// field is embedded. This causes flagIndir to move over a bit
|
||||
// and means that flagRO is the combination of either of the
|
||||
// original flagRO bit and the new bit.
|
||||
//
|
||||
// This code detects the change by extracting what used to be
|
||||
// the indirect bit to ensure it's set. When it's not, the flag
|
||||
// order has been changed to the newer format, so the flags are
|
||||
// updated accordingly.
|
||||
if upfv&flagIndir == 0 {
|
||||
flagRO = 3 << 5
|
||||
flagIndir = 1 << 7
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
2
vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
|
@ -181,6 +181,8 @@ func (d *dumpState) dumpSlice(v reflect.Value) {
|
|||
// Try to use existing uint8 slices and fall back to converting
|
||||
// and copying if that fails.
|
||||
case vt.Kind() == reflect.Uint8:
|
||||
// TODO(davec): Fix up the disableUnsafe bits...
|
||||
|
||||
// We need an addressable interface to convert the type
|
||||
// to a byte slice. However, the reflect package won't
|
||||
// give us an interface on certain things like
|
||||
|
|
2
vendor/github.com/urfave/cli/.gitignore
generated
vendored
2
vendor/github.com/urfave/cli/.gitignore
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
*.coverprofile
|
||||
node_modules/
|
31
vendor/github.com/urfave/cli/.travis.yml
generated
vendored
31
vendor/github.com/urfave/cli/.travis.yml
generated
vendored
|
@ -1,40 +1,23 @@
|
|||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
go:
|
||||
- 1.1.2
|
||||
- 1.2.2
|
||||
- 1.3.3
|
||||
- 1.4
|
||||
- 1.5.4
|
||||
- 1.6.2
|
||||
- master
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: master
|
||||
include:
|
||||
- go: 1.6.2
|
||||
os: osx
|
||||
- go: 1.1.2
|
||||
install: go get -v .
|
||||
before_script: echo skipping gfmxr on $TRAVIS_GO_VERSION
|
||||
script:
|
||||
- ./runtests vet
|
||||
- ./runtests test
|
||||
- go: tip
|
||||
|
||||
before_script:
|
||||
- go get github.com/urfave/gfmxr/...
|
||||
- if [ ! -f node_modules/.bin/markdown-toc ] ; then
|
||||
npm install markdown-toc ;
|
||||
fi
|
||||
- go get github.com/meatballhat/gfmxr/...
|
||||
|
||||
script:
|
||||
- ./runtests vet
|
||||
- ./runtests test
|
||||
- ./runtests gfmxr
|
||||
- ./runtests toc
|
||||
- go vet ./...
|
||||
- go test -v ./...
|
||||
- gfmxr -c $(grep -c 'package main' README.md) -s README.md
|
||||
|
|
65
vendor/github.com/urfave/cli/CHANGELOG.md
generated
vendored
65
vendor/github.com/urfave/cli/CHANGELOG.md
generated
vendored
|
@ -3,19 +3,6 @@
|
|||
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- `./runtests` test runner with coverage tracking by default
|
||||
- testing on OS X
|
||||
- testing on Windows
|
||||
- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code
|
||||
|
||||
### Changed
|
||||
- Use spaces for alignment in help/usage output instead of tabs, making the
|
||||
output alignment consistent regardless of tab width
|
||||
|
||||
### Fixed
|
||||
- Printing of command aliases in help text
|
||||
- Printing of visible flags for both struct and struct pointer flags
|
||||
|
||||
## [1.17.0] - 2016-05-09
|
||||
### Added
|
||||
|
@ -36,7 +23,7 @@
|
|||
makes it easier to script around apps built using `cli` since they can trust
|
||||
that a 0 exit code indicated a successful execution.
|
||||
- cleanups based on [Go Report Card
|
||||
feedback](https://goreportcard.com/report/github.com/urfave/cli)
|
||||
feedback](https://goreportcard.com/report/github.com/codegangsta/cli)
|
||||
|
||||
## [1.16.0] - 2016-05-02
|
||||
### Added
|
||||
|
@ -296,28 +283,28 @@ signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
|
|||
### Added
|
||||
- Initial implementation.
|
||||
|
||||
[Unreleased]: https://github.com/urfave/cli/compare/v1.17.0...HEAD
|
||||
[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0
|
||||
[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
|
||||
[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0
|
||||
[1.14.0]: https://github.com/urfave/cli/compare/v1.13.0...v1.14.0
|
||||
[1.13.0]: https://github.com/urfave/cli/compare/v1.12.0...v1.13.0
|
||||
[1.12.0]: https://github.com/urfave/cli/compare/v1.11.1...v1.12.0
|
||||
[1.11.1]: https://github.com/urfave/cli/compare/v1.11.0...v1.11.1
|
||||
[1.11.0]: https://github.com/urfave/cli/compare/v1.10.2...v1.11.0
|
||||
[1.10.2]: https://github.com/urfave/cli/compare/v1.10.1...v1.10.2
|
||||
[1.10.1]: https://github.com/urfave/cli/compare/v1.10.0...v1.10.1
|
||||
[1.10.0]: https://github.com/urfave/cli/compare/v1.9.0...v1.10.0
|
||||
[1.9.0]: https://github.com/urfave/cli/compare/v1.8.0...v1.9.0
|
||||
[1.8.0]: https://github.com/urfave/cli/compare/v1.7.1...v1.8.0
|
||||
[1.7.1]: https://github.com/urfave/cli/compare/v1.7.0...v1.7.1
|
||||
[1.7.0]: https://github.com/urfave/cli/compare/v1.6.0...v1.7.0
|
||||
[1.6.0]: https://github.com/urfave/cli/compare/v1.5.0...v1.6.0
|
||||
[1.5.0]: https://github.com/urfave/cli/compare/v1.4.1...v1.5.0
|
||||
[1.4.1]: https://github.com/urfave/cli/compare/v1.4.0...v1.4.1
|
||||
[1.4.0]: https://github.com/urfave/cli/compare/v1.3.1...v1.4.0
|
||||
[1.3.1]: https://github.com/urfave/cli/compare/v1.3.0...v1.3.1
|
||||
[1.3.0]: https://github.com/urfave/cli/compare/v1.2.0...v1.3.0
|
||||
[1.2.0]: https://github.com/urfave/cli/compare/v1.1.0...v1.2.0
|
||||
[1.1.0]: https://github.com/urfave/cli/compare/v1.0.0...v1.1.0
|
||||
[1.0.0]: https://github.com/urfave/cli/compare/v0.1.0...v1.0.0
|
||||
[Unreleased]: https://github.com/codegangsta/cli/compare/v1.17.0...HEAD
|
||||
[1.17.0]: https://github.com/codegangsta/cli/compare/v1.16.0...v1.17.0
|
||||
[1.16.0]: https://github.com/codegangsta/cli/compare/v1.15.0...v1.16.0
|
||||
[1.15.0]: https://github.com/codegangsta/cli/compare/v1.14.0...v1.15.0
|
||||
[1.14.0]: https://github.com/codegangsta/cli/compare/v1.13.0...v1.14.0
|
||||
[1.13.0]: https://github.com/codegangsta/cli/compare/v1.12.0...v1.13.0
|
||||
[1.12.0]: https://github.com/codegangsta/cli/compare/v1.11.1...v1.12.0
|
||||
[1.11.1]: https://github.com/codegangsta/cli/compare/v1.11.0...v1.11.1
|
||||
[1.11.0]: https://github.com/codegangsta/cli/compare/v1.10.2...v1.11.0
|
||||
[1.10.2]: https://github.com/codegangsta/cli/compare/v1.10.1...v1.10.2
|
||||
[1.10.1]: https://github.com/codegangsta/cli/compare/v1.10.0...v1.10.1
|
||||
[1.10.0]: https://github.com/codegangsta/cli/compare/v1.9.0...v1.10.0
|
||||
[1.9.0]: https://github.com/codegangsta/cli/compare/v1.8.0...v1.9.0
|
||||
[1.8.0]: https://github.com/codegangsta/cli/compare/v1.7.1...v1.8.0
|
||||
[1.7.1]: https://github.com/codegangsta/cli/compare/v1.7.0...v1.7.1
|
||||
[1.7.0]: https://github.com/codegangsta/cli/compare/v1.6.0...v1.7.0
|
||||
[1.6.0]: https://github.com/codegangsta/cli/compare/v1.5.0...v1.6.0
|
||||
[1.5.0]: https://github.com/codegangsta/cli/compare/v1.4.1...v1.5.0
|
||||
[1.4.1]: https://github.com/codegangsta/cli/compare/v1.4.0...v1.4.1
|
||||
[1.4.0]: https://github.com/codegangsta/cli/compare/v1.3.1...v1.4.0
|
||||
[1.3.1]: https://github.com/codegangsta/cli/compare/v1.3.0...v1.3.1
|
||||
[1.3.0]: https://github.com/codegangsta/cli/compare/v1.2.0...v1.3.0
|
||||
[1.2.0]: https://github.com/codegangsta/cli/compare/v1.1.0...v1.2.0
|
||||
[1.1.0]: https://github.com/codegangsta/cli/compare/v1.0.0...v1.1.0
|
||||
[1.0.0]: https://github.com/codegangsta/cli/compare/v0.1.0...v1.0.0
|
||||
|
|
1122
vendor/github.com/urfave/cli/README.md
generated
vendored
1122
vendor/github.com/urfave/cli/README.md
generated
vendored
File diff suppressed because it is too large
Load diff
2
vendor/github.com/urfave/cli/altsrc/flag.go
generated
vendored
2
vendor/github.com/urfave/cli/altsrc/flag.go
generated
vendored
|
@ -7,7 +7,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
// FlagInputSourceExtension is an extension interface of cli.Flag that
|
||||
|
|
2
vendor/github.com/urfave/cli/altsrc/flag_test.go
generated
vendored
2
vendor/github.com/urfave/cli/altsrc/flag_test.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
type testApplyInputSource struct {
|
||||
|
|
2
vendor/github.com/urfave/cli/altsrc/input_source_context.go
generated
vendored
2
vendor/github.com/urfave/cli/altsrc/input_source_context.go
generated
vendored
|
@ -3,7 +3,7 @@ package altsrc
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
// InputSourceContext is an interface used to allow
|
||||
|
|
2
vendor/github.com/urfave/cli/altsrc/map_input_source.go
generated
vendored
2
vendor/github.com/urfave/cli/altsrc/map_input_source.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
// MapInputSource implements InputSourceContext to return
|
||||
|
|
2
vendor/github.com/urfave/cli/altsrc/yaml_command_test.go
generated
vendored
2
vendor/github.com/urfave/cli/altsrc/yaml_command_test.go
generated
vendored
|
@ -11,7 +11,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func TestCommandYamlFileTest(t *testing.T) {
|
||||
|
|
2
vendor/github.com/urfave/cli/altsrc/yaml_file_loader.go
generated
vendored
2
vendor/github.com/urfave/cli/altsrc/yaml_file_loader.go
generated
vendored
|
@ -12,7 +12,7 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
"github.com/codegangsta/cli"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
|
15
vendor/github.com/urfave/cli/app.go
generated
vendored
15
vendor/github.com/urfave/cli/app.go
generated
vendored
|
@ -8,12 +8,11 @@ import (
|
|||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md"
|
||||
changeLogURL = "https://github.com/codegangsta/cli/blob/master/CHANGELOG.md"
|
||||
appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
|
||||
runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL)
|
||||
|
||||
|
@ -465,13 +464,11 @@ func (a Author) String() string {
|
|||
func HandleAction(action interface{}, context *Context) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// Try to detect a known reflection error from *this scope*, rather than
|
||||
// swallowing all panics that may happen when calling an Action func.
|
||||
s := fmt.Sprintf("%v", r)
|
||||
if strings.HasPrefix(s, "reflect: ") && strings.Contains(s, "too many input arguments") {
|
||||
err = NewExitError(fmt.Sprintf("ERROR unknown Action error: %v. See %s", r, appActionDeprecationURL), 2)
|
||||
} else {
|
||||
panic(r)
|
||||
switch r.(type) {
|
||||
case error:
|
||||
err = r.(error)
|
||||
default:
|
||||
err = NewExitError(fmt.Sprintf("ERROR unknown Action error: %v. See %s", r, appActionDeprecationURL), 2)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
13
vendor/github.com/urfave/cli/app_test.go
generated
vendored
13
vendor/github.com/urfave/cli/app_test.go
generated
vendored
|
@ -1452,16 +1452,3 @@ func TestHandleAction_WithInvalidFuncReturnSignature(t *testing.T) {
|
|||
t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode())
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleAction_WithUnknownPanic(t *testing.T) {
|
||||
defer func() { refute(t, recover(), nil) }()
|
||||
|
||||
var fn ActionFunc
|
||||
|
||||
app := NewApp()
|
||||
app.Action = func(ctx *Context) error {
|
||||
fn(ctx)
|
||||
return nil
|
||||
}
|
||||
HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil))
|
||||
}
|
||||
|
|
27
vendor/github.com/urfave/cli/appveyor.yml
generated
vendored
27
vendor/github.com/urfave/cli/appveyor.yml
generated
vendored
|
@ -2,24 +2,15 @@ version: "{build}"
|
|||
|
||||
os: Windows Server 2012 R2
|
||||
|
||||
clone_folder: c:\gopath\src\github.com\urfave\cli
|
||||
|
||||
environment:
|
||||
GOPATH: C:\gopath
|
||||
GOVERSION: 1.6
|
||||
PYTHON: C:\Python27-x64
|
||||
PYTHON_VERSION: 2.7.x
|
||||
PYTHON_ARCH: 64
|
||||
GFMXR_DEBUG: 1
|
||||
|
||||
install:
|
||||
- set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
|
||||
- go version
|
||||
- go env
|
||||
- go get github.com/urfave/gfmxr/...
|
||||
- go get -v -t ./...
|
||||
- go version
|
||||
- go env
|
||||
|
||||
build_script:
|
||||
- python runtests vet
|
||||
- python runtests test
|
||||
- python runtests gfmxr
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- go vet ./...
|
||||
- go test -v ./...
|
||||
|
||||
test: off
|
||||
|
||||
deploy: off
|
||||
|
|
105
vendor/github.com/urfave/cli/context.go
generated
vendored
105
vendor/github.com/urfave/cli/context.go
generated
vendored
|
@ -31,21 +31,6 @@ func (c *Context) Int(name string) int {
|
|||
return lookupInt(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Int64 looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
func (c *Context) Int64(name string) int64 {
|
||||
return lookupInt64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Uint looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
func (c *Context) Uint(name string) uint {
|
||||
return lookupUint(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Uint64 looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
func (c *Context) Uint64(name string) uint64 {
|
||||
return lookupUint64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Duration looks up the value of a local time.Duration flag, returns 0 if no
|
||||
// time.Duration flag exists
|
||||
func (c *Context) Duration(name string) time.Duration {
|
||||
|
@ -85,12 +70,6 @@ func (c *Context) IntSlice(name string) []int {
|
|||
return lookupIntSlice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Int64Slice looks up the value of a local int slice flag, returns nil if no int
|
||||
// slice flag exists
|
||||
func (c *Context) Int64Slice(name string) []int64 {
|
||||
return lookupInt64Slice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Generic looks up the value of a local generic flag, returns nil if no generic
|
||||
// flag exists
|
||||
func (c *Context) Generic(name string) interface{} {
|
||||
|
@ -105,30 +84,6 @@ func (c *Context) GlobalInt(name string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
// GlobalInt64 looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
func (c *Context) GlobalInt64(name string) int64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt64(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GlobalUint looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
func (c *Context) GlobalUint(name string) uint {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupUint(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GlobalUint64 looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
func (c *Context) GlobalUint64(name string) uint64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupUint64(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GlobalFloat64 looks up the value of a global float64 flag, returns float64(0)
|
||||
// if no float64 flag exists
|
||||
func (c *Context) GlobalFloat64(name string) float64 {
|
||||
|
@ -192,15 +147,6 @@ func (c *Context) GlobalIntSlice(name string) []int {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GlobalInt64Slice looks up the value of a global int slice flag, returns nil if
|
||||
// no int slice flag exists
|
||||
func (c *Context) GlobalInt64Slice(name string) []int64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt64Slice(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GlobalGeneric looks up the value of a global generic flag, returns nil if no
|
||||
// generic flag exists
|
||||
func (c *Context) GlobalGeneric(name string) interface{} {
|
||||
|
@ -360,46 +306,7 @@ func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
|
|||
func lookupInt(name string, set *flag.FlagSet) int {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return int(val)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupInt64(name string, set *flag.FlagSet) int64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupUint(name string, set *flag.FlagSet) uint {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return uint(val)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupUint64(name string, set *flag.FlagSet) uint64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
||||
val, err := strconv.Atoi(f.Value.String())
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
@ -463,16 +370,6 @@ func lookupIntSlice(name string, set *flag.FlagSet) []int {
|
|||
return nil
|
||||
}
|
||||
|
||||
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
return (f.Value.(*Int64Slice)).Value()
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
|
|
41
vendor/github.com/urfave/cli/context_test.go
generated
vendored
41
vendor/github.com/urfave/cli/context_test.go
generated
vendored
|
@ -9,29 +9,17 @@ import (
|
|||
func TestNewContext(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Int("myflag", 12, "doc")
|
||||
set.Int64("myflagInt64", int64(12), "doc")
|
||||
set.Uint("myflagUint", uint(93), "doc")
|
||||
set.Uint64("myflagUint64", uint64(93), "doc")
|
||||
set.Float64("myflag64", float64(17), "doc")
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.Int("myflag", 42, "doc")
|
||||
globalSet.Int64("myflagInt64", int64(42), "doc")
|
||||
globalSet.Uint("myflagUint", uint(33), "doc")
|
||||
globalSet.Uint64("myflagUint64", uint64(33), "doc")
|
||||
globalSet.Float64("myflag64", float64(47), "doc")
|
||||
globalCtx := NewContext(nil, globalSet, nil)
|
||||
command := Command{Name: "mycommand"}
|
||||
c := NewContext(nil, set, globalCtx)
|
||||
c.Command = command
|
||||
expect(t, c.Int("myflag"), 12)
|
||||
expect(t, c.Int64("myflagInt64"), int64(12))
|
||||
expect(t, c.Uint("myflagUint"), uint(93))
|
||||
expect(t, c.Uint64("myflagUint64"), uint64(93))
|
||||
expect(t, c.Float64("myflag64"), float64(17))
|
||||
expect(t, c.GlobalInt("myflag"), 42)
|
||||
expect(t, c.GlobalInt64("myflagInt64"), int64(42))
|
||||
expect(t, c.GlobalUint("myflagUint"), uint(33))
|
||||
expect(t, c.GlobalUint64("myflagUint64"), uint64(33))
|
||||
expect(t, c.GlobalFloat64("myflag64"), float64(47))
|
||||
expect(t, c.Command.Name, "mycommand")
|
||||
}
|
||||
|
@ -43,27 +31,6 @@ func TestContext_Int(t *testing.T) {
|
|||
expect(t, c.Int("myflag"), 12)
|
||||
}
|
||||
|
||||
func TestContext_Int64(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Int64("myflagInt64", 12, "doc")
|
||||
c := NewContext(nil, set, nil)
|
||||
expect(t, c.Int64("myflagInt64"), int64(12))
|
||||
}
|
||||
|
||||
func TestContext_Uint(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Uint("myflagUint", uint(13), "doc")
|
||||
c := NewContext(nil, set, nil)
|
||||
expect(t, c.Uint("myflagUint"), uint(13))
|
||||
}
|
||||
|
||||
func TestContext_Uint64(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Uint64("myflagUint64", uint64(9), "doc")
|
||||
c := NewContext(nil, set, nil)
|
||||
expect(t, c.Uint64("myflagUint64"), uint64(9))
|
||||
}
|
||||
|
||||
func TestContext_GlobalInt(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Int("myflag", 12, "doc")
|
||||
|
@ -72,14 +39,6 @@ func TestContext_GlobalInt(t *testing.T) {
|
|||
expect(t, c.GlobalInt("nope"), 0)
|
||||
}
|
||||
|
||||
func TestContext_GlobalInt64(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Int64("myflagInt64", 12, "doc")
|
||||
c := NewContext(nil, set, nil)
|
||||
expect(t, c.GlobalInt64("myflagInt64"), int64(12))
|
||||
expect(t, c.GlobalInt64("nope"), int64(0))
|
||||
}
|
||||
|
||||
func TestContext_Float64(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Float64("myflag", float64(17), "doc")
|
||||
|
|
233
vendor/github.com/urfave/cli/flag.go
generated
vendored
233
vendor/github.com/urfave/cli/flag.go
generated
vendored
|
@ -189,7 +189,7 @@ func (f *IntSlice) Set(value string) error {
|
|||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *IntSlice) String() string {
|
||||
return fmt.Sprintf("%#v", *f)
|
||||
return fmt.Sprintf("%d", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of ints set by this flag
|
||||
|
@ -245,77 +245,6 @@ func (f IntSliceFlag) GetName() string {
|
|||
return f.Name
|
||||
}
|
||||
|
||||
// Int64Slice is an opaque type for []int to satisfy flag.Value
|
||||
type Int64Slice []int64
|
||||
|
||||
// Set parses the value into an integer and appends it to the list of values
|
||||
func (f *Int64Slice) Set(value string) error {
|
||||
tmp, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*f = append(*f, tmp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *Int64Slice) String() string {
|
||||
return fmt.Sprintf("%#v", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of ints set by this flag
|
||||
func (f *Int64Slice) Value() []int64 {
|
||||
return *f
|
||||
}
|
||||
|
||||
// Int64SliceFlag is an int flag that can be specified multiple times on the
|
||||
// command-line
|
||||
type Int64SliceFlag struct {
|
||||
Name string
|
||||
Value *Int64Slice
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f Int64SliceFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
newVal := &Int64Slice{}
|
||||
for _, s := range strings.Split(envVal, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
err := newVal.Set(s)
|
||||
if err != nil {
|
||||
fmt.Fprintf(ErrWriter, err.Error())
|
||||
}
|
||||
}
|
||||
f.Value = newVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Value == nil {
|
||||
f.Value = &Int64Slice{}
|
||||
}
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Int64SliceFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// BoolFlag is a switch that defaults to false
|
||||
type BoolFlag struct {
|
||||
Name string
|
||||
|
@ -447,6 +376,7 @@ func (f StringFlag) GetName() string {
|
|||
}
|
||||
|
||||
// IntFlag is a flag that takes an integer
|
||||
// Errors if the value provided cannot be parsed
|
||||
type IntFlag struct {
|
||||
Name string
|
||||
Value int
|
||||
|
@ -490,138 +420,6 @@ func (f IntFlag) GetName() string {
|
|||
return f.Name
|
||||
}
|
||||
|
||||
// Int64Flag is a flag that takes a 64-bit integer
|
||||
type Int64Flag struct {
|
||||
Name string
|
||||
Value int64
|
||||
Usage string
|
||||
EnvVar string
|
||||
Destination *int64
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f Int64Flag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f Int64Flag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||
if err == nil {
|
||||
f.Value = envValInt
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.Int64Var(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Int64(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Int64Flag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// UintFlag is a flag that takes an unsigned integer
|
||||
type UintFlag struct {
|
||||
Name string
|
||||
Value uint
|
||||
Usage string
|
||||
EnvVar string
|
||||
Destination *uint
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f UintFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f UintFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||
if err == nil {
|
||||
f.Value = uint(envValInt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.UintVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Uint(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f UintFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Uint64Flag is a flag that takes an unsigned 64-bit integer
|
||||
type Uint64Flag struct {
|
||||
Name string
|
||||
Value uint64
|
||||
Usage string
|
||||
EnvVar string
|
||||
Destination *uint64
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f Uint64Flag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f Uint64Flag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||
if err == nil {
|
||||
f.Value = uint64(envValInt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Uint64(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Uint64Flag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// DurationFlag is a flag that takes a duration specified in Go's duration
|
||||
// format: https://golang.org/pkg/time/#ParseDuration
|
||||
type DurationFlag struct {
|
||||
|
@ -668,6 +466,7 @@ func (f DurationFlag) GetName() string {
|
|||
}
|
||||
|
||||
// Float64Flag is a flag that takes an float value
|
||||
// Errors if the value provided cannot be parsed
|
||||
type Float64Flag struct {
|
||||
Name string
|
||||
Value float64
|
||||
|
@ -713,7 +512,7 @@ func (f Float64Flag) GetName() string {
|
|||
func visibleFlags(fl []Flag) []Flag {
|
||||
visible := []Flag{}
|
||||
for _, flag := range fl {
|
||||
if !flagValue(flag).FieldByName("Hidden").Bool() {
|
||||
if !reflect.ValueOf(flag).FieldByName("Hidden").Bool() {
|
||||
visible = append(visible, flag)
|
||||
}
|
||||
}
|
||||
|
@ -779,24 +578,13 @@ func withEnvHint(envVar, str string) string {
|
|||
return str + envText
|
||||
}
|
||||
|
||||
func flagValue(f Flag) reflect.Value {
|
||||
fv := reflect.ValueOf(f)
|
||||
for fv.Kind() == reflect.Ptr {
|
||||
fv = reflect.Indirect(fv)
|
||||
}
|
||||
return fv
|
||||
}
|
||||
|
||||
func stringifyFlag(f Flag) string {
|
||||
fv := flagValue(f)
|
||||
fv := reflect.ValueOf(f)
|
||||
|
||||
switch f.(type) {
|
||||
case IntSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
||||
case Int64SliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
|
||||
case StringSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
||||
|
@ -842,17 +630,6 @@ func stringifyIntSliceFlag(f IntSliceFlag) string {
|
|||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
}
|
||||
|
||||
func stringifyInt64SliceFlag(f Int64SliceFlag) string {
|
||||
defaultVals := []string{}
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
}
|
||||
|
||||
func stringifyStringSliceFlag(f StringSliceFlag) string {
|
||||
defaultVals := []string{}
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
|
|
208
vendor/github.com/urfave/cli/flag_test.go
generated
vendored
208
vendor/github.com/urfave/cli/flag_test.go
generated
vendored
|
@ -162,114 +162,6 @@ func TestIntFlagWithEnvVarHelpOutput(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var int64FlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"hats", "--hats value\t(default: 8589934592)"},
|
||||
{"H", "-H value\t(default: 8589934592)"},
|
||||
}
|
||||
|
||||
func TestInt64FlagHelpOutput(t *testing.T) {
|
||||
for _, test := range int64FlagTests {
|
||||
flag := Int64Flag{Name: test.name, Value: 8589934592}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt64FlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2")
|
||||
for _, test := range int64FlagTests {
|
||||
flag := IntFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_BAR]"
|
||||
if runtime.GOOS == "windows" {
|
||||
expectedSuffix = " [%APP_BAR%]"
|
||||
}
|
||||
if !strings.HasSuffix(output, expectedSuffix) {
|
||||
t.Errorf("%s does not end with"+expectedSuffix, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var uintFlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"nerfs", "--nerfs value\t(default: 41)"},
|
||||
{"N", "-N value\t(default: 41)"},
|
||||
}
|
||||
|
||||
func TestUintFlagHelpOutput(t *testing.T) {
|
||||
for _, test := range uintFlagTests {
|
||||
flag := UintFlag{Name: test.name, Value: 41}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUintFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2")
|
||||
for _, test := range uintFlagTests {
|
||||
flag := UintFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_BAR]"
|
||||
if runtime.GOOS == "windows" {
|
||||
expectedSuffix = " [%APP_BAR%]"
|
||||
}
|
||||
if !strings.HasSuffix(output, expectedSuffix) {
|
||||
t.Errorf("%s does not end with"+expectedSuffix, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var uint64FlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"gerfs", "--gerfs value\t(default: 8589934582)"},
|
||||
{"G", "-G value\t(default: 8589934582)"},
|
||||
}
|
||||
|
||||
func TestUint64FlagHelpOutput(t *testing.T) {
|
||||
for _, test := range uint64FlagTests {
|
||||
flag := Uint64Flag{Name: test.name, Value: 8589934582}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUint64FlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2")
|
||||
for _, test := range uint64FlagTests {
|
||||
flag := UintFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_BAR]"
|
||||
if runtime.GOOS == "windows" {
|
||||
expectedSuffix = " [%APP_BAR%]"
|
||||
}
|
||||
if !strings.HasSuffix(output, expectedSuffix) {
|
||||
t.Errorf("%s does not end with"+expectedSuffix, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var durationFlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
|
@ -349,49 +241,6 @@ func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
var int64SliceFlagTests = []struct {
|
||||
name string
|
||||
value *Int64Slice
|
||||
expected string
|
||||
}{
|
||||
{"heads", &Int64Slice{}, "--heads value\t"},
|
||||
{"H", &Int64Slice{}, "-H value\t"},
|
||||
{"H, heads", func() *Int64Slice {
|
||||
i := &Int64Slice{}
|
||||
i.Set("2")
|
||||
i.Set("17179869184")
|
||||
return i
|
||||
}(), "-H value, --heads value\t(default: 2, 17179869184)"},
|
||||
}
|
||||
|
||||
func TestInt64SliceFlagHelpOutput(t *testing.T) {
|
||||
for _, test := range int64SliceFlagTests {
|
||||
flag := Int64SliceFlag{Name: test.name, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt64SliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_SMURF", "42,17179869184")
|
||||
for _, test := range int64SliceFlagTests {
|
||||
flag := Int64SliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"}
|
||||
output := flag.String()
|
||||
|
||||
expectedSuffix := " [$APP_SMURF]"
|
||||
if runtime.GOOS == "windows" {
|
||||
expectedSuffix = " [%APP_SMURF%]"
|
||||
}
|
||||
if !strings.HasSuffix(output, expectedSuffix) {
|
||||
t.Errorf("%q does not end with"+expectedSuffix, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var float64FlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
|
@ -730,63 +579,6 @@ func TestParseMultiIntSliceFromEnvCascade(t *testing.T) {
|
|||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiInt64Slice(t *testing.T) {
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
Int64SliceFlag{Name: "serve, s", Value: &Int64Slice{}},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.Int64Slice("serve"), []int64{10, 17179869184}) {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.Int64Slice("s"), []int64{10, 17179869184}) {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}).Run([]string{"run", "-s", "10", "-s", "17179869184"})
|
||||
}
|
||||
|
||||
func TestParseMultiInt64SliceFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,17179869184")
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
Int64SliceFlag{Name: "intervals, i", Value: &Int64Slice{}, EnvVar: "APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.Int64Slice("intervals"), []int64{20, 30, 17179869184}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.Int64Slice("i"), []int64{20, 30, 17179869184}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiInt64SliceFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,17179869184")
|
||||
|
||||
(&App{
|
||||
Flags: []Flag{
|
||||
Int64SliceFlag{Name: "intervals, i", Value: &Int64Slice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *Context) error {
|
||||
if !reflect.DeepEqual(ctx.Int64Slice("intervals"), []int64{20, 30, 17179869184}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.Int64Slice("i"), []int64{20, 30, 17179869184}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiFloat64(t *testing.T) {
|
||||
a := App{
|
||||
Flags: []Flag{
|
||||
|
|
9
vendor/github.com/urfave/cli/help.go
generated
vendored
9
vendor/github.com/urfave/cli/help.go
generated
vendored
|
@ -26,7 +26,7 @@ AUTHOR(S):
|
|||
{{end}}{{if .VisibleCommands}}
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}
|
||||
{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{"\t"}}{{.Usage}}{{end}}
|
||||
{{end}}{{end}}{{if .VisibleFlags}}
|
||||
GLOBAL OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}
|
||||
|
@ -67,7 +67,7 @@ USAGE:
|
|||
|
||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}
|
||||
{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{"\t"}}{{.Usage}}{{end}}
|
||||
{{end}}{{if .VisibleFlags}}
|
||||
OPTIONS:
|
||||
{{range .VisibleFlags}}{{.}}
|
||||
|
@ -117,9 +117,8 @@ var HelpPrinter helpPrinter = printHelp
|
|||
var VersionPrinter = printVersion
|
||||
|
||||
// ShowAppHelp is an action that displays the help.
|
||||
func ShowAppHelp(c *Context) error {
|
||||
func ShowAppHelp(c *Context) {
|
||||
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
||||
|
@ -192,7 +191,7 @@ func printHelp(out io.Writer, templ string, data interface{}) {
|
|||
"join": strings.Join,
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
|
||||
w := tabwriter.NewWriter(out, 0, 8, 1, '\t', 0)
|
||||
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
||||
err := t.Execute(w, data)
|
||||
if err != nil {
|
||||
|
|
70
vendor/github.com/urfave/cli/help_test.go
generated
vendored
70
vendor/github.com/urfave/cli/help_test.go
generated
vendored
|
@ -169,76 +169,6 @@ func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestShowAppHelp_CommandAliases(t *testing.T) {
|
||||
app := &App{
|
||||
Commands: []Command{
|
||||
{
|
||||
Name: "frobbly",
|
||||
Aliases: []string{"fr", "frob"},
|
||||
Action: func(ctx *Context) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
output := &bytes.Buffer{}
|
||||
app.Writer = output
|
||||
app.Run([]string{"foo", "--help"})
|
||||
|
||||
if !strings.Contains(output.String(), "frobbly, fr, frob") {
|
||||
t.Errorf("expected output to include all command aliases; got: %q", output.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestShowCommandHelp_CommandAliases(t *testing.T) {
|
||||
app := &App{
|
||||
Commands: []Command{
|
||||
{
|
||||
Name: "frobbly",
|
||||
Aliases: []string{"fr", "frob", "bork"},
|
||||
Action: func(ctx *Context) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
output := &bytes.Buffer{}
|
||||
app.Writer = output
|
||||
app.Run([]string{"foo", "help", "fr"})
|
||||
|
||||
if !strings.Contains(output.String(), "frobbly") {
|
||||
t.Errorf("expected output to include command name; got: %q", output.String())
|
||||
}
|
||||
|
||||
if strings.Contains(output.String(), "bork") {
|
||||
t.Errorf("expected output to exclude command aliases; got: %q", output.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestShowSubcommandHelp_CommandAliases(t *testing.T) {
|
||||
app := &App{
|
||||
Commands: []Command{
|
||||
{
|
||||
Name: "frobbly",
|
||||
Aliases: []string{"fr", "frob", "bork"},
|
||||
Action: func(ctx *Context) error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
output := &bytes.Buffer{}
|
||||
app.Writer = output
|
||||
app.Run([]string{"foo", "help"})
|
||||
|
||||
if !strings.Contains(output.String(), "frobbly, fr, frob, bork") {
|
||||
t.Errorf("expected output to include all command aliases; got: %q", output.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestShowAppHelp_HiddenCommand(t *testing.T) {
|
||||
app := &App{
|
||||
Commands: []Command{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue