github.com/SDLMoe/hugo@v0.47.1/tpl/lang/lang.go (about) 1 // Copyright 2017 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package lang 15 16 import ( 17 "errors" 18 "fmt" 19 "math" 20 "strconv" 21 "strings" 22 23 "github.com/gohugoio/hugo/deps" 24 "github.com/spf13/cast" 25 ) 26 27 // New returns a new instance of the lang-namespaced template functions. 28 func New(deps *deps.Deps) *Namespace { 29 return &Namespace{ 30 deps: deps, 31 } 32 } 33 34 // Namespace provides template functions for the "lang" namespace. 35 type Namespace struct { 36 deps *deps.Deps 37 } 38 39 // Translate ... 40 func (ns *Namespace) Translate(id interface{}, args ...interface{}) (string, error) { 41 sid, err := cast.ToStringE(id) 42 if err != nil { 43 return "", nil 44 } 45 46 return ns.deps.Translate(sid, args...), nil 47 } 48 49 // NumFmt formats a number with the given precision using the 50 // negative, decimal, and grouping options. The `options` 51 // parameter is a string consisting of `<negative> <decimal> <grouping>`. The 52 // default `options` value is `- . ,`. 53 // 54 // Note that numbers are rounded up at 5 or greater. 55 // So, with precision set to 0, 1.5 becomes `2`, and 1.4 becomes `1`. 56 func (ns *Namespace) NumFmt(precision, number interface{}, options ...interface{}) (string, error) { 57 prec, err := cast.ToIntE(precision) 58 if err != nil { 59 return "", err 60 } 61 62 n, err := cast.ToFloat64E(number) 63 if err != nil { 64 return "", err 65 } 66 67 var neg, dec, grp string 68 69 if len(options) == 0 { 70 // TODO(moorereason): move to site config 71 neg, dec, grp = "-", ".", "," 72 } else { 73 s, err := cast.ToStringE(options[0]) 74 if err != nil { 75 return "", nil 76 } 77 78 rs := strings.Fields(s) 79 switch len(rs) { 80 case 0: 81 case 1: 82 neg = rs[0] 83 case 2: 84 neg, dec = rs[0], rs[1] 85 case 3: 86 neg, dec, grp = rs[0], rs[1], rs[2] 87 default: 88 return "", errors.New("too many fields in options parameter to NumFmt") 89 } 90 } 91 92 // Logic from MIT Licensed github.com/go-playground/locales/ 93 // Original Copyright (c) 2016 Go Playground 94 95 s := strconv.FormatFloat(math.Abs(n), 'f', prec, 64) 96 L := len(s) + 2 + len(s[:len(s)-1-prec])/3 97 98 var count int 99 inWhole := prec == 0 100 b := make([]byte, 0, L) 101 102 for i := len(s) - 1; i >= 0; i-- { 103 if s[i] == '.' { 104 for j := len(dec) - 1; j >= 0; j-- { 105 b = append(b, dec[j]) 106 } 107 inWhole = true 108 continue 109 } 110 111 if inWhole { 112 if count == 3 { 113 for j := len(grp) - 1; j >= 0; j-- { 114 b = append(b, grp[j]) 115 } 116 count = 1 117 } else { 118 count++ 119 } 120 } 121 122 b = append(b, s[i]) 123 } 124 125 if n < 0 { 126 for j := len(neg) - 1; j >= 0; j-- { 127 b = append(b, neg[j]) 128 } 129 } 130 131 // reverse 132 for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 { 133 b[i], b[j] = b[j], b[i] 134 } 135 136 return string(b), nil 137 } 138 139 type pagesLanguageMerger interface { 140 MergeByLanguageInterface(other interface{}) (interface{}, error) 141 } 142 143 func (ns *Namespace) Merge(p2, p1 interface{}) (interface{}, error) { 144 merger, ok := p1.(pagesLanguageMerger) 145 if !ok { 146 return nil, fmt.Errorf("language merge not supported for %T", p1) 147 } 148 return merger.MergeByLanguageInterface(p2) 149 }