Skip to content

Commit c583d09

Browse files
Fix GetN and GetNC to honor package domain. Refactor global package functions to make them all concurrent safe. Fixes #14
1 parent 4d0fbfd commit c583d09

File tree

3 files changed

+209
-45
lines changed

3 files changed

+209
-45
lines changed

CONTRIBUTING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
# CONTRIBUTING
22

3+
This open source project welcomes everybody that wants to contribute to it by implementing new features, fixing bugs, testing, creating documentation or simply talk about it.
4+
5+
Most contributions will start by creating a new Issue to discuss what is the contribution about and to agree on the steps to move forward.
6+
37
## Issues
48

59
All issues reports are welcome. Open a new Issue whenever you want to report a bug, request a change or make a proposal.
610

11+
This should be your start point of contribution.
12+
713

814
## Pull Requests
915

gotext.go

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,68 +22,110 @@ For quick/simple translations you can use the package level functions directly.
2222
*/
2323
package gotext
2424

25-
import "fmt"
25+
import (
26+
"fmt"
27+
"sync"
28+
)
2629

2730
// Global environment variables
28-
var (
31+
type config struct {
32+
sync.RWMutex
33+
2934
// Default domain to look at when no domain is specified. Used by package level functions.
30-
domain = "default"
35+
domain string
3136

3237
// Language set.
33-
language = "en_US"
38+
language string
3439

3540
// Path to library directory where all locale directories and translation files are.
36-
library = "/usr/local/share/locale"
41+
library string
3742

3843
// Storage for package level methods
3944
storage *Locale
40-
)
45+
}
46+
47+
var globalConfig *config
48+
49+
// Init default configuration
50+
func init() {
51+
globalConfig = &config{
52+
domain: "default",
53+
language: "en_US",
54+
library: "/usr/local/share/locale",
55+
storage: nil,
56+
}
57+
}
4158

4259
// loadStorage creates a new Locale object at package level based on the Global variables settings.
4360
// It's called automatically when trying to use Get or GetD methods.
4461
func loadStorage(force bool) {
45-
if storage == nil || force {
46-
storage = NewLocale(library, language)
62+
globalConfig.Lock()
63+
64+
if globalConfig.storage == nil || force {
65+
globalConfig.storage = NewLocale(globalConfig.library, globalConfig.language)
4766
}
4867

49-
if _, ok := storage.domains[domain]; !ok || force {
50-
storage.AddDomain(domain)
68+
if _, ok := globalConfig.storage.domains[globalConfig.domain]; !ok || force {
69+
globalConfig.storage.AddDomain(globalConfig.domain)
5170
}
71+
72+
globalConfig.Unlock()
5273
}
5374

5475
// GetDomain is the domain getter for the package configuration
5576
func GetDomain() string {
56-
return domain
77+
globalConfig.RLock()
78+
dom := globalConfig.domain
79+
globalConfig.RUnlock()
80+
81+
return dom
5782
}
5883

5984
// SetDomain sets the name for the domain to be used at package level.
6085
// It reloads the corresponding translation file.
6186
func SetDomain(dom string) {
62-
domain = dom
87+
globalConfig.Lock()
88+
globalConfig.domain = dom
89+
globalConfig.Unlock()
90+
6391
loadStorage(true)
6492
}
6593

6694
// GetLanguage is the language getter for the package configuration
6795
func GetLanguage() string {
68-
return language
96+
globalConfig.RLock()
97+
lang := globalConfig.language
98+
globalConfig.RUnlock()
99+
100+
return lang
69101
}
70102

71103
// SetLanguage sets the language code to be used at package level.
72104
// It reloads the corresponding translation file.
73105
func SetLanguage(lang string) {
74-
language = lang
106+
globalConfig.Lock()
107+
globalConfig.language = lang
108+
globalConfig.Unlock()
109+
75110
loadStorage(true)
76111
}
77112

78113
// GetLibrary is the library getter for the package configuration
79114
func GetLibrary() string {
80-
return library
115+
globalConfig.RLock()
116+
lib := globalConfig.library
117+
globalConfig.RUnlock()
118+
119+
return lib
81120
}
82121

83122
// SetLibrary sets the root path for the loale directories and files to be used at package level.
84123
// It reloads the corresponding translation file.
85124
func SetLibrary(lib string) {
86-
library = lib
125+
globalConfig.Lock()
126+
globalConfig.library = lib
127+
globalConfig.Unlock()
128+
87129
loadStorage(true)
88130
}
89131

@@ -92,23 +134,27 @@ func SetLibrary(lib string) {
92134
// This function is recommended to be used when changing more than one setting,
93135
// as using each setter will introduce a I/O overhead because the translation file will be loaded after each set.
94136
func Configure(lib, lang, dom string) {
95-
library = lib
96-
language = lang
97-
domain = dom
137+
globalConfig.Lock()
138+
139+
globalConfig.library = lib
140+
globalConfig.language = lang
141+
globalConfig.domain = dom
142+
143+
globalConfig.Unlock()
98144

99145
loadStorage(true)
100146
}
101147

102148
// Get uses the default domain globally set to return the corresponding translation of a given string.
103149
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
104150
func Get(str string, vars ...interface{}) string {
105-
return GetD(domain, str, vars...)
151+
return GetD(GetDomain(), str, vars...)
106152
}
107153

108-
// GetN retrieves the (N)th plural form of translation for the given string in the "default" domain.
154+
// GetN retrieves the (N)th plural form of translation for the given string in the default domain.
109155
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
110156
func GetN(str, plural string, n int, vars ...interface{}) string {
111-
return GetND("default", str, plural, n, vars...)
157+
return GetND(GetDomain(), str, plural, n, vars...)
112158
}
113159

114160
// GetD returns the corresponding translation in the given domain for a given string.
@@ -124,19 +170,23 @@ func GetND(dom, str, plural string, n int, vars ...interface{}) string {
124170
loadStorage(false)
125171

126172
// Return translation
127-
return storage.GetND(dom, str, plural, n, vars...)
173+
globalConfig.RLock()
174+
tr := globalConfig.storage.GetND(dom, str, plural, n, vars...)
175+
globalConfig.RUnlock()
176+
177+
return tr
128178
}
129179

130180
// GetC uses the default domain globally set to return the corresponding translation of the given string in the given context.
131181
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
132182
func GetC(str, ctx string, vars ...interface{}) string {
133-
return GetDC(domain, str, ctx, vars...)
183+
return GetDC(GetDomain(), str, ctx, vars...)
134184
}
135185

136-
// GetNC retrieves the (N)th plural form of translation for the given string in the given context in the "default" domain.
186+
// GetNC retrieves the (N)th plural form of translation for the given string in the given context in the default domain.
137187
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
138188
func GetNC(str, plural string, n int, ctx string, vars ...interface{}) string {
139-
return GetNDC("default", str, plural, n, ctx, vars...)
189+
return GetNDC(GetDomain(), str, plural, n, ctx, vars...)
140190
}
141191

142192
// GetDC returns the corresponding translation in the given domain for the given string in the given context.
@@ -152,7 +202,11 @@ func GetNDC(dom, str, plural string, n int, ctx string, vars ...interface{}) str
152202
loadStorage(false)
153203

154204
// Return translation
155-
return storage.GetNDC(dom, str, plural, n, ctx, vars...)
205+
globalConfig.RLock()
206+
tr := globalConfig.storage.GetNDC(dom, str, plural, n, ctx, vars...)
207+
globalConfig.RUnlock()
208+
209+
return tr
156210
}
157211

158212
// printf applies text formatting only when needed to parse variables.

0 commit comments

Comments
 (0)