github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/langs/language.go (about)

     1  // Copyright 2023 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  const paramsDeprecationWarning = `.Language.Params is deprecated and will be removed in a future release. Use site.Params instead.
    99  
   100  - For all but custom parameters, you need to use the built in Hugo variables, e.g. site.Title, site.LanguageCode; site.Language.Params.Title will not work.
   101  - All custom parameters needs to be placed below params, e.g. [languages.en.params] in TOML.
   102  
   103  See https://gohugo.io/content-management/multilingual/#changes-in-hugo-01120
   104  
   105  `
   106  
   107  // Params returns the language params.
   108  // Note that this is the same as the Site.Params, but we keep it here for legacy reasons.
   109  // Deprecated: Use the site.Params instead.
   110  func (l *Language) Params() maps.Params {
   111  	// TODO(bep) Remove this for now as it created a little too much noise. Need to think about this.
   112  	// See https://github.com/gohugoio/hugo/issues/11025
   113  	//DeprecationFunc(".Language.Params", paramsDeprecationWarning, false)
   114  	return l.params
   115  }
   116  
   117  func (l *Language) LanguageCode() string {
   118  	if l.LanguageConfig.LanguageCode != "" {
   119  		return l.LanguageConfig.LanguageCode
   120  	}
   121  	return l.Lang
   122  }
   123  
   124  func (l *Language) loadLocation(tzStr string) error {
   125  	location, err := time.LoadLocation(tzStr)
   126  	if err != nil {
   127  		return fmt.Errorf("invalid timeZone for language %q: %w", l.Lang, err)
   128  	}
   129  	l.location = location
   130  
   131  	return nil
   132  }
   133  
   134  func (l *Language) String() string {
   135  	return l.Lang
   136  }
   137  
   138  // Languages is a sortable list of languages.
   139  type Languages []*Language
   140  
   141  func (l Languages) AsSet() map[string]bool {
   142  	m := make(map[string]bool)
   143  	for _, lang := range l {
   144  		m[lang.Lang] = true
   145  	}
   146  
   147  	return m
   148  }
   149  
   150  func (l Languages) AsOrdinalSet() map[string]int {
   151  	m := make(map[string]int)
   152  	for i, lang := range l {
   153  		m[lang.Lang] = i
   154  	}
   155  
   156  	return m
   157  }
   158  
   159  // Internal access to unexported Language fields.
   160  // This construct is to prevent them from leaking to the templates.
   161  
   162  func SetParams(l *Language, params maps.Params) {
   163  	l.params = params
   164  }
   165  
   166  func GetTimeFormatter(l *Language) htime.TimeFormatter {
   167  	return l.timeFormatter
   168  }
   169  
   170  func GetTranslator(l *Language) locales.Translator {
   171  	return l.translator
   172  }
   173  
   174  func GetLocation(l *Language) *time.Location {
   175  	return l.location
   176  }
   177  
   178  func GetCollator1(l *Language) *Collator {
   179  	return l.collator1
   180  }
   181  
   182  func GetCollator2(l *Language) *Collator {
   183  	return l.collator2
   184  }
   185  
   186  type Collator struct {
   187  	sync.Mutex
   188  	c *collate.Collator
   189  }
   190  
   191  // CompareStrings compares a and b.
   192  // It returns -1 if a < b, 1 if a > b and 0 if a == b.
   193  // Note that the Collator is not thread safe, so you may want
   194  // to acquire a lock on it before calling this method.
   195  func (c *Collator) CompareStrings(a, b string) int {
   196  	return c.c.CompareString(a, b)
   197  }