Skip to content

Add translation example #1394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

cxlblm
Copy link

@cxlblm cxlblm commented Mar 7, 2025

No description provided.

@cxlblm cxlblm requested a review from a team as a code owner March 7, 2025 02:51
@coveralls
Copy link

coveralls commented Mar 7, 2025

Coverage Status

coverage: 73.653% (+0.05%) from 73.607%
when pulling 6b3ea1d on cxlblm:translation
into 0540a5e on go-playground:master.

// The supported locales need to be predefined.
enTrans, _ := uni.GetTranslator("en")
en_translations.RegisterDefaultTranslations(validate, enTrans)
zhTrans, _ := uni.GetTranslator("zh")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution to the project.

Where is zhTrans being used?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution to the project.

Where is zhTrans being used?

The variable zhTrans exists to register the global Chinese translator using zh_translations.RegisterDefaultTranslations(validate, zhTrans). This is done to ensure that both English (en) and Chinese (zh) can be supported in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm....
When I execute this example, the Chinese translation doesn't appear.

$ cd _examples/translations && go run main.go
map[User.Tagline:Tagline must be less than 10 characters in length User.Tagline2:Tagline2 must be greater than 1 character in length]
Username is a required field
Username must have a value!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.... When I execute this example, the Chinese translation doesn't appear.

$ cd _examples/translations && go run main.go
map[User.Tagline:Tagline must be less than 10 characters in length User.Tagline2:Tagline2 must be greater than 1 character in length]
Username is a required field
Username must have a value!

The purpose of en_translations.RegisterDefaultTranslations(validate, enTrans) and zh_translations.RegisterDefaultTranslations(validate, zhTrans) is to pre-register all supported languages. However, the specific language to be used is determined by the accept-language in the HTTP header. For simplicity, a fixed value (uni.GetTranslator("en")) is hardcoded in the code. Below is a demo from our real-world scenario.

package main

import (
	"encoding/json"
	"errors"
	"github.com/go-playground/locales/en"
	"github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	en_translations "github.com/go-playground/validator/v10/translations/en"
	zh_translations "github.com/go-playground/validator/v10/translations/zh"
	"net/http"
)

var uni *ut.UniversalTranslator

func main() {
	validate := validator.New()
	en := en.New()
	uni = ut.New(en, en, zh.New())

	validate = validator.New()
	enTrans, _ := uni.GetTranslator("en")
	en_translations.RegisterDefaultTranslations(validate, enTrans)
	zhTrans, _ := uni.GetTranslator("zh")
	zh_translations.RegisterDefaultTranslations(validate, zhTrans)

	type User struct {
		FirstName string `json:"first_name" validate:"required"`
		LastName  string `json:"last_name" validate:"required"`
	}

	http.HandleFunc("POST /users", func(w http.ResponseWriter, r *http.Request) {
		// ... fill user value
		var user User

		// Header Accept-Language value is en or zh
		trans, _ := uni.GetTranslator(r.Header.Get("Accept-Language"))
		if err := validate.Struct(&user); err != nil {
			var errs validator.ValidationErrors
			var httpErrors []validator.ValidationErrorsTranslations
			if errors.As(err, &errs) {
				httpErrors = append(httpErrors, errs.Translate(trans))
			}
			r, _ := json.Marshal(httpErrors)
			w.Write(r)
		}
	})

	http.ListenAndServe(":8081", nil)
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ☝️ type of example is highly valuable. I’d include it in this PR as a separate function, possibly with a client http request that sets the Accept-Language header to 'zh'.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried executing your example, but it resulted in the following error:

main.go:8:2: cannot find module providing package github.com/go-playground/locales/zh_Hant:

Would you be able to fix it?

Could you provide the execution environment? It works fine on my local machine. Could you also check whether the relevant packages are present?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you go:

$ git clean -ffdx
$ go mod vendor
$ cd _examples/http-transalations 
$ go run main.go
main.go:8:2: cannot find module providing package github.com/go-playground/locales/zh_Hant

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you go:

$ git clean -ffdx
$ go mod vendor
$ cd _examples/http-transalations 
$ go run main.go
main.go:8:2: cannot find module providing package github.com/go-playground/locales/zh_Hant

I pinpointed the issue and found that the dependency related to zh_Hant wasn't included during compilation, which caused go mod vendor to skip copying the relevant dependencies into the vendor directory. I’ve adjusted the dependencies accordingly. However, I’m curious—what's the purpose of using the go mod vendor command in the first place?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4a3f92e fixes the dependency issue. I'm able to run your example.

How can I see the localized error message?
I attempted a POST request, but it returned the following output:

curl -d '{"first_name":"foo"}' -H "Accept-Language: zh-TW" -H "Content-Type: application/json" -X POST http://localhost:8081/users

[{"User.FirstName":"FirstName is a required field","User.LastName":"LastName is a required field"}]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4a3f92e fixes the dependency issue. I'm able to run your example.

How can I see the localized error message? I attempted a POST request, but it returned the following output:

curl -d '{"first_name":"foo"}' -H "Accept-Language: zh-TW" -H "Content-Type: application/json" -X POST http://localhost:8081/users

[{"User.FirstName":"FirstName is a required field","User.LastName":"LastName is a required field"}]

You can use the following command to get error messages in Traditional Chinese:

curl -d '{"first_name":"foo"}' -H "Accept-Language: zh-Hant-TW" -H "Content-Type: application/json" -X POST http://localhost:8081/users

Or use this command to get messages in Simplified Chinese:

curl -d '{"first_name":"foo"}' -H "Accept-Language: zh" -H "Content-Type: application/json" -X POST http://localhost:8081/users

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants