language.go - hugo - [fork] hugo port for 9front
HTML git clone https://git.drkhsh.at/hugo.git
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
language.go (4881B)
---
1 // Copyright 2024 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 langs contains the language related types and function.
15 package langs
16
17 import (
18 "fmt"
19 "sync"
20 "time"
21
22 "golang.org/x/text/collate"
23 "golang.org/x/text/language"
24
25 "github.com/gohugoio/hugo/common/htime"
26 "github.com/gohugoio/hugo/common/maps"
27 "github.com/gohugoio/locales"
28 translators "github.com/gohugoio/localescompressed"
29 )
30
31 type Language struct {
32 // The language code, e.g. "en" or "no".
33 // This is currently only settable as the key in the language map in the config.
34 Lang string
35
36 // Fields from the language config.
37 LanguageConfig
38
39 // Used for date formatting etc. We don't want these exported to the
40 // templates.
41 translator locales.Translator
42 timeFormatter htime.TimeFormatter
43 tag language.Tag
44 // collator1 and collator2 are the same, we have 2 to prevent deadlocks.
45 collator1 *Collator
46 collator2 *Collator
47
48 location *time.Location
49
50 // This is just an alias of Site.Params.
51 params maps.Params
52 }
53
54 // NewLanguage creates a new language.
55 func NewLanguage(lang, defaultContentLanguage, timeZone string, languageConfig LanguageConfig) (*Language, error) {
56 translator := translators.GetTranslator(lang)
57 if translator == nil {
58 translator = translators.GetTranslator(defaultContentLanguage)
59 if translator == nil {
60 translator = translators.GetTranslator("en")
61 }
62 }
63
64 var coll1, coll2 *Collator
65 tag, err := language.Parse(lang)
66 if err == nil {
67 coll1 = &Collator{
68 c: collate.New(tag),
69 }
70 coll2 = &Collator{
71 c: collate.New(tag),
72 }
73 } else {
74 coll1 = &Collator{
75 c: collate.New(language.English),
76 }
77 coll2 = &Collator{
78 c: collate.New(language.English),
79 }
80 }
81
82 l := &Language{
83 Lang: lang,
84 LanguageConfig: languageConfig,
85 translator: translator,
86 timeFormatter: htime.NewTimeFormatter(translator),
87 tag: tag,
88 collator1: coll1,
89 collator2: coll2,
90 }
91
92 return l, l.loadLocation(timeZone)
93 }
94
95 // This is injected from hugolib to avoid circular dependencies.
96 var DeprecationFunc = func(item, alternative string, err bool) {}
97
98 // Params returns the language params.
99 // Note that this is the same as the Site.Params, but we keep it here for legacy reasons.
100 // Deprecated: Use the site.Params instead.
101 func (l *Language) Params() maps.Params {
102 // TODO(bep) Remove this for now as it created a little too much noise. Need to think about this.
103 // See https://github.com/gohugoio/hugo/issues/11025
104 // DeprecationFunc(".Language.Params", paramsDeprecationWarning, false)
105 return l.params
106 }
107
108 func (l *Language) LanguageCode() string {
109 if l.LanguageConfig.LanguageCode != "" {
110 return l.LanguageConfig.LanguageCode
111 }
112 return l.Lang
113 }
114
115 func (l *Language) loadLocation(tzStr string) error {
116 location, err := time.LoadLocation(tzStr)
117 if err != nil {
118 return fmt.Errorf("invalid timeZone for language %q: %w", l.Lang, err)
119 }
120 l.location = location
121
122 return nil
123 }
124
125 func (l *Language) String() string {
126 return l.Lang
127 }
128
129 // Languages is a sortable list of languages.
130 type Languages []*Language
131
132 func (l Languages) AsSet() map[string]bool {
133 m := make(map[string]bool)
134 for _, lang := range l {
135 m[lang.Lang] = true
136 }
137
138 return m
139 }
140
141 // AsIndexSet returns a map with the language code as key and index in l as value.
142 func (l Languages) AsIndexSet() map[string]int {
143 m := make(map[string]int)
144 for i, lang := range l {
145 m[lang.Lang] = i
146 }
147
148 return m
149 }
150
151 // Internal access to unexported Language fields.
152 // This construct is to prevent them from leaking to the templates.
153
154 func SetParams(l *Language, params maps.Params) {
155 l.params = params
156 }
157
158 func GetTimeFormatter(l *Language) htime.TimeFormatter {
159 return l.timeFormatter
160 }
161
162 func GetTranslator(l *Language) locales.Translator {
163 return l.translator
164 }
165
166 func GetLocation(l *Language) *time.Location {
167 return l.location
168 }
169
170 func GetCollator1(l *Language) *Collator {
171 return l.collator1
172 }
173
174 func GetCollator2(l *Language) *Collator {
175 return l.collator2
176 }
177
178 type Collator struct {
179 sync.Mutex
180 c *collate.Collator
181 }
182
183 // CompareStrings compares a and b.
184 // It returns -1 if a < b, 1 if a > b and 0 if a == b.
185 // Note that the Collator is not thread safe, so you may want
186 // to acquire a lock on it before calling this method.
187 func (c *Collator) CompareStrings(a, b string) int {
188 return c.c.CompareString(a, b)
189 }