taldir

Directory service to resolve wallet mailboxes by messenger addresses
Log | Files | Refs | Submodules | README | LICENSE

dict.go (2978B)


      1 // Copyright 2017 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 catalog
      6 
      7 import (
      8 	"sync"
      9 
     10 	"golang.org/x/text/internal"
     11 	"golang.org/x/text/internal/catmsg"
     12 	"golang.org/x/text/language"
     13 )
     14 
     15 // A Message holds a collection of translations for the same phrase that may
     16 // vary based on the values of substitution arguments.
     17 type Message = catmsg.Message
     18 
     19 // TODO:
     20 // Dictionary returns a Dictionary that returns the first Message, using the
     21 // given language tag, that matches:
     22 //   1. the last one registered by one of the Set methods
     23 //   2. returned by one of the Loaders
     24 //   3. repeat from 1. using the parent language
     25 // This approach allows messages to be underspecified.
     26 // func (c *Catalog) Dictionary(tag language.Tag) (Dictionary, error) {
     27 // 	// TODO: verify dictionary exists.
     28 // 	return &dict{&c.index, tag}, nil
     29 // }
     30 
     31 type dict struct {
     32 	s   *store
     33 	tag language.Tag // TODO: make compact tag.
     34 }
     35 
     36 func (d *dict) Lookup(key string) (data string, ok bool) {
     37 	return d.s.lookup(d.tag, key)
     38 }
     39 
     40 func (b *Builder) lookup(tag language.Tag, key string) (data string, ok bool) {
     41 	return b.index.lookup(tag, key)
     42 }
     43 
     44 func (c *Builder) set(tag language.Tag, key string, s *store, msg ...Message) error {
     45 	data, err := catmsg.Compile(tag, &dict{&c.macros, tag}, catmsg.FirstOf(msg))
     46 
     47 	s.mutex.Lock()
     48 	defer s.mutex.Unlock()
     49 
     50 	m := s.index[tag]
     51 	if m == nil {
     52 		m = msgMap{}
     53 		if s.index == nil {
     54 			s.index = map[language.Tag]msgMap{}
     55 		}
     56 		c.matcher = nil
     57 		s.index[tag] = m
     58 	}
     59 
     60 	m[key] = data
     61 	return err
     62 }
     63 
     64 func (c *Builder) Matcher() language.Matcher {
     65 	c.index.mutex.RLock()
     66 	m := c.matcher
     67 	c.index.mutex.RUnlock()
     68 	if m != nil {
     69 		return m
     70 	}
     71 
     72 	c.index.mutex.Lock()
     73 	if c.matcher == nil {
     74 		c.matcher = language.NewMatcher(c.unlockedLanguages())
     75 	}
     76 	m = c.matcher
     77 	c.index.mutex.Unlock()
     78 	return m
     79 }
     80 
     81 type store struct {
     82 	mutex sync.RWMutex
     83 	index map[language.Tag]msgMap
     84 }
     85 
     86 type msgMap map[string]string
     87 
     88 func (s *store) lookup(tag language.Tag, key string) (data string, ok bool) {
     89 	s.mutex.RLock()
     90 	defer s.mutex.RUnlock()
     91 
     92 	for ; ; tag = tag.Parent() {
     93 		if msgs, ok := s.index[tag]; ok {
     94 			if msg, ok := msgs[key]; ok {
     95 				return msg, true
     96 			}
     97 		}
     98 		if tag == language.Und {
     99 			break
    100 		}
    101 	}
    102 	return "", false
    103 }
    104 
    105 // Languages returns all languages for which the Catalog contains variants.
    106 func (b *Builder) Languages() []language.Tag {
    107 	s := &b.index
    108 	s.mutex.RLock()
    109 	defer s.mutex.RUnlock()
    110 
    111 	return b.unlockedLanguages()
    112 }
    113 
    114 func (b *Builder) unlockedLanguages() []language.Tag {
    115 	s := &b.index
    116 	if len(s.index) == 0 {
    117 		return nil
    118 	}
    119 	tags := make([]language.Tag, 0, len(s.index))
    120 	_, hasFallback := s.index[b.options.fallback]
    121 	offset := 0
    122 	if hasFallback {
    123 		tags = append(tags, b.options.fallback)
    124 		offset = 1
    125 	}
    126 	for t := range s.index {
    127 		if t != b.options.fallback {
    128 			tags = append(tags, t)
    129 		}
    130 	}
    131 	internal.SortTags(tags[offset:])
    132 	return tags
    133 }