Merge pull request #84 from leonelquinteros/revert-73-multilang

Revert "Add support for multiple languages"
This commit is contained in:
Leonel Quinteros 2023-08-29 13:20:19 -03:00 committed by GitHub
commit 37f474cfb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 217 deletions

246
gotext.go
View file

@ -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)
}

View file

@ -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)

View file

@ -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)