Loading pkg/i18n/countries/countries.go +11 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ import "errors" var ( // ErrorFunctionNotImplemented is returned when a function is not implemented. ErrorFunctionNotImplemented = errors.New("function not implemented") // ErrorUnknownCountry is returned when country is not known. ErrorUnknownCountry = errors.New("unkown country") ) // Countries holds mappings. Loading @@ -24,3 +26,12 @@ func (c *Countries) Add(country, description string) (bool, error) { c.data[country] = description return true, nil } // Get ... func (c *Countries) Get(country string) (bool, error) { _, valid := c.data[country] if !valid { return false, ErrorUnknownCountry } return true, nil } pkg/i18n/i18n.go 0 → 100644 +120 −0 Original line number Diff line number Diff line package i18n import ( "errors" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/countries" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/languages" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/mappings" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/translations" ) var ( // ErrorNilMapping is returned when the mapping is nil. ErrorNilMapping = errors.New("mapping is nil") // ErrorNoTranslation ... ErrorNoTranslation = errors.New("no translation") // ErrorCurrentIsNil ... ErrorCurrentIsNil = errors.New("current is nil") ) // I18N ... type I18N struct { languages *languages.Languages countries *countries.Countries mappings *mappings.Mappings translations *translations.Translations standard *mappings.Mapping current *mappings.Mapping } // New ... func New() *I18N { return &I18N{ languages: languages.New(), countries: countries.New(), mappings: mappings.New(), translations: translations.New(), } } // AddCountry ... func (i18n *I18N) AddCountry(country, description string) (bool, error) { return i18n.countries.Add(country, description) } // AddLanguage ... func (i18n *I18N) AddLanguage(language, description string) (bool, error) { return i18n.languages.Add(language, description) } // AddMapping ... func (i18n *I18N) AddMapping(language, country, description string, fallback *mappings.Mapping) (bool, error) { if fallback == nil { i18n.standard = fallback } return i18n.mappings.Add(language, country, description, fallback) } // GetMapping ... func (i18n *I18N) GetMapping(language, country string) (*mappings.Mapping, error) { return i18n.mappings.Get(language, country) } // SetMapping ... func (i18n *I18N) SetMapping(language, country string) (bool, error) { if lt, lerr := i18n.languages.Get(language); !lt { return false, lerr } if ct, cerr := i18n.countries.Get(country); !ct { return false, cerr } mp, merr := i18n.GetMapping(language, country) if merr != nil { return false, merr } i18n.current = mp return true, nil } // AddTranslation ... func (i18n *I18N) AddTranslation(language, country, name, value string) (bool, error) { if lt, lerr := i18n.languages.Get(language); !lt { return false, lerr } if ct, cerr := i18n.countries.Get(country); !ct { return false, cerr } return i18n.translations.Add(language, country, name, value) } // GetTranslation ... func (i18n *I18N) GetTranslation(name string) (string, error) { if i18n.current == nil { return "", ErrorCurrentIsNil } if lt, lerr := i18n.languages.Get(i18n.current.Language); !lt { return "", lerr } if ct, cerr := i18n.countries.Get(i18n.current.Country); !ct { return "", cerr } fallback, _ := i18n.mappings.GetFallback(i18n.current.Language, i18n.current.Country) for _, m := range []*mappings.Mapping{ i18n.current, fallback, i18n.standard, } { if m == nil { continue } val, err := i18n.translations.Get(m, name) if err != nil { continue } return val, nil } return "", ErrorNoTranslation } pkg/i18n/i18n_test.go +44 −38 Original line number Diff line number Diff line Loading @@ -4,54 +4,60 @@ import ( "strings" "testing" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/countries" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/languages" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/mappings" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/translations" ) func TestI18N(t *testing.T) { countries := countries.New() countries.Add("US", "United States") countries.Add("GB", "Great Britian") countries.Add("DE", "Germany") countries.Add("AT", "Austria") countries.Add("CH", "Swiss") languages := languages.New() languages.Add("en", "English") languages.Add("de", "Germany") mappings := mappings.New() mappings.Add("en", "US", "English for the United States", nil) m0, _ := mappings.Get("en", "US") mappings.Add("en", "GB", "English for Great Britian", m0) mappings.Add("de", "DE", "German for Germany", m0) m1, _ := mappings.Get("de", "DE") mappings.Add("de", "AT", "German for Austria", m1) mappings.Add("de", "CH", "German for Switzerland", m1) translations := translations.New(mappings) translations.Add("en", "US", "hello", "hello") translations.Add("en", "US", "world", "world") translations.Add("en", "US", "unknown", "unknown") translations.Add("de", "DE", "hello", "Hallo") translations.Add("de", "AT", "hello", "Servus") translations.Add("de", "DE", "world", "Welt") i18n := New() i18n.AddLanguage("en", "English") i18n.AddLanguage("de", "German") i18n.AddCountry("US", "United States") i18n.AddCountry("GB", "Great Britian") i18n.AddCountry("DE", "Germany") i18n.AddCountry("AT", "Austria") i18n.AddCountry("CH", "Swiss") i18n.AddMapping("en", "US", "English for the United States", nil) m0, _ := i18n.GetMapping("en", "US") i18n.AddMapping("en", "GB", "English for Great Britian", m0) i18n.AddMapping("de", "DE", "German for Germany", m0) m1, _ := i18n.GetMapping("de", "DE") i18n.AddMapping("de", "AT", "German for Austria", m1) i18n.AddMapping("de", "CH", "German for Switzerland", m1) i18n.AddTranslation("en", "US", "hello", "hello") i18n.AddTranslation("en", "US", "world", "world") i18n.AddTranslation("en", "US", "unknown", "unknown") i18n.AddTranslation("de", "DE", "hello", "Hallo") i18n.AddTranslation("de", "AT", "hello", "Servus") i18n.AddTranslation("de", "DE", "world", "Welt") for _, x := range []struct { l, c, key, val string l, c, name, value string e1, e2 error }{ {l: "de", c: "AT", key: "hello", val: "Servus"}, {l: "de", c: "CH", key: "hello", val: "Hallo"}, {l: "de", c: "AT", key: "world", val: "Welt"}, {l: "de", c: "AT", key: "unknown", val: "unknown"}, {l: "xx", c: "XX", name: "hello", value: "", e1: languages.ErrorUnknownLanguage, e2: translations.ErrorNoTranslation}, {l: "en", c: "US", name: "hello", value: "hello"}, {l: "en", c: "GB", name: "hello", value: "hello"}, {l: "de", c: "AT", name: "hello", value: "Servus"}, {l: "de", c: "CH", name: "hello", value: "Hallo"}, {l: "de", c: "AT", name: "world", value: "Welt"}, {l: "de", c: "AT", name: "unknown", value: "unknown"}, } { m, _ := mappings.Get(x.l, x.c) r, _ := translations.Get(m, x.key) if strings.Compare(r, x.val) != 0 { t.Errorf("\"%s\"(%s_%s) is \"%s\", expected \"%s\"", x.key, x.l, x.c, r, x.val) _, err := i18n.SetMapping(x.l, x.c) if err != x.e1 { t.Errorf("failed to get mapping for %s/%s: %s", x.l, x.c, err) } r, err := i18n.GetTranslation(x.name) if err != x.e2 { t.Errorf("failed to get translation for %s: %s", x.name, err) } if strings.Compare(r, x.value) != 0 { t.Errorf("\"%s\"(%s_%s) is \"%s\", expected \"%s\"", x.name, x.l, x.c, r, x.value) } } } pkg/i18n/languages/languages.go +12 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ import "errors" var ( // ErrorFunctionNotImplemented is returned when a function is not implemented. ErrorFunctionNotImplemented = errors.New("function not implemented") // ErrorUnknownLanguage is returned when the language is not known. ErrorUnknownLanguage = errors.New("unknown language") ) // Languages ... Loading @@ -24,3 +26,13 @@ func (l *Languages) Add(name, description string) (bool, error) { l.data[name] = description return true, nil } // Get ... func (l *Languages) Get(name string) (bool, error) { _, valid := l.data[name] if !valid { return false, ErrorUnknownLanguage } return true, nil } pkg/i18n/mappings/mappings.go +9 −1 Original line number Diff line number Diff line package mappings import "errors" import ( "errors" "fmt" ) var ( // ErrorFunctionNotImplemented is returned when a function is not implemented. Loading Loading @@ -73,3 +76,8 @@ func (m *Mappings) GetDefault() (*Mapping, error) { } return m.base, nil } // String ... func (m *Mapping) String() string { return fmt.Sprintf("%s_%s", m.Language, m.Country) } Loading
pkg/i18n/countries/countries.go +11 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ import "errors" var ( // ErrorFunctionNotImplemented is returned when a function is not implemented. ErrorFunctionNotImplemented = errors.New("function not implemented") // ErrorUnknownCountry is returned when country is not known. ErrorUnknownCountry = errors.New("unkown country") ) // Countries holds mappings. Loading @@ -24,3 +26,12 @@ func (c *Countries) Add(country, description string) (bool, error) { c.data[country] = description return true, nil } // Get ... func (c *Countries) Get(country string) (bool, error) { _, valid := c.data[country] if !valid { return false, ErrorUnknownCountry } return true, nil }
pkg/i18n/i18n.go 0 → 100644 +120 −0 Original line number Diff line number Diff line package i18n import ( "errors" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/countries" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/languages" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/mappings" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/translations" ) var ( // ErrorNilMapping is returned when the mapping is nil. ErrorNilMapping = errors.New("mapping is nil") // ErrorNoTranslation ... ErrorNoTranslation = errors.New("no translation") // ErrorCurrentIsNil ... ErrorCurrentIsNil = errors.New("current is nil") ) // I18N ... type I18N struct { languages *languages.Languages countries *countries.Countries mappings *mappings.Mappings translations *translations.Translations standard *mappings.Mapping current *mappings.Mapping } // New ... func New() *I18N { return &I18N{ languages: languages.New(), countries: countries.New(), mappings: mappings.New(), translations: translations.New(), } } // AddCountry ... func (i18n *I18N) AddCountry(country, description string) (bool, error) { return i18n.countries.Add(country, description) } // AddLanguage ... func (i18n *I18N) AddLanguage(language, description string) (bool, error) { return i18n.languages.Add(language, description) } // AddMapping ... func (i18n *I18N) AddMapping(language, country, description string, fallback *mappings.Mapping) (bool, error) { if fallback == nil { i18n.standard = fallback } return i18n.mappings.Add(language, country, description, fallback) } // GetMapping ... func (i18n *I18N) GetMapping(language, country string) (*mappings.Mapping, error) { return i18n.mappings.Get(language, country) } // SetMapping ... func (i18n *I18N) SetMapping(language, country string) (bool, error) { if lt, lerr := i18n.languages.Get(language); !lt { return false, lerr } if ct, cerr := i18n.countries.Get(country); !ct { return false, cerr } mp, merr := i18n.GetMapping(language, country) if merr != nil { return false, merr } i18n.current = mp return true, nil } // AddTranslation ... func (i18n *I18N) AddTranslation(language, country, name, value string) (bool, error) { if lt, lerr := i18n.languages.Get(language); !lt { return false, lerr } if ct, cerr := i18n.countries.Get(country); !ct { return false, cerr } return i18n.translations.Add(language, country, name, value) } // GetTranslation ... func (i18n *I18N) GetTranslation(name string) (string, error) { if i18n.current == nil { return "", ErrorCurrentIsNil } if lt, lerr := i18n.languages.Get(i18n.current.Language); !lt { return "", lerr } if ct, cerr := i18n.countries.Get(i18n.current.Country); !ct { return "", cerr } fallback, _ := i18n.mappings.GetFallback(i18n.current.Language, i18n.current.Country) for _, m := range []*mappings.Mapping{ i18n.current, fallback, i18n.standard, } { if m == nil { continue } val, err := i18n.translations.Get(m, name) if err != nil { continue } return val, nil } return "", ErrorNoTranslation }
pkg/i18n/i18n_test.go +44 −38 Original line number Diff line number Diff line Loading @@ -4,54 +4,60 @@ import ( "strings" "testing" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/countries" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/languages" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/mappings" "repositories.muehmer.net/bsmrgo/wizards/pkg/i18n/translations" ) func TestI18N(t *testing.T) { countries := countries.New() countries.Add("US", "United States") countries.Add("GB", "Great Britian") countries.Add("DE", "Germany") countries.Add("AT", "Austria") countries.Add("CH", "Swiss") languages := languages.New() languages.Add("en", "English") languages.Add("de", "Germany") mappings := mappings.New() mappings.Add("en", "US", "English for the United States", nil) m0, _ := mappings.Get("en", "US") mappings.Add("en", "GB", "English for Great Britian", m0) mappings.Add("de", "DE", "German for Germany", m0) m1, _ := mappings.Get("de", "DE") mappings.Add("de", "AT", "German for Austria", m1) mappings.Add("de", "CH", "German for Switzerland", m1) translations := translations.New(mappings) translations.Add("en", "US", "hello", "hello") translations.Add("en", "US", "world", "world") translations.Add("en", "US", "unknown", "unknown") translations.Add("de", "DE", "hello", "Hallo") translations.Add("de", "AT", "hello", "Servus") translations.Add("de", "DE", "world", "Welt") i18n := New() i18n.AddLanguage("en", "English") i18n.AddLanguage("de", "German") i18n.AddCountry("US", "United States") i18n.AddCountry("GB", "Great Britian") i18n.AddCountry("DE", "Germany") i18n.AddCountry("AT", "Austria") i18n.AddCountry("CH", "Swiss") i18n.AddMapping("en", "US", "English for the United States", nil) m0, _ := i18n.GetMapping("en", "US") i18n.AddMapping("en", "GB", "English for Great Britian", m0) i18n.AddMapping("de", "DE", "German for Germany", m0) m1, _ := i18n.GetMapping("de", "DE") i18n.AddMapping("de", "AT", "German for Austria", m1) i18n.AddMapping("de", "CH", "German for Switzerland", m1) i18n.AddTranslation("en", "US", "hello", "hello") i18n.AddTranslation("en", "US", "world", "world") i18n.AddTranslation("en", "US", "unknown", "unknown") i18n.AddTranslation("de", "DE", "hello", "Hallo") i18n.AddTranslation("de", "AT", "hello", "Servus") i18n.AddTranslation("de", "DE", "world", "Welt") for _, x := range []struct { l, c, key, val string l, c, name, value string e1, e2 error }{ {l: "de", c: "AT", key: "hello", val: "Servus"}, {l: "de", c: "CH", key: "hello", val: "Hallo"}, {l: "de", c: "AT", key: "world", val: "Welt"}, {l: "de", c: "AT", key: "unknown", val: "unknown"}, {l: "xx", c: "XX", name: "hello", value: "", e1: languages.ErrorUnknownLanguage, e2: translations.ErrorNoTranslation}, {l: "en", c: "US", name: "hello", value: "hello"}, {l: "en", c: "GB", name: "hello", value: "hello"}, {l: "de", c: "AT", name: "hello", value: "Servus"}, {l: "de", c: "CH", name: "hello", value: "Hallo"}, {l: "de", c: "AT", name: "world", value: "Welt"}, {l: "de", c: "AT", name: "unknown", value: "unknown"}, } { m, _ := mappings.Get(x.l, x.c) r, _ := translations.Get(m, x.key) if strings.Compare(r, x.val) != 0 { t.Errorf("\"%s\"(%s_%s) is \"%s\", expected \"%s\"", x.key, x.l, x.c, r, x.val) _, err := i18n.SetMapping(x.l, x.c) if err != x.e1 { t.Errorf("failed to get mapping for %s/%s: %s", x.l, x.c, err) } r, err := i18n.GetTranslation(x.name) if err != x.e2 { t.Errorf("failed to get translation for %s: %s", x.name, err) } if strings.Compare(r, x.value) != 0 { t.Errorf("\"%s\"(%s_%s) is \"%s\", expected \"%s\"", x.name, x.l, x.c, r, x.value) } } }
pkg/i18n/languages/languages.go +12 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ import "errors" var ( // ErrorFunctionNotImplemented is returned when a function is not implemented. ErrorFunctionNotImplemented = errors.New("function not implemented") // ErrorUnknownLanguage is returned when the language is not known. ErrorUnknownLanguage = errors.New("unknown language") ) // Languages ... Loading @@ -24,3 +26,13 @@ func (l *Languages) Add(name, description string) (bool, error) { l.data[name] = description return true, nil } // Get ... func (l *Languages) Get(name string) (bool, error) { _, valid := l.data[name] if !valid { return false, ErrorUnknownLanguage } return true, nil }
pkg/i18n/mappings/mappings.go +9 −1 Original line number Diff line number Diff line package mappings import "errors" import ( "errors" "fmt" ) var ( // ErrorFunctionNotImplemented is returned when a function is not implemented. Loading Loading @@ -73,3 +76,8 @@ func (m *Mappings) GetDefault() (*Mapping, error) { } return m.base, nil } // String ... func (m *Mapping) String() string { return fmt.Sprintf("%s_%s", m.Language, m.Country) }