summaryrefslogtreecommitdiffstats
path: root/tpl
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2022-04-10 20:30:52 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2022-04-12 13:24:16 +0200
commit627eed1d620910f494056330733db6c6187b8fe9 (patch)
treea136a398e8f85b10d3de7b1781825453886435ed /tpl
parent82ba634ed90186c756189a79b637559b28dd363e (diff)
Make string sorting (e.g. ByTitle, ByLinkTitle and ByParam) language aware
Fixes #2180
Diffstat (limited to 'tpl')
-rw-r--r--tpl/collections/collections_test.go4
-rw-r--r--tpl/collections/sort.go16
-rw-r--r--tpl/collections/sort_test.go6
-rw-r--r--tpl/compare/compare.go24
4 files changed, 40 insertions, 10 deletions
diff --git a/tpl/collections/collections_test.go b/tpl/collections/collections_test.go
index 8fc43318d..bcc2855c7 100644
--- a/tpl/collections/collections_test.go
+++ b/tpl/collections/collections_test.go
@@ -133,7 +133,9 @@ func TestDelimit(t *testing.T) {
t.Parallel()
c := qt.New(t)
- ns := New(&deps.Deps{})
+ ns := New(&deps.Deps{
+ Language: langs.NewDefaultLanguage(config.New()),
+ })
for i, test := range []struct {
seq any
diff --git a/tpl/collections/sort.go b/tpl/collections/sort.go
index 305399eb8..ce7f27771 100644
--- a/tpl/collections/sort.go
+++ b/tpl/collections/sort.go
@@ -20,6 +20,7 @@ import (
"strings"
"github.com/gohugoio/hugo/common/maps"
+ "github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/tpl/compare"
"github.com/spf13/cast"
)
@@ -47,8 +48,10 @@ func (ns *Namespace) Sort(seq any, args ...any) (any, error) {
return nil, errors.New("can't sort " + reflect.ValueOf(seq).Type().String())
}
+ collator := langs.GetCollator(ns.deps.Language)
+
// Create a list of pairs that will be used to do the sort
- p := pairList{SortAsc: true, SliceType: sliceType}
+ p := pairList{Collator: collator, SortAsc: true, SliceType: sliceType}
p.Pairs = make([]pair, seqv.Len())
var sortByField string
@@ -124,6 +127,10 @@ func (ns *Namespace) Sort(seq any, args ...any) (any, error) {
}
}
}
+
+ collator.Lock()
+ defer collator.Unlock()
+
return p.sort(), nil
}
@@ -137,6 +144,7 @@ type pair struct {
// A slice of pairs that implements sort.Interface to sort by Value.
type pairList struct {
+ Collator *langs.Collator
Pairs []pair
SortAsc bool
SliceType reflect.Type
@@ -151,16 +159,16 @@ func (p pairList) Less(i, j int) bool {
if iv.IsValid() {
if jv.IsValid() {
// can only call Interface() on valid reflect Values
- return sortComp.Lt(iv.Interface(), jv.Interface())
+ return sortComp.LtCollate(p.Collator, iv.Interface(), jv.Interface())
}
// if j is invalid, test i against i's zero value
- return sortComp.Lt(iv.Interface(), reflect.Zero(iv.Type()))
+ return sortComp.LtCollate(p.Collator, iv.Interface(), reflect.Zero(iv.Type()))
}
if jv.IsValid() {
// if i is invalid, test j against j's zero value
- return sortComp.Lt(reflect.Zero(jv.Type()), jv.Interface())
+ return sortComp.LtCollate(p.Collator, reflect.Zero(jv.Type()), jv.Interface())
}
return false
diff --git a/tpl/collections/sort_test.go b/tpl/collections/sort_test.go
index 698118864..a4adccf51 100644
--- a/tpl/collections/sort_test.go
+++ b/tpl/collections/sort_test.go
@@ -19,6 +19,8 @@ import (
"testing"
"github.com/gohugoio/hugo/common/maps"
+ "github.com/gohugoio/hugo/config"
+ "github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/deps"
)
@@ -28,7 +30,9 @@ type stringsSlice []string
func TestSort(t *testing.T) {
t.Parallel()
- ns := New(&deps.Deps{})
+ ns := New(&deps.Deps{
+ Language: langs.NewDefaultLanguage(config.New()),
+ })
type ts struct {
MyInt int
diff --git a/tpl/compare/compare.go b/tpl/compare/compare.go
index 21b9c5bcd..3e9730dad 100644
--- a/tpl/compare/compare.go
+++ b/tpl/compare/compare.go
@@ -21,6 +21,7 @@ import (
"time"
"github.com/gohugoio/hugo/compare"
+ "github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/common/types"
)
@@ -188,10 +189,11 @@ func (n *Namespace) Le(first any, others ...any) bool {
}
// Lt returns the boolean truth of arg1 < arg2 && arg1 < arg3 && arg1 < arg4.
-func (n *Namespace) Lt(first any, others ...any) bool {
+// The provided collator will be used for string comparisons.
+func (n *Namespace) LtCollate(collator *langs.Collator, first any, others ...any) bool {
n.checkComparisonArgCount(1, others...)
for _, other := range others {
- left, right := n.compareGet(first, other)
+ left, right := n.compareGetWithCollator(collator, first, other)
if !(left < right) {
return false
}
@@ -199,6 +201,11 @@ func (n *Namespace) Lt(first any, others ...any) bool {
return true
}
+// Lt returns the boolean truth of arg1 < arg2 && arg1 < arg3 && arg1 < arg4.
+func (n *Namespace) Lt(first any, others ...any) bool {
+ return n.LtCollate(nil, first, others...)
+}
+
func (n *Namespace) checkComparisonArgCount(min int, others ...any) bool {
if len(others) < min {
panic("missing arguments for comparison")
@@ -216,6 +223,10 @@ func (n *Namespace) Conditional(condition bool, a, b any) any {
}
func (ns *Namespace) compareGet(a any, b any) (float64, float64) {
+ return ns.compareGetWithCollator(nil, a, b)
+}
+
+func (ns *Namespace) compareGetWithCollator(collator *langs.Collator, a any, b any) (float64, float64) {
if ac, ok := a.(compare.Comparer); ok {
c := ac.Compare(b)
if c < 0 {
@@ -296,8 +307,13 @@ func (ns *Namespace) compareGet(a any, b any) (float64, float64) {
}
}
- if ns.caseInsensitive && leftStr != nil && rightStr != nil {
- c := compare.Strings(*leftStr, *rightStr)
+ if (ns.caseInsensitive || collator != nil) && leftStr != nil && rightStr != nil {
+ var c int
+ if collator != nil {
+ c = collator.CompareStrings(*leftStr, *rightStr)
+ } else {
+ c = compare.Strings(*leftStr, *rightStr)
+ }
if c < 0 {
return 0, 1
} else if c > 0 {