nicksnyder / go-i18n

Translate your Go program into multiple languages.
MIT License
2.88k stars 268 forks source link

Easy wrapper around this library #292

Open amitavaghosh1 opened 1 year ago

amitavaghosh1 commented 1 year ago

Obviously the examples provided are way to descriptive for a real world use. With already so much code we have to write in go, I don't think, I would like to see 10 line implementations per localized string.

Here is an example wrapper you can use . Please feel free to improve it.

package locales

import (
    "encoding/json"
    "fmt"
    "strings"

    "github.com/nicksnyder/go-i18n/v2/i18n"
    "golang.org/x/text/language"
)

type Localizer struct {
    bundle *i18n.Bundle
}

var localizer Localizer

func NewLocalizer(path string, languages ...string) Localizer {
    path = strings.TrimSuffix(path, "/")

    bundle := i18n.NewBundle(language.English)
    bundle.RegisterUnmarshalFunc("json", json.Unmarshal)

    for _, lang := range languages {
        bundle.MustLoadMessageFile(fmt.Sprintf("%s/translations/%s.json", path, lang))
    }

    return Localizer{bundle: bundle}
}

func (l Localizer) Get(lang string, id string) string {
    localizer := i18n.NewLocalizer(l.bundle, lang)

    cfg := &i18n.LocalizeConfig{
        DefaultMessage: &i18n.Message{
            ID:    id,
            Other: id,
            One:   id,
        },
    }

    str, err := localizer.Localize(cfg)
    if err != nil {
        return id
    }

    return str
}

func (l Localizer) GetWithData(lang, id string, data map[string]interface{}) string {
    localizer := i18n.NewLocalizer(l.bundle, lang)

    cfg := &i18n.LocalizeConfig{
        DefaultMessage: &i18n.Message{
            ID:    id,
            Other: id,
        },
        TemplateData: data,
    }
    str, err := localizer.Localize(cfg)
    if err != nil {
        return id
    }

    return str
}

and use it as such

lc := locales.NewLocalizer(dotConfig.LocaleRootPath, "en", "es")

fmt.Println(lc.Get("en", "time_up"))
fmt.Println(lc.Get("es", "time_up"))
fmt.Println(lc.Get("es", "time up"))

translations/en.json

{
    "time_up": "Retry limit exceeded"
}

translations/es.json

{
    "time_up": "demasiados reintentos"
}

The immediate improvement is to make sure, the languages exists.

brutalzinn commented 5 months ago

Thanks for this. Saved me a lot of time. A small contribute to take more advantage of distribuition of wrapper between modules:


type Localizer struct {
    bundle *i18n.Bundle
}

var defaultLang = "pt"

var localizer Localizer

func NewLocalizer(languages ...string) Localizer {
    path, err := os.Getwd()
    if err != nil {
        panic("error on get Getwd")
    }

    bundle := i18n.NewBundle(language.English)
    bundle.RegisterUnmarshalFunc("json", json.Unmarshal)

    for _, lang := range languages {
        bundle.MustLoadMessageFile(fmt.Sprintf("%s/translations/%s.json", path, lang))
    }

    localizer = Localizer{bundle: bundle}
    return localizer
}

func Get(id string) string {
    return localizer.get(defaultLang, id)
}

func GetWithData(id string, data map[string]any) string {
    return localizer.getWithData(defaultLang, id, data)
}

func (l Localizer) get(lang string, id string) string {
    localizer := i18n.NewLocalizer(l.bundle, lang)

    cfg := &i18n.LocalizeConfig{
        DefaultMessage: &i18n.Message{
            ID:    id,
            Other: id,
            One:   id,
        },
    }

    str, err := localizer.Localize(cfg)
    if err != nil {
        return id
    }
    return str
}

func (l Localizer) getWithData(lang, id string, data map[string]any) string {
    localizer := i18n.NewLocalizer(l.bundle, lang)

    cfg := &i18n.LocalizeConfig{
        DefaultMessage: &i18n.Message{
            ID:    id,
            Other: id,
        },
        TemplateData: data,
    }
    str, err := localizer.Localize(cfg)
    if err != nil {
        return id
    }

    return str
}