Skip to content

Latest commit

 

History

History
 
 

i18n

i18n Example

This project is an demo for i18n usage. We integrated go-i18n into our project for localization.

We start with the project generate with kratos-layout, you could use kratos new to generate it.

The following steps are applied.

Step 1: install

Install the cli tool goi18n and the package.

go get -u github.com/nicksnyder/go-i18n/v2/goi18n
go get -u github.com/nicksnyder/go-i18n

Step 2: implement and register the middleware

There's a middleware in internal/pkg/middleware/localize, we implement this middleware, and register it into our http server in internal/server/http.go. We init the bundle and load our translation file(we will generate it later). For convenience, we hard-coded the translation file path here, you should avoid it in your project :)

Also the middleware will extract accept-language header from our request, then set the correct localizer to the context. In our service request handler, we can use the FromContext method to get this localizer for localization.

This middleware is so simple that we can show it as following:

package localize

import (
	"context"
	"github.com/BurntSushi/toml"
	"github.com/nicksnyder/go-i18n/v2/i18n"
	"golang.org/x/text/language"

	"github.com/go-kratos/kratos/v2/middleware"
	"github.com/go-kratos/kratos/v2/transport"
)

type localizerKey struct{}

func I18N() middleware.Middleware {
	bundle := i18n.NewBundle(language.English)
	bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
	bundle.MustLoadMessageFile("../../active.zh.toml")

	return func(handler middleware.Handler) middleware.Handler {
		return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
			if tr, ok := transport.FromServerContext(ctx); ok {
				accept := tr.Header().Get("accept-language")
				println(accept)
				localizer := i18n.NewLocalizer(bundle, accept)
				ctx = context.WithValue(ctx, localizerKey{}, localizer)
			}
			return handler(ctx, req)
		}
	}
}

func FromContext(ctx context.Context) *i18n.Localizer {
	return ctx.Value(localizerKey{}).(*i18n.Localizer)
}

Step 3:

Write our request handler code. In internal/service/greeter.go, we use localize.FromContext(ctx) to get the localizer, and write the string for localizing. You should write your message with golang template syntax. Notice that both One and Other fields must be filled or you will get an panic on translation file generation with goi18n tool.

func (s *GreeterService) SayHello(ctx context.Context, in *v1.HelloRequest) (*v1.HelloReply, error) {
	s.log.WithContext(ctx).Infof("SayHello Received: %v", in.GetName())

	if in.GetName() == "error" {
		return nil, v1.ErrorUserNotFound("user not found: %s", in.GetName())
	}
	localizer := localize.FromContext(ctx)
	helloMsg, err := localizer.Localize(&i18n.LocalizeConfig{
		DefaultMessage: &i18n.Message{
			Description: "sayhello",
			ID:    "sayHello",
			One:   "Hello {{.Name}}",
			Other: "Hello {{.Name}}",
		},
		TemplateData: map[string]interface{}{
			"Name": in.Name,
		},
	})
	if err != nil {
		return nil, err
	}
	return &v1.HelloReply{Message: helloMsg}, nil
}

Step 3: Generate and translate

In the root of this project, generate active.en.toml with

goi18n extract

The string which should be translated will be extracted from your code, and write into active.en.toml You should create the empty target language file:

touch tranlate.zh.toml

Then fill the translate file:

goi18n merge active.en.toml translate.zh.toml

You should edit the translate.zh.toml to finish the translation work. We translate Hello to 你好 in Chinese. After that, you should rename this file to active.zh.toml And this file is the translation file that we load in the Step 2. You could also embed these translation files into your binaries for easier deployment.

Step 4: Run

Go to cmd/i18n/, and run go run . to start the service.

You could try with curl with Accept-Language header

curl "http://localhost:8000/helloworld/eric" \
     -H 'Accept-Language: zh-CN'

Will get the Chinese result {"message":"你好 eric"}

And if no header:

curl "http://localhost:8000/helloworld/eric"

Will get the default English result {"message":"Hello eric"}

Reference

  • go-i18n You could refer to this repository for more detailed document.