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/README.md

136 lines
4.4 KiB

# i18n Example
This project is an demo for i18n usage.
We integrated [go-i18n](https://github.com/nicksnyder/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.
```bash
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:
```go
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.
```go
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
```bash
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:
```bash
touch tranlate.zh.toml
```
Then fill the translate file:
```bash
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
```bash
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](https://github.com/nicksnyder/go-i18n) You could refer to this repository for more detailed document.