langs/i18n: Revise the plural implementation

There were some issues introduced with the plural counting when we upgraded from v1 to v2 of go-i18n.

This commit improves that situation given the following rules:

* A single integer argument is used as plural count and passed to the i18n template as a int type with a `.Count` method. The latter is to preserve compability with v1.
* Else the plural count is either fetched from the `Count`/`count` field/method/map or from the value itself.
* Any data type is accepted, if it can be converted to an integer, that value is used.

The above means that you can now do pass a single integer and both of the below will work:

```
{{ . }} minutes to read
{{ .Count }} minutes to read
```

Fixes #8454
Closes #7822
See https://github.com/gohugoio/hugoDocs/issues/1410
This commit is contained in:
Bjørn Erik Pedersen
2021-04-22 09:57:24 +02:00
parent 243951ebe9
commit 537c905ec1
2 changed files with 164 additions and 8 deletions

View File

@@ -141,6 +141,20 @@ other = "{{ .Count }} minutes to read"
expected: "One minute to read",
expectedFlag: "One minute to read",
},
{
name: "readingTime-many-dot",
data: map[string][]byte{
"en.toml": []byte(`[readingTime]
one = "One minute to read"
other = "{{ . }} minutes to read"
`),
},
args: 21,
lang: "en",
id: "readingTime",
expected: "21 minutes to read",
expectedFlag: "21 minutes to read",
},
{
name: "readingTime-many",
data: map[string][]byte{
@@ -155,6 +169,62 @@ other = "{{ .Count }} minutes to read"
expected: "21 minutes to read",
expectedFlag: "21 minutes to read",
},
// Issue #8454
{
name: "readingTime-map-one",
data: map[string][]byte{
"en.toml": []byte(`[readingTime]
one = "One minute to read"
other = "{{ .Count }} minutes to read"
`),
},
args: map[string]interface{}{"Count": 1},
lang: "en",
id: "readingTime",
expected: "One minute to read",
expectedFlag: "One minute to read",
},
{
name: "readingTime-string-one",
data: map[string][]byte{
"en.toml": []byte(`[readingTime]
one = "One minute to read"
other = "{{ . }} minutes to read"
`),
},
args: "1",
lang: "en",
id: "readingTime",
expected: "One minute to read",
expectedFlag: "One minute to read",
},
{
name: "readingTime-map-many",
data: map[string][]byte{
"en.toml": []byte(`[readingTime]
one = "One minute to read"
other = "{{ .Count }} minutes to read"
`),
},
args: map[string]interface{}{"Count": 21},
lang: "en",
id: "readingTime",
expected: "21 minutes to read",
expectedFlag: "21 minutes to read",
},
{
name: "argument-float",
data: map[string][]byte{
"en.toml": []byte(`[float]
other = "Number is {{ . }}"
`),
},
args: 22.5,
lang: "en",
id: "float",
expected: "Number is 22.5",
expectedFlag: "Number is 22.5",
},
// Same id and translation in current language
// https://github.com/gohugoio/hugo/issues/2607
{
@@ -246,6 +316,46 @@ func doTestI18nTranslate(t testing.TB, test i18nTest, cfg config.Provider) strin
return f(test.id, test.args)
}
type countField struct {
Count int
}
type noCountField struct {
Counts int
}
type countMethod struct {
}
func (c countMethod) Count() int {
return 32
}
func TestGetPluralCount(t *testing.T) {
c := qt.New(t)
c.Assert(getPluralCount(map[string]interface{}{"Count": 32}), qt.Equals, 32)
c.Assert(getPluralCount(map[string]interface{}{"Count": 1}), qt.Equals, 1)
c.Assert(getPluralCount(map[string]interface{}{"Count": "32"}), qt.Equals, 32)
c.Assert(getPluralCount(map[string]interface{}{"count": 32}), qt.Equals, 32)
c.Assert(getPluralCount(map[string]interface{}{"Count": "32"}), qt.Equals, 32)
c.Assert(getPluralCount(map[string]interface{}{"Counts": 32}), qt.Equals, 0)
c.Assert(getPluralCount("foo"), qt.Equals, 0)
c.Assert(getPluralCount(countField{Count: 22}), qt.Equals, 22)
c.Assert(getPluralCount(&countField{Count: 22}), qt.Equals, 22)
c.Assert(getPluralCount(noCountField{Counts: 23}), qt.Equals, 0)
c.Assert(getPluralCount(countMethod{}), qt.Equals, 32)
c.Assert(getPluralCount(&countMethod{}), qt.Equals, 32)
c.Assert(getPluralCount(1234), qt.Equals, 1234)
c.Assert(getPluralCount(1234.4), qt.Equals, 1234)
c.Assert(getPluralCount(1234.6), qt.Equals, 1234)
c.Assert(getPluralCount(0.6), qt.Equals, 0)
c.Assert(getPluralCount(1.0), qt.Equals, 1)
c.Assert(getPluralCount("1234"), qt.Equals, 1234)
c.Assert(getPluralCount(nil), qt.Equals, 0)
}
func prepareTranslationProvider(t testing.TB, test i18nTest, cfg config.Provider) *TranslationProvider {
c := qt.New(t)
fs := hugofs.NewMem(cfg)