Added basic i18n
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
query "github.com/tgckpg/golifehk/query"
|
||||
)
|
||||
|
||||
type Generics struct {
|
||||
Name *map[string]string
|
||||
query.Words
|
||||
}
|
||||
8
i18n/distance.go
Normal file
8
i18n/distance.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package i18n
|
||||
|
||||
func FormatDistance(langPack LangPack, meters float64) string {
|
||||
if meters < 1000 {
|
||||
return UNITS_METER.Text(langPack, meters)
|
||||
}
|
||||
return UNITS_KM.Text(langPack, meters/1000)
|
||||
}
|
||||
66
i18n/functions.go
Normal file
66
i18n/functions.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
langRes "github.com/tgckpg/golifehk/resources/langpacks"
|
||||
)
|
||||
|
||||
type LangPack map[string]string
|
||||
|
||||
var (
|
||||
LangPacks = map[string]LangPack{}
|
||||
defaultLang = "en"
|
||||
langMu sync.RWMutex
|
||||
)
|
||||
|
||||
func LoadKeys(lang string) (LangPack, error) {
|
||||
langMu.RLock()
|
||||
langPack, ok := LangPacks[lang]
|
||||
langMu.RUnlock()
|
||||
if ok {
|
||||
return langPack, nil
|
||||
}
|
||||
|
||||
langMu.Lock()
|
||||
defer langMu.Unlock()
|
||||
|
||||
// check again after obtaining write lock
|
||||
if langPack, ok := LangPacks[lang]; ok {
|
||||
return langPack, nil
|
||||
}
|
||||
|
||||
data, err := langRes.FS.ReadFile(lang + "/messages.json")
|
||||
if err == nil {
|
||||
var parsed LangPack
|
||||
if err := json.Unmarshal(data, &parsed); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
LangPacks[lang] = parsed
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
if lang == defaultLang {
|
||||
return nil, fmt.Errorf("No language packs available: %s", lang)
|
||||
}
|
||||
|
||||
// avoid recursive locking mess; explicit fallback is cleaner
|
||||
if fallback, ok := LangPacks[defaultLang]; ok {
|
||||
return fallback, nil
|
||||
}
|
||||
|
||||
data, err = langRes.FS.ReadFile("langpacks/" + defaultLang + "/messages.json")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("No language packs available: %s", lang)
|
||||
}
|
||||
|
||||
var fallback LangPack
|
||||
if err := json.Unmarshal(data, &fallback); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
LangPacks[defaultLang] = fallback
|
||||
return fallback, nil
|
||||
}
|
||||
15
i18n/messages.go
Normal file
15
i18n/messages.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package i18n
|
||||
|
||||
const (
|
||||
DS_KMB_ETA_DEPARTED Key = "DS.KMB.ETA.DEPARTED"
|
||||
DS_KMB_NEAREST_STOPS Key = "DS.KMB.NEAREST_STOPS"
|
||||
DS_KMB_NO_NEAREST_STOPS Key = "DS.KMB.NO_NEAREST_STOPS"
|
||||
DS_MTR_NEAREST_STOPS Key = "DS.MTR.NEAREST_STOPS"
|
||||
DS_MTR_NO_NEAREST_STOPS Key = "DS.MTR.NO_NEAREST_STOPS"
|
||||
DS_MTR_NO_SCHEDULES Key = "DS.MTR.NO_SCHEDULES"
|
||||
NO_RESULTS Key = "NO_RESULTS"
|
||||
UNITS_MINUTE Key = "UNITS.MINUTE"
|
||||
UNITS_KM Key = "UNITS.KM"
|
||||
UNITS_METER Key = "UNITS.METER"
|
||||
UNITS_MILE Key = "UNITS.MILE"
|
||||
)
|
||||
31
i18n/race_test.go
Normal file
31
i18n/race_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadKeysRace(t *testing.T) {
|
||||
// Reset shared global state so the test starts clean
|
||||
LangPacks = map[string]LangPack{}
|
||||
|
||||
const goroutines = 200
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(goroutines)
|
||||
|
||||
start := make(chan struct{})
|
||||
|
||||
for i := 0; i < goroutines; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
<-start
|
||||
_, _ = LoadKeys("en")
|
||||
}()
|
||||
}
|
||||
|
||||
// Release all goroutines at once to maximize overlap
|
||||
close(start)
|
||||
wg.Wait()
|
||||
}
|
||||
26
i18n/types.go
Normal file
26
i18n/types.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
query "github.com/tgckpg/golifehk/query"
|
||||
)
|
||||
|
||||
type Generics struct {
|
||||
Name *map[string]string
|
||||
query.Words
|
||||
}
|
||||
|
||||
type Key string
|
||||
|
||||
func (k Key) Text(langPack map[string]string, args ...any) string {
|
||||
txt, ok := langPack[string(k)]
|
||||
if !ok {
|
||||
return string(k)
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
return fmt.Sprintf(txt, args...)
|
||||
}
|
||||
|
||||
return txt
|
||||
}
|
||||
Reference in New Issue
Block a user