// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package message // TODO: some types in this file will need to be made public at some time. // Documentation and method names will reflect this by using the exported name. import ( "sync" "golang.org/x/text/internal" "golang.org/x/text/internal/format" "golang.org/x/text/language" ) // DefaultCatalog is used by SetString. var DefaultCatalog *Catalog = newCatalog() // SetString calls SetString on the default Catalog. func SetString(tag language.Tag, key string, msg string) error { return DefaultCatalog.SetString(tag, key, msg) } // TODO: // // SetSelect is a shorthand for DefaultCatalog.SetSelect. // func SetSelect(tag language.Tag, key string, s ...format.Statement) error { // return DefaultCatalog.SetSelect(tag, key, s...) // } type msgMap map[string]format.Statement // A Catalog holds translations for messages for supported languages. type Catalog struct { index map[language.Tag]msgMap mutex sync.Mutex // For locking all operations. } // Printer creates a Printer that uses c. func (c *Catalog) Printer(tag language.Tag) *Printer { // TODO: pre-create indexes for tag lookup. return &Printer{ tag: tag, cat: c, } } // NewCatalog returns a new Catalog. If a message is not present in a Catalog, // the fallback Catalogs will be used in order as an alternative source. func newCatalog(fallback ...*Catalog) *Catalog { // TODO: implement fallback. return &Catalog{ index: map[language.Tag]msgMap{}, } } // Languages returns a slice of all languages for which the Catalog contains // variants. func (c *Catalog) Languages() []language.Tag { c.mutex.Lock() defer c.mutex.Unlock() tags := []language.Tag{} for t, _ := range c.index { tags = append(tags, t) } internal.SortTags(tags) return tags } // SetString sets the translation for the given language and key. func (c *Catalog) SetString(tag language.Tag, key string, msg string) error { return c.set(tag, key, format.String(msg)) } func (c *Catalog) get(tag language.Tag, key string) (msg string, ok bool) { c.mutex.Lock() defer c.mutex.Unlock() for ; ; tag = tag.Parent() { if msgs, ok := c.index[tag]; ok { if statement, ok := msgs[key]; ok { // TODO: use type switches when we implement selecting. msg := string(statement.(format.String)) return msg, true } } if tag == language.Und { break } } return "", false } func (c *Catalog) set(tag language.Tag, key string, s ...format.Statement) error { if len(s) != 1 { // TODO: handle errors properly when we process statement sequences. panic("statement sequence should be of length 1") } c.mutex.Lock() defer c.mutex.Unlock() m := c.index[tag] if m == nil { m = map[string]format.Statement{} c.index[tag] = m } m[key] = s[0] return nil }