Buffalo 的 i18n 默认不注入 JSON 响应,需显式调用 c.Localize() 并手动塞入结构体或 map 后再 r.JSON;测试时须显式设置 Accept-Language 头,且 locales 文件名大小写与路径必须严格匹配。

Buffalo 中 i18n 默认不自动注入到 JSON 响应里
Buffalo 的 i18n 系统(基于 go-i18n)默认只作用于模板渲染(r.HTML),对 r.JSON 或 r.Auto 不生效。你调用 c.Render(200, r.JSON(data)) 时,哪怕请求头带了 Accept-Language: zh-CN,返回的字符串字段仍是英文原值——这不是 bug,是设计使然:JSON 响应体通常由前端或客户端做本地化,框架不越界处理。
- 验证方式:在 handler 里加
log.Printf("lang: %s", c.Request().Header.Get("Accept-Language")),确认请求头已送达 - 真正起作用的是
c.Localize(&i18n.LocalizeConfig{MessageID: "user.created"}),它需要显式调用 -
r.Auto会根据Content-Type自动选JSON或HTML,但不会触发翻译逻辑
手动注入翻译结果到 JSON 响应的三种写法
必须把翻译后的字符串塞进结构体字段,再交给 r.JSON。推荐用结构体嵌套 map[string]string 或预定义多语言字段:
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
- 方式一(简单直接):
func UserHandler(c buffalo.Context) error { msg := c.Localize(&i18n.LocalizeConfig{MessageID: "user.created"}) return c.Render(200, r.JSON(map[string]string{"message": msg})) } - 方式二(复用结构体):
type UserResponse struct { ID int `json:"id"` Name string `json:"name"` Message string `json:"message"` } func UserHandler(c buffalo.Context) error { resp := UserResponse{ ID: 123, Name: "Alice", Message: c.Localize(&i18n.LocalizeConfig{MessageID: "user.created"}), } return c.Render(200, r.JSON(resp)) } - 方式三(避免重复 localize 调用):在
init()里预加载常用 message ID 到 context,用c.Data["msg_user_created"]取值
测试多语言响应必须控制 Accept-Language 请求头
Buffalo 的测试工具(buffalo.Test)默认不带语言头,req.Header.Set("Accept-Language", "zh-CN") 必须显式设置,否则始终走默认语言(通常是 en-US):
- 错误写法:
ts := httptest.NewRecorder(); req, _ := http.NewRequest("GET", "/api/user", nil)—— 没设头,永远测不到中文 - 正确写法:
req, _ := http.NewRequest("GET", "/api/user", nil) req.Header.Set("Accept-Language", "zh-CN") ts := httptest.NewRecorder() app.ServeHTTP(ts, req) - 注意:Buffalo 的
i18n依赖buffalo.Request的c.Request().Header,不能用标准http.Request直接 mock - 多个语言并行测试时,每个
http.NewRequest都要单独 set,不能复用同一 req 对象
容易忽略的坑:go-i18n 的 message 文件路径和 key 大小写敏感
Buffalo 默认从 locales/ 下读取 en-US.all.json、zh-CN.all.json,但实际加载失败时不会报错,只会静默回退到英文——这导致你改了中文文件却看不到效果,还以为是代码问题。
- 检查点:运行
buffalo dev后看终端是否输出Loaded 2 translation files;没输出说明路径或命名不对 - 文件名必须全小写:
zh-cn.all.json❌,zh-CN.all.json✅(破折号大小写必须严格匹配) - message key 区分大小写:
"user.created"和"User.Created"是两个不同 key - 调试技巧:在 handler 里打印
c.Localize(&i18n.LocalizeConfig{MessageID: "xxx"})返回空字符串,基本可断定 key 或 locale 文件未加载
locales/zh-CN.all.json 文件名少了个大写 C,或者测试时忘了 req.Header.Set——这两处不排查完,其他代码写得再对也白搭。

















