nicksnyder / go-i18n

Translate your Go program into multiple languages.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Easy wrapper around this library

amitavaghosh1 opened this issue · comments

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.

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
}