【Validator】universal-translator,实现动态多语言切换,go案例根据Accept-Language 动态设置 locale

代码实现

根据 locale 设置动态语言翻译,具体包括初始化翻译器、注册多语言翻译规则、动态选择语言、以及输出本地化错误提示。

package validate

import (
	"errors"
	"fmt"

	"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"
	enTranslations "github.com/go-playground/validator/v10/translations/en"
	zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)

var validate = validator.New()
var uni *ut.UniversalTranslator

func LocalizedValidation() {
	// 初始化支持语言
	en := en.New()
	zh := zh.New()
	uni = ut.New(en, zh) // 初始化翻译器支持中英文
	locale := "zh"       // 动态设置语言,可从配置或用户选择中获取

	// 根据 locale 获取翻译器
	trans, _ := uni.GetTranslator(locale)
	switch locale {
	case "en":
		enTranslations.RegisterDefaultTranslations(validate, trans)
	case "zh":
		zhTranslations.RegisterDefaultTranslations(validate, trans)
	default:
		fmt.Println("Unsupported locale, defaulting to English")
		enTranslations.RegisterDefaultTranslations(validate, trans)
	}

	// 定义需要验证的结构体
	type User struct {
		Name  string `validate:"required"`     // 必填字段
		Email string `validate:"required,email"` // 必填且必须是邮箱格式
	}
	user := User{}

	// 验证结构体
	err := validate.Struct(user)
	if err != nil {
		var validationErrors validator.ValidationErrors
		if errors.As(err, &validationErrors) {
			for _, e := range validationErrors {
				// 输出本地化的错误提示信息
				fmt.Println(e.Translate(trans))
			}
		}
	}
}

核心功能点

功能模块 关键代码/方法 描述
初始化翻译器 ut.New(en, zh) 支持多种语言的翻译器初始化。
动态语言选择 uni.GetTranslator(locale) 根据用户 locale 设置动态语言翻译。
注册翻译规则 enTranslations.RegisterDefaultTranslations 为不同语言注册默认验证规则翻译。
捕获验证错误 validator.ValidationErrors 验证失败时,捕获错误信息。
本地化错误输出 FieldError.Translate(trans) 将错误翻译为用户指定语言的提示信息。

运行效果示例

  • 输入

    User{
        Name:  "",
        Email: "invalid-email",
    }
    
  • 输出locale = "zh"

    Name 为必填字段
    Email 必须是一个有效的邮箱地址
    
  • 输出locale = "en"

    Name is a required field
    Email must be a valid email address
    

根据Accept-Language 动态设置 locale

package main

import (
	"errors"
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"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"
	enTranslations "github.com/go-playground/validator/v10/translations/en"
	zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)

var validate = validator.New()
var uni *ut.UniversalTranslator

// 初始化翻译器支持的语言
func initTranslator() {
	en := en.New()
	zh := zh.New()
	uni = ut.New(en, zh)
}

// 动态获取 locale 并设置翻译器
func getTranslator(c *gin.Context) ut.Translator {
	// 获取请求头的 Accept-Language
	lang := c.GetHeader("Accept-Language")
	if lang == "" {
		lang = "en" // 默认语言
	}

	// 提取主语言部分(如 zh-CN 取 zh)
	lang = strings.Split(lang, ",")[0]
	lang = strings.Split(lang, "-")[0]

	// 获取对应的 Translator
	trans, _ := uni.GetTranslator(lang)
	switch lang {
	case "en":
		enTranslations.RegisterDefaultTranslations(validate, trans)
	case "zh":
		zhTranslations.RegisterDefaultTranslations(validate, trans)
	default:
		// 如果不支持该语言,默认使用英文
		trans, _ = uni.GetTranslator("en")
		enTranslations.RegisterDefaultTranslations(validate, trans)
	}
	return trans
}

// 定义需要验证的结构体
type User struct {
	Name  string `validate:"required"`
	Email string `validate:"required,email"`
}

func main() {
	initTranslator()

	r := gin.Default()

	r.POST("/validate", func(c *gin.Context) {
		// 动态获取翻译器
		trans := getTranslator(c)

		// 从请求体解析用户数据
		var user User
		if err := c.ShouldBindJSON(&user); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
			return
		}

		// 验证结构体
		err := validate.Struct(user)
		if err != nil {
			var validationErrors validator.ValidationErrors
			if errors.As(err, &validationErrors) {
				// 收集本地化错误信息
				errorMessages := make([]string, len(validationErrors))
				for i, e := range validationErrors {
					errorMessages[i] = e.Translate(trans)
				}
				c.JSON(http.StatusBadRequest, gin.H{"errors": errorMessages})
				return
			}
		}

		// 验证成功
		c.JSON(http.StatusOK, gin.H{"message": "Validation passed!"})
	})

	// 启动服务
	r.Run(":8080")
}


核心步骤
  1. 初始化翻译器
  • 使用 ut.New() 初始化支持的语言翻译器(如英文 en 和中文 zh)。
  1. 从请求头获取 Accept-Language
  • 提取用户请求中的 Accept-Language,如 zh-CNen-US,并解析主语言部分(zhen)。
  1. 动态注册翻译规则
  • 根据解析出的语言动态注册相应的翻译规则(enTranslationszhTranslations)。
  1. 结构体验证
  • 使用 validator 验证用户提交的数据,捕获验证错误。
  1. 本地化错误输出
  • 将验证错误信息翻译为用户选择的语言,并返回给前端。

测试效果

请求 1:语言为中文
  • 请求头
  Accept-Language: zh-CN
  • 请求体
  {
    "Name": "",
    "Email": "invalid-email"
  }
  • 响应
  {
    "errors": [
      "Name 为必填字段",
      "Email 必须是一个有效的邮箱地址"
    ]
  }
请求 2:语言为英文
  • 请求头
  Accept-Language: en-US
  • 请求体
  {
    "Name": "",
    "Email": "invalid-email"
  }
  • 响应
  {
    "errors": [
      "Name is a required field",
      "Email must be a valid email address"
    ]
  }
请求 3:语言为空(默认英文)
  • 请求头
  Accept-Language: 
  • 请求体
  {
    "Name": "",
    "Email": "invalid-email"
  }
  • 响应
  {
    "errors": [
      "Name is a required field",
      "Email must be a valid email address"
    ]
  }

https://github.com/0voice

你可能感兴趣的:(golang,开发语言,后端)