From 4c923532a0ba57dfb8cdd4f65eddfda6040b29ee Mon Sep 17 00:00:00 2001 From: Leonel Quinteros Date: Tue, 29 Aug 2023 13:20:03 -0300 Subject: [PATCH] Revert "Add support for multiple languages" --- gotext.go | 246 ++++++++++++++++--------------------------------- gotext_test.go | 20 +--- locale.go | 34 ------- 3 files changed, 83 insertions(+), 217 deletions(-) diff --git a/gotext.go b/gotext.go index 9b6d8f7..a999261 100644 --- a/gotext.go +++ b/gotext.go @@ -24,7 +24,6 @@ package gotext import ( "encoding/gob" - "strings" "sync" ) @@ -32,17 +31,17 @@ import ( type config struct { sync.RWMutex - // Path to library directory where all locale directories and Translation files are. - library string - // Default domain to look at when no domain is specified. Used by package level functions. domain string // Language set. - languages []string + language string + + // Path to library directory where all locale directories and Translation files are. + library string // Storage for package level methods - locales []*Locale + storage *Locale } var globalConfig *config @@ -50,36 +49,29 @@ var globalConfig *config func init() { // Init default configuration globalConfig = &config{ - domain: "default", - languages: []string{"en_US"}, - library: "/usr/local/share/locale", - locales: nil, + domain: "default", + language: "en_US", + library: "/usr/local/share/locale", + storage: nil, } // Register Translator types for gob encoding gob.Register(TranslatorEncoding{}) } -// loadStorage creates a new Locale object at package level based on the Global variables settings -// for every language specified using Configure. +// loadStorage creates a new Locale object at package level based on the Global variables settings. // It's called automatically when trying to use Get or GetD methods. func loadStorage(force bool) { globalConfig.Lock() - if globalConfig.locales == nil || force { - var locales []*Locale - for _, language := range globalConfig.languages { - locales = append(locales, NewLocale(globalConfig.library, language)) - } - globalConfig.locales = locales + if globalConfig.storage == nil || force { + globalConfig.storage = NewLocale(globalConfig.library, globalConfig.language) } - for _, locale := range globalConfig.locales { - if _, ok := locale.Domains[globalConfig.domain]; !ok || force { - locale.AddDomain(globalConfig.domain) - } - locale.SetDomain(globalConfig.domain) + if _, ok := globalConfig.storage.Domains[globalConfig.domain]; !ok || force { + globalConfig.storage.AddDomain(globalConfig.domain) } + globalConfig.storage.SetDomain(globalConfig.domain) globalConfig.Unlock() } @@ -88,9 +80,8 @@ func loadStorage(force bool) { func GetDomain() string { var dom string globalConfig.RLock() - if globalConfig.locales != nil { - // All locales have the same domain - dom = globalConfig.locales[0].GetDomain() + if globalConfig.storage != nil { + dom = globalConfig.storage.GetDomain() } if dom == "" { dom = globalConfig.domain @@ -105,42 +96,28 @@ func GetDomain() string { func SetDomain(dom string) { globalConfig.Lock() globalConfig.domain = dom - if globalConfig.locales != nil { - for _, locale := range globalConfig.locales { - locale.SetDomain(dom) - } + if globalConfig.storage != nil { + globalConfig.storage.SetDomain(dom) } globalConfig.Unlock() loadStorage(true) } -// GetLanguage returns the language gotext will translate into. -// If multiple languages have been supplied, the first one will be returned. +// GetLanguage is the language getter for the package configuration func GetLanguage() string { - return GetLanguages()[0] -} - -// GetLanguages returns all languages that have been supplied. -func GetLanguages() []string { globalConfig.RLock() - defer globalConfig.RUnlock() - return globalConfig.languages + lang := globalConfig.language + globalConfig.RUnlock() + + return lang } -// SetLanguage sets the language code (or colon separated language codes) to be used at package level. +// SetLanguage sets the language code to be used at package level. // It reloads the corresponding Translation file. func SetLanguage(lang string) { globalConfig.Lock() - var languages []string - for _, language := range strings.Split(lang, ":") { - language = SimplifiedLocale(language) - languages = append(languages, language) - if language == "C" { - break - } - } - globalConfig.languages = languages + globalConfig.language = SimplifiedLocale(lang) globalConfig.Unlock() loadStorage(true) @@ -155,7 +132,7 @@ func GetLibrary() string { return lib } -// SetLibrary sets the root path for the locale directories and files to be used at package level. +// SetLibrary sets the root path for the loale directories and files to be used at package level. // It reloads the corresponding Translation file. func SetLibrary(lib string) { globalConfig.Lock() @@ -196,15 +173,7 @@ func SetStorage(storage *Locale) { func Configure(lib, lang, dom string) { globalConfig.Lock() globalConfig.library = lib - var languages []string - for _, language := range strings.Split(lang, ":") { - language = SimplifiedLocale(language) - languages = append(languages, language) - if language == "C" { - break - } - } - globalConfig.languages = languages + globalConfig.language = SimplifiedLocale(lang) globalConfig.domain = dom globalConfig.Unlock() @@ -229,20 +198,16 @@ func GetD(dom, str string, vars ...interface{}) string { // Try to load default package Locale storage loadStorage(false) + // Return Translation globalConfig.RLock() - defer globalConfig.RUnlock() - var tr string - for i, locale := range globalConfig.locales { - if _, ok := locale.Domains[dom]; !ok { - locale.AddDomain(dom) - } - if !locale.IsTranslatedD(dom, str) && i < (len(globalConfig.locales)-1) { - continue - } - tr = locale.GetD(dom, str, vars...) - break + if _, ok := globalConfig.storage.Domains[dom]; !ok { + globalConfig.storage.AddDomain(dom) } + + tr := globalConfig.storage.GetD(dom, str, vars...) + globalConfig.RUnlock() + return tr } @@ -252,20 +217,16 @@ func GetND(dom, str, plural string, n int, vars ...interface{}) string { // Try to load default package Locale storage loadStorage(false) + // Return Translation globalConfig.RLock() - defer globalConfig.RUnlock() - var tr string - for i, locale := range globalConfig.locales { - if _, ok := locale.Domains[dom]; !ok { - locale.AddDomain(dom) - } - if !locale.IsTranslatedND(dom, str, n) && i < (len(globalConfig.locales)-1) { - continue - } - tr = locale.GetND(dom, str, plural, n, vars...) - break + if _, ok := globalConfig.storage.Domains[dom]; !ok { + globalConfig.storage.AddDomain(dom) } + + tr := globalConfig.storage.GetND(dom, str, plural, n, vars...) + globalConfig.RUnlock() + return tr } @@ -287,17 +248,11 @@ func GetDC(dom, str, ctx string, vars ...interface{}) string { // Try to load default package Locale storage loadStorage(false) + // Return Translation globalConfig.RLock() - defer globalConfig.RUnlock() + tr := globalConfig.storage.GetDC(dom, str, ctx, vars...) + globalConfig.RUnlock() - var tr string - for i, locale := range globalConfig.locales { - if !locale.IsTranslatedDC(dom, str, ctx) && i < (len(globalConfig.locales)-1) { - continue - } - tr = locale.GetDC(dom, str, ctx, vars...) - break - } return tr } @@ -309,101 +264,62 @@ func GetNDC(dom, str, plural string, n int, ctx string, vars ...interface{}) str // Return Translation globalConfig.RLock() - defer globalConfig.RUnlock() + tr := globalConfig.storage.GetNDC(dom, str, plural, n, ctx, vars...) + globalConfig.RUnlock() - var tr string - for i, locale := range globalConfig.locales { - if !locale.IsTranslatedNDC(dom, str, n, ctx) && i < (len(globalConfig.locales)-1) { - continue - } - tr = locale.GetNDC(dom, str, plural, n, ctx, vars...) - break - } return tr } -// IsTranslated reports whether a string is translated in given languages. -// When the langs argument is omitted, the output of GetLanguages is used. -func IsTranslated(str string, langs ...string) bool { - return IsTranslatedND(GetDomain(), str, 0, langs...) +// IsTranslated reports whether a string is translated +func IsTranslated(str string) bool { + return IsTranslatedND(GetDomain(), str, 0) } -// IsTranslatedN reports whether a plural string is translated in given languages. -// When the langs argument is omitted, the output of GetLanguages is used. -func IsTranslatedN(str string, n int, langs ...string) bool { - return IsTranslatedND(GetDomain(), str, n, langs...) +// IsTranslatedN reports whether a plural string is translated +func IsTranslatedN(str string, n int) bool { + return IsTranslatedND(GetDomain(), str, n) } -// IsTranslatedD reports whether a domain string is translated in given languages. -// When the langs argument is omitted, the output of GetLanguages is used. -func IsTranslatedD(dom, str string, langs ...string) bool { - return IsTranslatedND(dom, str, 0, langs...) +// IsTranslatedD reports whether a domain string is translated +func IsTranslatedD(dom, str string) bool { + return IsTranslatedND(dom, str, 0) } -// IsTranslatedND reports whether a plural domain string is translated in any of given languages. -// When the langs argument is omitted, the output of GetLanguages is used. -func IsTranslatedND(dom, str string, n int, langs ...string) bool { - if len(langs) == 0 { - langs = GetLanguages() - } - +// IsTranslatedND reports whether a plural domain string is translated +func IsTranslatedND(dom, str string, n int) bool { loadStorage(false) globalConfig.RLock() defer globalConfig.RUnlock() - for _, lang := range langs { - lang = SimplifiedLocale(lang) - - for _, supportedLocale := range globalConfig.locales { - if lang != supportedLocale.GetActualLanguage(dom) { - continue - } - return supportedLocale.IsTranslatedND(dom, str, n) - } - } - return false -} - -// IsTranslatedC reports whether a context string is translated in given languages. -// When the langs argument is omitted, the output of GetLanguages is used. -func IsTranslatedC(str, ctx string, langs ...string) bool { - return IsTranslatedNDC(GetDomain(), str, 0, ctx, langs...) -} - -// IsTranslatedNC reports whether a plural context string is translated in given languages. -// When the langs argument is omitted, the output of GetLanguages is used. -func IsTranslatedNC(str string, n int, ctx string, langs ...string) bool { - return IsTranslatedNDC(GetDomain(), str, n, ctx, langs...) -} - -// IsTranslatedDC reports whether a domain context string is translated in given languages. -// When the langs argument is omitted, the output of GetLanguages is used. -func IsTranslatedDC(dom, str, ctx string, langs ...string) bool { - return IsTranslatedNDC(dom, str, 0, ctx, langs...) -} - -// IsTranslatedNDC reports whether a plural domain context string is translated in any of given languages. -// When the langs argument is omitted, the output of GetLanguages is used. -func IsTranslatedNDC(dom, str string, n int, ctx string, langs ...string) bool { - if len(langs) == 0 { - langs = GetLanguages() + if _, ok := globalConfig.storage.Domains[dom]; !ok { + globalConfig.storage.AddDomain(dom) } + return globalConfig.storage.IsTranslatedND(dom, str, n) +} + +// IsTranslatedC reports whether a context string is translated +func IsTranslatedC(str, ctx string) bool { + return IsTranslatedNDC(GetDomain(), str, 0, ctx) +} + +// IsTranslatedNC reports whether a plural context string is translated +func IsTranslatedNC(str string, n int, ctx string) bool { + return IsTranslatedNDC(GetDomain(), str, n, ctx) +} + +// IsTranslatedDC reports whether a domain context string is translated +func IsTranslatedDC(dom, str, ctx string) bool { + return IsTranslatedNDC(dom, str, 0, ctx) +} + +// IsTranslatedNDC reports whether a plural domain context string is translated +func IsTranslatedNDC(dom, str string, n int, ctx string) bool { loadStorage(false) globalConfig.RLock() defer globalConfig.RUnlock() - for _, lang := range langs { - lang = SimplifiedLocale(lang) - - for _, locale := range globalConfig.locales { - if lang != locale.GetActualLanguage(dom) { - continue - } - return locale.IsTranslatedNDC(dom, str, n, ctx) - } - } - return false + return globalConfig.storage.IsTranslatedNDC(dom, str, n, ctx) } diff --git a/gotext_test.go b/gotext_test.go index ca2d363..561ea69 100644 --- a/gotext_test.go +++ b/gotext_test.go @@ -186,29 +186,13 @@ msgstr "Another text on another domain" t.Errorf("Expected 'Another text on another domain' but got '%s'", tr) } - // IsTranslated tests for when the string is translated in English. + // Test IsTranslation functions if !IsTranslated("My text") { - t.Error("'My text' should be reported as translated when 'langs' is omitted.") + t.Error("'My text' should be reported as translated.") } - if !IsTranslated("My text", "en_US") { - t.Error("'My text' should be reported as translated when 'langs' is 'en_US'.") - } - if IsTranslated("My text", "cs_CZ") { - t.Error("'My text' should be reported as not translated when 'langs' is 'cs_CZ'.") - } - if !IsTranslated("My text", "en_US", "cs_CZ") { - t.Error("'My text' should be reported as translated when 'langs' is 'en_US, cs_CZ'.") - } - - // IsTranslated tests for when the string is not translated in English if IsTranslated("Another string") { t.Error("'Another string' should be reported as not translated.") } - if IsTranslated("String not in .po") { - t.Error("'String not in .po' should be reported as not translated.") - } - - // IsTranslated tests for plurals and contexts plural := "One with var: %s" if !IsTranslated(plural) { t.Errorf("'%s' should be reported as translated for singular.", plural) diff --git a/locale.go b/locale.go index ac204dd..c39d730 100644 --- a/locale.go +++ b/locale.go @@ -111,40 +111,6 @@ func (l *Locale) findExt(dom, ext string) string { return "" } -// GetActualLanguage inspects the filesystem and decides whether to strip -// a CC part of the ll_CC locale string. -func (l *Locale) GetActualLanguage(dom string) string { - extensions := []string{"mo", "po"} - var fp string - for _, ext := range extensions { - // 'll' (or 'll_CC') exists, and it was specified as-is - fp = path.Join(l.path, l.lang, "LC_MESSAGES", dom+"."+ext) - if l.fileExists(fp) { - return l.lang - } - // 'll' exists, but 'll_CC' was specified - if len(l.lang) > 2 { - fp = path.Join(l.path, l.lang[:2], "LC_MESSAGES", dom+"."+ext) - if l.fileExists(fp) { - return l.lang[:2] - } - } - // 'll' (or 'll_CC') exists outside of LC_category, and it was specified as-is - fp = path.Join(l.path, l.lang, dom+"."+ext) - if l.fileExists(fp) { - return l.lang - } - // 'll' exists outside of LC_category, but 'll_CC' was specified - if len(l.lang) > 2 { - fp = path.Join(l.path, l.lang[:2], dom+"."+ext) - if l.fileExists(fp) { - return l.lang[:2] - } - } - } - return "" -} - func (l *Locale) fileExists(filename string) bool { if l.fs != nil { _, err := fs.Stat(l.fs, filename)