Skip to content

Commit 1242791

Browse files
committed
setup the package and added dependencies and add some comments on the lib
1 parent 9f4ed2b commit 1242791

File tree

3 files changed

+187
-0
lines changed

3 files changed

+187
-0
lines changed

go.mod

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module github.com/haslten-dev/lokyn
2+
3+
go 1.24.6
4+
5+
require (
6+
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade
7+
github.com/nicksnyder/go-i18n/v2 v2.6.0
8+
golang.org/x/text v0.28.0
9+
)
10+
11+
require golang.org/x/sys v0.27.0 // indirect

go.sum

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
2+
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE=
6+
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
7+
github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ=
8+
github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE=
9+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
11+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
12+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
13+
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
14+
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
15+
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
16+
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
17+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
18+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

lokyn.go

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Package lokyn is a small and lightweight library to help using lower level libs like jeandeaual/go-locale and nicksnyder/go-i18n.
2+
// It's heavily inspired by the Fyne lang package, but in a standalone philosophy. The real deal comes when Lokyn app is used to help
3+
// translating the application.
4+
package lokyn
5+
6+
import (
7+
"embed"
8+
"encoding/json"
9+
"log"
10+
"sync"
11+
12+
"github.com/jeandeaual/go-locale"
13+
"github.com/nicksnyder/go-i18n/v2/i18n"
14+
"golang.org/x/text/language"
15+
)
16+
17+
var (
18+
bundle *i18n.Bundle
19+
localizer *i18n.Localizer
20+
once sync.Once
21+
22+
currentLang language.Tag
23+
translated []language.Tag
24+
)
25+
26+
// Init inits the package, only once.
27+
func Init() {
28+
once.Do(initBundle)
29+
}
30+
31+
// AddTranslationFS registers all the managed languages to lokyn.
32+
func AddTranslationFS(fs embed.FS, dir string) error {
33+
files, err := fs.ReadDir(dir)
34+
if err != nil {
35+
return err
36+
}
37+
38+
for _, f := range files {
39+
name := f.Name()
40+
data, err := fs.ReadFile(dir + "/" + name)
41+
if err != nil {
42+
continue
43+
}
44+
45+
err = addLanguage(data, name)
46+
if err != nil {
47+
continue
48+
}
49+
}
50+
51+
initLanguage()
52+
53+
return nil
54+
}
55+
56+
// GetCurrentLanguage returns the current language as string.
57+
func GetCurrentLanguage() string {
58+
return currentLang.String()
59+
}
60+
61+
// SetLanguage helps defining the current language.
62+
func SetLanguage(lang string) {
63+
setupLang(lang)
64+
}
65+
66+
// L returns translation of the given key.
67+
func L(key string) string {
68+
return getKey(key, key)
69+
}
70+
71+
// P returns translation with plural management.
72+
func P(key string, count int) string {
73+
return getPluralKey(key, key, count)
74+
}
75+
76+
// initBundle initialize lokyn with english language.
77+
func initBundle() {
78+
bundle = i18n.NewBundle(language.English)
79+
bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
80+
81+
translated = []language.Tag{language.Make("en")}
82+
}
83+
84+
// initLanguage init the language based on the system language.
85+
func initLanguage() {
86+
all, err := locale.GetLocales()
87+
if err != nil {
88+
all = []string{"en"}
89+
}
90+
91+
setupLang(closestSupportedLocale(all).String())
92+
}
93+
94+
// setupLang initialize a new localizer for the requested language.
95+
func setupLang(lang string) {
96+
currentLang = language.Make(lang)
97+
localizer = i18n.NewLocalizer(bundle, lang)
98+
}
99+
100+
// addLanguage adds a language to lokyn managed languages.
101+
func addLanguage(data []byte, name string) error {
102+
f, err := bundle.ParseMessageFileBytes(data, name)
103+
if err != nil {
104+
return err
105+
}
106+
107+
translated = append(translated, f.Tag)
108+
return nil
109+
}
110+
111+
// getKey gets the requested key, manage a fallback key.
112+
func getKey(key, fallback string) string {
113+
ret, err := localizer.Localize(&i18n.LocalizeConfig{
114+
DefaultMessage: &i18n.Message{
115+
ID: key,
116+
Other: fallback,
117+
},
118+
})
119+
120+
if err != nil {
121+
log.Println("Error in translation")
122+
}
123+
124+
return ret
125+
}
126+
127+
// getPluralKey gets the requested key, manage a fallback and plural.
128+
func getPluralKey(key, fallback string, count int) string {
129+
ret, err := localizer.Localize(&i18n.LocalizeConfig{
130+
DefaultMessage: &i18n.Message{
131+
ID: key,
132+
Other: fallback,
133+
},
134+
PluralCount: count,
135+
})
136+
137+
if err != nil {
138+
log.Println("Error in translation")
139+
}
140+
141+
return ret
142+
}
143+
144+
// closestSupportedLocale helps to determine the closest language tag based on the locales given in parameter.
145+
func closestSupportedLocale(locs []string) language.Tag {
146+
matcher := language.NewMatcher(translated)
147+
148+
tags := make([]language.Tag, len(locs))
149+
for i, loc := range locs {
150+
tag, err := language.Parse(loc)
151+
if err != nil {
152+
log.Println("Error in parsing tags")
153+
}
154+
tags[i] = tag
155+
}
156+
best, _, _ := matcher.Match(tags...)
157+
return best
158+
}

0 commit comments

Comments
 (0)