Iris 未内置 i18n 因其定位为高性能 HTTP/2 框架,坚持“功能丰富但不强耦合”设计哲学,将多语言等业务层能力交由用户按需集成;官方不提供 app.I18n() 或 iris.I18n 类型,任何称其原生支持多语言的说法均属错误。

Iris 本身不内置 i18n 支持,必须手动集成第三方库(如 go-i18n 或 golang.org/x/text),且需自行绑定到 iris.Context 生命周期中。
为什么 Iris 没有开箱即用的 i18n?
Iris 定位是「高性能 HTTP/2 Web 框架」,核心聚焦路由、中间件、上下文和响应控制。它的设计哲学是「功能丰富但不强耦合」——像 i18n 这类业务逻辑层能力,官方明确交由用户按需选型集成。这和 Beego 内置 beego/i18n、Spring Boot 自带 MessageSource 的思路完全不同。
直接尝试调用 app.I18n() 或查找 iris.I18n 类型会失败,因为这些不存在。任何声称「Iris 原生支持多语言」的教程都混淆了框架能力和社区实践。
最简可行方案:用 go-i18n + 中间件注入
推荐使用维护活跃、API 清晰的 github.com/nicksnyder/go-i18n/v2/i18n(v2 版本),配合中间件在每次请求时解析语言偏好并挂载翻译器实例到 ctx.Values()。
- 安装依赖:
go get github.com/nicksnyder/go-i18n/v2/i18n - 准备语言包:在
locales/下放en-US.yaml、zh-CN.yaml等文件,内容格式为 YAML 键值对(如hello: "Hello") - 初始化
i18n.Bundle并加载全部 locale 文件(注意路径需可被 Go module 正确 resolve) - 写中间件:
func(ctx iris.Context) { lang := detectLang(ctx); t, _ := bundle.NewPrinter(lang); ctx.Values().Set("i18n", t); ctx.Next() } - 在 handler 中取用:
t := ctx.Values().Get("i18n").(*i18n.Printer); msg := t.Sprintf("hello")
关键点:不要在全局复用同一个 *i18n.Printer,它不是并发安全的;必须 per-request 构造并注入。
语言检测逻辑怎么写才靠谱?
真实场景下,语言来源有优先级:URL 路径参数(如 /zh-CN/about) > Cookie(lang=zh-CN) > Accept-Language 请求头 > 默认语言(如 en-US)。硬编码只读 Accept-Language 会导致切换语言失败。
- 路径检测需配合 Iris 路由分组:
app.Party("/zh-CN").Use(zhMiddleware),否则正则提取易出错 - Cookie 读写要用
ctx.SetCookieKV()和ctx.GetCookie(),别用标准http.SetCookie -
Accept-Language解析不能简单取第一个,要用golang.org/x/net/http/httpguts或手写权重解析(如zh-CN,zh;q=0.9,en;q=0.8) - 默认语言必须显式声明,
bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)后记得调用bundle.MustLoadMessageFile()加载 fallback
漏掉任意一环,用户切语言后刷新页面就回退到英文——这是上线后最常被 QA 打回来的问题。
模板渲染里怎么用翻译文本?
Iris 的 ctx.View() 不自动传入 i18n.Printer,你得手动塞进视图数据:
ctx.ViewData("T", ctx.Values().Get("i18n"))
// 模板中:{{ .T.Sprintf "welcome" .Name }}
如果用 html/template,还需注册自定义函数:
app.RegisterView(iris.HTML("./views", ".html").AddFunc("t", func(key string, args ...interface{}) string {
t := ctx.Values().Get("i18n").(*i18n.Printer)
return t.Sprintf(key, args...)
}))
// 模板中:{{ t "welcome" .Name }}
注意:函数闭包里捕获的 ctx 是 handler 执行时的,不能在 RegisterView 顶层直接用,必须动态生成函数或改用 ctx.ViewFuncs() 注册。
真正麻烦的不是集成,而是语言状态如何跨重定向、AJAX、WebSocket 保持一致。比如用户在 /zh-CN/dashboard 点按钮触发 API 请求,后端返回 JSON 里的错误消息仍需按 zh-CN 翻译——这意味着每个 handler 都要重复做语言解析,或者把逻辑下沉到 service 层并透传 lang 参数。这点容易被忽略,直到法务说「隐私政策弹窗文字没本地化」才紧急补救。


















