// Copyright 2020 ChaiShushan . All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gettext import ( "fmt" "sync" ) type _Locale struct { mutex sync.Mutex fs FileSystem lang string domain string trMap map[string]*translator trCurrent *translator } var _ Gettexter = (*_Locale)(nil) func newLocale(domain, path string, data ...interface{}) *_Locale { if domain == "" { domain = "default" } p := &_Locale{ lang: DefaultLanguage, domain: domain, } if len(data) > 0 { p.fs = NewFS(path, data[0]) } else { p.fs = NewFS(path, nil) } p.syncTrMap() return p } func (p *_Locale) makeTrMapKey(domain, _Locale string) string { return domain + "_$$$_" + _Locale } func (p *_Locale) FileSystem() FileSystem { return p.fs } func (p *_Locale) GetLanguage() string { p.mutex.Lock() defer p.mutex.Unlock() return p.lang } func (p *_Locale) SetLanguage(lang string) Gettexter { p.mutex.Lock() defer p.mutex.Unlock() if lang == "" { lang = DefaultLanguage } if lang == p.lang { return p } p.lang = lang p.syncTrMap() return p } func (p *_Locale) GetDomain() string { p.mutex.Lock() defer p.mutex.Unlock() return p.domain } func (p *_Locale) SetDomain(domain string) Gettexter { p.mutex.Lock() defer p.mutex.Unlock() if domain == "" || domain == p.domain { return p } p.domain = domain p.syncTrMap() return p } func (p *_Locale) syncTrMap() { p.trMap = make(map[string]*translator) trMapKey := p.makeTrMapKey(p.domain, p.lang) if tr, ok := p.trMap[trMapKey]; ok { p.trCurrent = tr return } // try load po file if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".po"); err == nil { if tr, err := newPoTranslator(fmt.Sprintf("%s_%s.po", p.domain, p.lang), data); err == nil { p.trMap[trMapKey] = tr p.trCurrent = tr return } } // try load mo file if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".mo"); err == nil { if tr, err := newMoTranslator(fmt.Sprintf("%s_%s.mo", p.domain, p.lang), data); err == nil { p.trMap[trMapKey] = tr p.trCurrent = tr return } } // try load json file if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".json"); err == nil { if tr, err := newJsonTranslator(p.lang, fmt.Sprintf("%s_%s.json", p.domain, p.lang), data); err == nil { p.trMap[trMapKey] = tr p.trCurrent = tr return } } // no po/mo file p.trMap[trMapKey] = nilTranslator p.trCurrent = nilTranslator return } func (p *_Locale) Gettext(msgid string) string { p.mutex.Lock() defer p.mutex.Unlock() return p.trCurrent.PGettext("", msgid) } func (p *_Locale) PGettext(msgctxt, msgid string) string { p.mutex.Lock() defer p.mutex.Unlock() return p.trCurrent.PGettext(msgctxt, msgid) } func (p *_Locale) NGettext(msgid, msgidPlural string, n int) string { p.mutex.Lock() defer p.mutex.Unlock() return p.trCurrent.PNGettext("", msgid, msgidPlural, n) } func (p *_Locale) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { p.mutex.Lock() defer p.mutex.Unlock() return p.trCurrent.PNGettext(msgctxt, msgid, msgidPlural, n) } func (p *_Locale) DGettext(domain, msgid string) string { p.mutex.Lock() defer p.mutex.Unlock() return p.gettext(domain, "", msgid, "", 0) } func (p *_Locale) DNGettext(domain, msgid, msgidPlural string, n int) string { p.mutex.Lock() defer p.mutex.Unlock() return p.gettext(domain, "", msgid, msgidPlural, n) } func (p *_Locale) DPGettext(domain, msgctxt, msgid string) string { p.mutex.Lock() defer p.mutex.Unlock() return p.gettext(domain, msgctxt, msgid, "", 0) } func (p *_Locale) DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { p.mutex.Lock() defer p.mutex.Unlock() return p.gettext(domain, msgctxt, msgid, msgidPlural, n) } func (p *_Locale) Getdata(name string) []byte { return p.getdata(p.domain, name) } func (p *_Locale) DGetdata(domain, name string) []byte { return p.getdata(domain, name) } func (p *_Locale) gettext(domain, msgctxt, msgid, msgidPlural string, n int) string { if f, ok := p.trMap[p.makeTrMapKey(domain, p.lang)]; ok { return f.PNGettext(msgctxt, msgid, msgidPlural, n) } return msgid } func (p *_Locale) getdata(domain, name string) []byte { if data, err := p.fs.LoadResourceFile(domain, p.lang, name); err == nil { return data } if p.lang != "default" { if data, err := p.fs.LoadResourceFile(domain, "default", name); err == nil { return data } } return nil }