🌍 一个专为 Gin 框架设计的开箱即用多语言库,提供高性能、易集成、生产就绪的国际化解决方案。
- 🚀 开箱即用 - 3行代码完成集成,零配置启动
 - ⚡ 高性能 - 多层缓存 + 对象池,响应时间 < 0.1ms
 - 🛡️ 生产就绪 - 完善的错误处理和降级机制
 - 🔥 热更新 - 无需重启,动态加载语言文件 (可选)
 - 📊 监控友好 - 内置性能指标和调试支持
 - 🌐 多语言检测 - Header、Cookie、Query、Accept-Language 多种方式
 - 🎯 零侵入 - 标准 Gin 中间件,完全兼容现有代码
 - 📝 统一响应 - 内置多语言响应码系统
 
go get github.com/chenguowei/go-i18n@latestpackage main
import (
    "github.com/gin-gonic/gin"
    i18n "github.com/chenguowei/go-i18n"
)
func main() {
    // 1. 初始化 i18n (使用默认配置)
    // 注意:默认配置会自动加载内置错误码,无需额外初始化
    if err := i18n.Init(); err != nil {
        panic(err)
    }
    // 2. 创建 Gin 路由并添加中间件
    r := gin.Default()
    r.Use(i18n.Middleware())
    // 3. 使用翻译和统一响应
    r.GET("/hello", func(c *gin.Context) {
        name := c.DefaultQuery("name", "World")
        // 翻译消息
        message := i18n.TFromGin(c, "WELCOME_MESSAGE", map[string]interface{}{
            "name": name,
        })
        // 统一响应格式
        i18n.SuccessResponse(c, map[string]interface{}{
            "message": message,
            "lang":    i18n.GetLanguageFromGin(c),
        })
    })
    r.Run(":8080")
}package main
import (
    "time"
    "github.com/gin-gonic/gin"
    i18n "github.com/chenguowei/go-i18n"
)
func main() {
    // 自定义配置
    config := i18n.Config{
        DefaultLanguage:  "zh-CN",
        FallbackLanguage: "en",
        LocalesPath:      "./locales",
        // 语言文件配置
        LocaleConfig: i18n.LocaleConfig{
            Mode:      "flat", // 支持 "flat" 或 "nested"
            Languages: []string{"en", "zh-CN", "zh-TW", "ja"},
        },
        // 缓存配置
        Cache: i18n.CacheConfig{
            Enable:     true,
            Size:       5000,
            TTL:        int64((2 * time.Hour).Seconds()),
            L2Size:     10000,
            EnableFile: false,
        },
        // 对象池配置
        Pool: i18n.PoolConfig{
            Enable:    true,
            Size:      200,
            WarmUp:    true,
            Languages: []string{"en", "zh-CN", "zh-TW", "ja"},
        },
        // 调试和监控
        Debug:         true,
        EnableMetrics: true,
        EnableWatcher: true, // 热更新
    }
    // 使用自定义配置初始化
    // 注意:默认配置会自动加载内置错误码,自定义配置也会自动初始化响应码系统
    if err := i18n.InitWithConfig(config); err != nil {
        panic(err)
    }
    r := gin.Default()
    // 自定义中间件选项
    middlewareOpts := i18n.DefaultMiddlewareOptions
    middlewareOpts.SupportedLangs = []string{"en", "zh-CN", "zh-TW", "ja"}
    middlewareOpts.EnableCookie = true
    middlewareOpts.EnableQuery = true
    r.Use(i18n.MiddlewareWithOpts(middlewareOpts))
    // 业务路由
    r.GET("/api/user/:id", getUserHandler)
    r.POST("/api/user", createUserHandler)
    r.Run(":8080)
}
func getUserHandler(c *gin.Context) {
    userID := c.Param("id")
    if userID == "404" {
        // 使用模板参数的错误响应
        i18n.JSONWithTemplate(c, i18n.UserNotFound, nil, map[string]interface{}{
            "userID": userID,
        })
        return
    }
    i18n.SuccessResponse(c, map[string]interface{}{
        "id":   userID,
        "name": "John Doe",
        "lang": i18n.GetLanguageFromGin(c),
    })
}
func createUserHandler(c *gin.Context) {
    // 创建用户逻辑...
    i18n.SuccessResponse(c, map[string]interface{}{
        "message": i18n.TFromGin(c, "USER_CREATED"),
        "id":      "12345",
    })
}在 locales/ 目录下创建 JSON 格式的语言文件:
locales/en.json
[
  {
    "id": "WELCOME_MESSAGE",
    "translation": "Hello, {{.name}}!"
  },
  {
    "id": "USER_CREATED",
    "translation": "User created successfully"
  },
  {
    "id": "USER_NOT_FOUND",
    "translation": "User with ID {{.userID}} not found"
  },
  {
    "id": "INVALID_PARAM",
    "translation": "Invalid parameters provided"
  }
]locales/zh-CN.json
[
  {
    "id": "WELCOME_MESSAGE",
    "translation": "你好,{{.name}}!"
  },
  {
    "id": "USER_CREATED",
    "translation": "用户创建成功"
  },
  {
    "id": "USER_NOT_FOUND",
    "translation": "ID为{{.userID}}的用户未找到"
  },
  {
    "id": "INVALID_PARAM",
    "translation": "提供的参数无效"
  }
]locales/zh-TW.json
[
  {
    "id": "WELCOME_MESSAGE",
    "translation": "你好,{{.name}}!"
  },
  {
    "id": "USER_CREATED",
    "translation": "用戶創建成功"
  },
  {
    "id": "USER_NOT_FOUND",
    "translation": "ID為{{.userID}}的用戶未找到"
  },
  {
    "id": "INVALID_PARAM",
    "translation": "提供的參數無效"
  }
]库支持多种语言检测方式,按优先级顺序:
- Header: 
X-Language: zh-CN - Cookie: 
lang=zh-CN - Query Parameter: 
?lang=zh-CN - Accept-Language: 
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 - Default: 配置的默认语言
 
# 通过 Header 指定语言
curl -H "X-Language: zh-CN" http://localhost:8080/api/hello
# 通过 Cookie 指定语言
curl -b "lang=zh-CN" http://localhost:8080/api/hello
# 通过 Query 参数指定语言
curl "http://localhost:8080/api/hello?lang=zh-CN"
# 使用 Accept-Language
curl -H "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8" http://localhost:8080/api/hello库提供了统一的响应系统,支持多语言错误消息:
{
  "code": 0,
  "message": "操作成功",
  "data": {...},
  "meta": {
    "timestamp": "2025-10-30T10:30:00Z",
    "language": "zh-CN",
    "request_id": "req-123",
    "trace_id": "trace-456"
  }
}// 成功响应
i18n.SuccessResponse(c, data)
// 错误响应
i18n.Error(c, i18n.InvalidParam)
i18n.JSONWithTemplate(c, i18n.UserNotFound, nil, map[string]interface{}{
    "userID": userID,
})
// 自定义响应
i18n.JSON(c, customCode, data)
i18n.JSONWithStatus(c, customCode, data, http.StatusBadRequest)
// 分页响应
i18n.ListResponse(c, i18n.Success, items, total, page, perPage)default_language: "en"
fallback_language: "en"
locales_path: "locales"
locale_config:
  mode: "flat"
  languages: ["en", "zh-CN", "zh-TW"]
response_config:
  load_builtin: true
  auto_init: true
cache:
  enable: true
  size: 1000
  ttl: 3600
  l2_size: 5000
  enable_file: false
pool:
  enable: true
  size: 100
  warm_up: true
  languages: ["en", "zh-CN", "zh-TW"]
debug: false
enable_metrics: false
enable_watcher: false支持通过环境变量覆盖配置:
export I18N_DEFAULT_LANGUAGE="zh-CN"
export I18N_DEBUG="true"
export I18N_ENABLE_METRICS="true"
export I18N_CACHE_SIZE="5000"
export I18N_POOL_SIZE="200"// 从 YAML 文件加载配置
err := i18n.InitFromConfigFile("config/i18n.yaml")
if err != nil {
    log.Fatalf("Failed to load i18n config: %v", err)
}
// 或者手动加载配置
config, err := i18n.LoadConfigFromFile("config/i18n.yaml")
if err != nil {
    log.Fatalf("Failed to load config file: %v", err)
}
// 验证配置
err = i18n.InitWithConfig(config)
if err != nil {
    log.Fatalf("Failed to initialize i18n: %v", err)
}// 自定义中间件选项
opts := i18n.MiddlewareOptions{
    HeaderKey:      "X-Language",           // 自定义 Header 键
    CookieName:     "lang",                  // 自定义 Cookie 名称
    QueryKey:       "lang",                  // 自定义查询参数键
    SupportedLangs: []string{"en", "zh-CN"}, // 支持的语言列表
    EnableCookie:   true,                    // 启用 Cookie 检测
    EnableQuery:    true,                    // 启用查询参数检测
}
r.Use(i18n.MiddlewareWithOpts(opts))- L1 缓存: 内存缓存,最快访问
 - L2 缓存: LRU 缓存,自动淘汰
 - 对象池: Localizer 对象复用,减少内存分配
 
// 启用调试模式
config := i18n.Config{
    Debug:         true,  // 启用详细日志
    EnableMetrics: true,  // 启用性能指标
}
// 获取统计信息
stats := i18n.GetStats()
metrics := i18n.GetMetrics()
// 热更新
config.EnableWatcher = trueconfig := i18n.Config{
    EnableWatcher: true,  // 启用文件监听
}
// 手动重新加载
i18n.Reload()// 从 Gin Context 翻译(推荐使用)
message := i18n.TFromGin(c, "WELCOME", data)
// 从 context.Context 翻译
message := i18n.T(ctx, "WELCOME", data)
// 使用指定语言翻译
message := i18n.GetService().TranslateWithLanguage(ctx, "zh-CN", "WELCOME", data)
// 获取当前语言
lang := i18n.GetLanguageFromGin(c)
lang = i18n.GetLanguage(ctx)// 语言文件中定义复数形式
{
  "ITEMS_COUNT": {
    "one": "{{.count}} item",
    "other": "{{.count}} items"
  }
}
// 使用复数翻译
message := i18n.GetService().Pluralize(ctx, "ITEMS_COUNT", count, data)查看 examples/ 目录中的完整示例:
- quickstart - 基础使用示例
 - nested - 嵌套模式示例
 - custom-codes - 自定义错误码示例
 - http-status-codes - HTTP 状态码示例
 - hybrid-codes - 混合错误码示例
 
运行示例:
cd examples/quickstart
go run main.go欢迎提交 Issue 和 Pull Request!
# 克隆仓库
git clone https://github.com/chenguowei/go-i18n.git
cd go-i18n
# 安装依赖
go mod download
# 运行测试
go test ./...
# 运行示例
go run examples/quickstart/main.go- Fork 项目
 - 创建特性分支 (
git checkout -b feature/amazing-feature) - 提交更改 (
git commit -m 'Add amazing feature') - 推送到分支 (
git push origin feature/amazing-feature) - 创建 Pull Request
 
本项目采用 MIT 许可证 - 详见 LICENSE 文件。
# 检查语言文件格式是否正确(必须是数组格式)
cat locales/en.json
# 检查文件路径是否正确
ls -la locales/
# 启用调试模式查看详细日志
export I18N_DEBUG=true
go run main.go# 检查环境变量设置
env | grep I18N_
# 检查配置文件格式
go run main.go 2>&1 | grep -i error
# 验证配置内容
I18N_DEBUG=true go run main.go// 在代码中添加调试信息
lang := i18n.GetLanguageFromGin(c)
fmt.Printf("Current language: %s\n", lang)
message := i18n.TFromGin(c, "YOUR_MESSAGE_ID")
fmt.Printf("Translation result: %s\n", message)// 确保已初始化响应码系统
if err := i18n.Init(); err != nil {
    log.Fatal("Failed to initialize i18n:", err)
}
// 检查错误码是否定义
func errorHandler(c *gin.Context) {
    // 使用内置错误码,确保已定义
    i18n.Error(c, i18n.UserNotFound)
}config := i18n.Config{
    Debug:         true,  // 启用调试日志
    EnableMetrics: true,  // 启用性能指标
}// 获取统计信息
stats := i18n.GetStats()
fmt.Printf("Cache stats: %+v\n", stats)
// 获取性能指标
metrics := i18n.GetMetrics()
fmt.Printf("Performance metrics: %+v\n", metrics)# 测试不同语言检测方式
curl -H "X-Language: zh-CN" http://localhost:8080/api/test
curl -b "lang=zh-CN" http://localhost:8080/api/test
curl "http://localhost:8080/api/test?lang=zh-CN"
curl -H "Accept-Language: zh-CN,zh;q=0.9" http://localhost:8080/api/test| 错误类型 | 错误码 | 常见原因 | 解决方案 | 
|---|---|---|---|
| 配置错误 | panic | 配置文件格式错误 | 检查 YAML 语法 | 
| 文件未找到 | - | 语言文件路径错误 | 检查文件路径和权限 | 
| 翻译失败 | messageID | 语言文件中无对应翻译 | 检查 messageID 拼写 | 
| 初始化失败 | - | 依赖或配置问题 | 检查 go.mod 和配置 | 
- nicksnyder/go-i18n - 核心 i18n 引擎
 - gin-gonic/gin - 优秀的 Web 框架
 - fsnotify - 文件监听库