taldir

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

locale.go (4259B)


      1 package internal
      2 
      3 import (
      4 	"fmt"
      5 	"text/template"
      6 
      7 	"golang.org/x/text/language"
      8 	"golang.org/x/text/message"
      9 	"golang.org/x/text/message/catalog"
     10 )
     11 
     12 // Locale is the default Locale.
     13 // Created by Catalog.
     14 // One Locale maps to one registered and loaded language.
     15 // Stores the translation variables and most importantly, the Messages (keys and their renderers).
     16 type Locale struct {
     17 	// The index of the language registered by the user, starting from zero.
     18 	index int
     19 	tag   language.Tag
     20 	// ID is the tag.String().
     21 	ID string
     22 	// Options given by the Catalog
     23 	Options Options
     24 
     25 	// Fields set by Catalog.
     26 	FuncMap template.FuncMap
     27 	Printer *message.Printer
     28 	//
     29 
     30 	// Fields set by this Load method.
     31 	Messages map[string]Renderer
     32 	Vars     []Var // shared per-locale variables.
     33 }
     34 
     35 // Load sets the translation messages based on the Catalog's key values.
     36 func (loc *Locale) Load(c *Catalog, keyValues Map) error {
     37 	return loc.setMap(c, "", keyValues)
     38 }
     39 
     40 func (loc *Locale) setMap(c *Catalog, key string, keyValues Map) error {
     41 	// unique locals or the shared ones.
     42 	isRoot := key == ""
     43 
     44 	vars := getVars(loc, VarsKey, keyValues)
     45 	if isRoot {
     46 		loc.Vars = vars
     47 	} else {
     48 		vars = removeVarsDuplicates(append(vars, loc.Vars...))
     49 	}
     50 
     51 	for k, v := range keyValues {
     52 		form, isPlural := loc.Options.PluralFormDecoder(loc, k)
     53 		if isPlural {
     54 			k = key
     55 		} else if !isRoot {
     56 			k = key + "." + k
     57 		}
     58 
     59 		switch value := v.(type) {
     60 		case string:
     61 			if err := loc.setString(c, k, value, vars, form); err != nil {
     62 				return fmt.Errorf("%s:%s parse string: %w", loc.ID, key, err)
     63 			}
     64 		case Map:
     65 			// fmt.Printf("%s is map\n", fullKey)
     66 			if err := loc.setMap(c, k, value); err != nil {
     67 				return fmt.Errorf("%s:%s parse map: %w", loc.ID, key, err)
     68 			}
     69 
     70 		default:
     71 			return fmt.Errorf("%s:%s unexpected type of %T as value", loc.ID, key, value)
     72 		}
     73 	}
     74 
     75 	return nil
     76 }
     77 
     78 func (loc *Locale) setString(c *Catalog, key string, value string, vars []Var, form PluralForm) (err error) {
     79 	isPlural := form != nil
     80 
     81 	// fmt.Printf("setStringVars: %s=%s\n", key, value)
     82 	msgs, vars := makeSelectfVars(value, vars, isPlural)
     83 	msgs = append(msgs, catalog.String(value))
     84 
     85 	m := &Message{
     86 		Locale: loc,
     87 		Key:    key,
     88 		Value:  value,
     89 		Vars:   vars,
     90 		Plural: isPlural,
     91 	}
     92 
     93 	var (
     94 		renderer, pluralRenderer Renderer = m, m
     95 	)
     96 
     97 	if stringIsTemplateValue(value, loc.Options.Left, loc.Options.Right) {
     98 		t, err := NewTemplate(c, m)
     99 		if err != nil {
    100 			return err
    101 		}
    102 
    103 		pluralRenderer = t
    104 		if !isPlural {
    105 			renderer = t
    106 		}
    107 	} else {
    108 		if isPlural {
    109 			pluralRenderer, err = newIndependentPluralRenderer(c, loc, key, msgs...)
    110 			if err != nil {
    111 				return fmt.Errorf("<%s = %s>: %w", key, value, err)
    112 			}
    113 		} else {
    114 			// let's make normal keys direct fire:
    115 			// renderer = &simpleRenderer{key, loc.Printer}
    116 			if err = c.Set(loc.tag, key, msgs...); err != nil {
    117 				return fmt.Errorf("<%s = %s>: %w", key, value, err)
    118 			}
    119 		}
    120 
    121 	}
    122 
    123 	if isPlural {
    124 		if existingMsg, ok := loc.Messages[key]; ok {
    125 			if msg, ok := existingMsg.(*Message); ok {
    126 				msg.AddPlural(form, pluralRenderer)
    127 				return
    128 			}
    129 		}
    130 
    131 		m.AddPlural(form, pluralRenderer)
    132 	}
    133 
    134 	loc.Messages[key] = renderer
    135 	return
    136 }
    137 
    138 // Index returns the current locale index from the languages list.
    139 func (loc *Locale) Index() int {
    140 	return loc.index
    141 }
    142 
    143 // Tag returns the full language Tag attached to this Locale,
    144 // it should be unique across different Locales.
    145 func (loc *Locale) Tag() *language.Tag {
    146 	return &loc.tag
    147 }
    148 
    149 // Language should return the exact languagecode of this `Locale`
    150 // that the user provided on `New` function.
    151 //
    152 // Same as `Tag().String()` but it's static.
    153 func (loc *Locale) Language() string {
    154 	return loc.ID
    155 }
    156 
    157 // GetMessage should return translated text based on the given "key".
    158 func (loc *Locale) GetMessage(key string, args ...interface{}) string {
    159 	return loc.getMessage(loc.ID, key, args...)
    160 }
    161 
    162 func (loc *Locale) getMessage(langInput, key string, args ...interface{}) string {
    163 	if msg, ok := loc.Messages[key]; ok {
    164 		result, err := msg.Render(args...)
    165 		if err != nil {
    166 			result = err.Error()
    167 		}
    168 
    169 		return result
    170 	}
    171 
    172 	if fn := loc.Options.DefaultMessageFunc; fn != nil {
    173 		// let langInput to be empty if that's the case.
    174 		return fn(langInput, loc.ID, key, args...)
    175 	}
    176 
    177 	return ""
    178 }