You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
kratos/examples/i18n
songzhibin97 8c9e70b47b
style: format (#1667)
3 years ago
..
api/helloworld/v1 feat(examples/i18n) add i18n example (#1157) 3 years ago
cmd/i18n style: format (#1667) 3 years ago
configs feat(examples/i18n) add i18n example (#1157) 3 years ago
internal fix: examples lint error (#1454) 3 years ago
third_party feat(examples/i18n) add i18n example (#1157) 3 years ago
.gitignore feat(examples/i18n) add i18n example (#1157) 3 years ago
Dockerfile feat(examples/i18n) add i18n example (#1157) 3 years ago
LICENSE feat(examples/i18n) add i18n example (#1157) 3 years ago
Makefile feat(examples/i18n) add i18n example (#1157) 3 years ago
README.md feat(examples/i18n) add i18n example (#1157) 3 years ago
active.en.toml feat(examples/i18n) add i18n example (#1157) 3 years ago
active.zh.toml feat(examples/i18n) add i18n example (#1157) 3 years ago
generate.go feat(examples/i18n) add i18n example (#1157) 3 years ago

README.md

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.