github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/text/message/catalog.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package message
     6  
     7  // TODO: some types in this file will need to be made public at some time.
     8  // Documentation and method names will reflect this by using the exported name.
     9  
    10  import (
    11  	"sync"
    12  
    13  	"golang.org/x/text/internal"
    14  	"golang.org/x/text/internal/format"
    15  	"golang.org/x/text/language"
    16  )
    17  
    18  // DefaultCatalog is used by SetString.
    19  var DefaultCatalog *Catalog = newCatalog()
    20  
    21  // SetString calls SetString on the default Catalog.
    22  func SetString(tag language.Tag, key string, msg string) error {
    23  	return DefaultCatalog.SetString(tag, key, msg)
    24  }
    25  
    26  // TODO:
    27  // // SetSelect is a shorthand for DefaultCatalog.SetSelect.
    28  // func SetSelect(tag language.Tag, key string, s ...format.Statement) error {
    29  // 	return DefaultCatalog.SetSelect(tag, key, s...)
    30  // }
    31  
    32  type msgMap map[string]format.Statement
    33  
    34  // A Catalog holds translations for messages for supported languages.
    35  type Catalog struct {
    36  	index map[language.Tag]msgMap
    37  
    38  	mutex sync.Mutex // For locking all operations.
    39  }
    40  
    41  // Printer creates a Printer that uses c.
    42  func (c *Catalog) Printer(tag language.Tag) *Printer {
    43  	// TODO: pre-create indexes for tag lookup.
    44  	return &Printer{
    45  		tag: tag,
    46  		cat: c,
    47  	}
    48  }
    49  
    50  // NewCatalog returns a new Catalog. If a message is not present in a Catalog,
    51  // the fallback Catalogs will be used in order as an alternative source.
    52  func newCatalog(fallback ...*Catalog) *Catalog {
    53  	// TODO: implement fallback.
    54  	return &Catalog{
    55  		index: map[language.Tag]msgMap{},
    56  	}
    57  }
    58  
    59  // Languages returns a slice of all languages for which the Catalog contains
    60  // variants.
    61  func (c *Catalog) Languages() []language.Tag {
    62  	c.mutex.Lock()
    63  	defer c.mutex.Unlock()
    64  
    65  	tags := []language.Tag{}
    66  	for t, _ := range c.index {
    67  		tags = append(tags, t)
    68  	}
    69  	internal.SortTags(tags)
    70  	return tags
    71  }
    72  
    73  // SetString sets the translation for the given language and key.
    74  func (c *Catalog) SetString(tag language.Tag, key string, msg string) error {
    75  	return c.set(tag, key, format.String(msg))
    76  }
    77  
    78  func (c *Catalog) get(tag language.Tag, key string) (msg string, ok bool) {
    79  	c.mutex.Lock()
    80  	defer c.mutex.Unlock()
    81  
    82  	for ; ; tag = tag.Parent() {
    83  		if msgs, ok := c.index[tag]; ok {
    84  			if statement, ok := msgs[key]; ok {
    85  				// TODO: use type switches when we implement selecting.
    86  				msg := string(statement.(format.String))
    87  				return msg, true
    88  			}
    89  		}
    90  		if tag == language.Und {
    91  			break
    92  		}
    93  	}
    94  	return "", false
    95  }
    96  
    97  func (c *Catalog) set(tag language.Tag, key string, s ...format.Statement) error {
    98  	if len(s) != 1 {
    99  		// TODO: handle errors properly when we process statement sequences.
   100  		panic("statement sequence should be of length 1")
   101  	}
   102  
   103  	c.mutex.Lock()
   104  	defer c.mutex.Unlock()
   105  
   106  	m := c.index[tag]
   107  	if m == nil {
   108  		m = map[string]format.Statement{}
   109  		c.index[tag] = m
   110  	}
   111  	m[key] = s[0]
   112  	return nil
   113  }