如何在Gobuffalo模型中使用i18n翻译器?
在Gobuffalo模型中访问i18n翻译器的解决方案
这个问题我之前也碰到过,确实模型里直接调用i18n翻译器不像actions里那么顺手——毕竟模型本身不持有buffalo.Context。给你几个实用的方案:
方案一:直接传递翻译器/上下文到模型方法
这是最直接也最安全的方式,因为请求级的上下文/翻译器不会有并发问题。
方式1:传递*i18n.Translator实例
在模型里定义方法时,把翻译器作为参数传入:
// models/user.go type User struct { gorm.Model Name string } // 示例方法:需要翻译内容时接收翻译器参数 func (u *User) GetWelcomeMessage(t *i18n.Translator) string { return t.Translate("user.welcome", map[string]interface{}{ "Name": u.Name, }) }
然后在actions里调用时,把当前请求的翻译器传进去:
// actions/users.go func ShowUser(c buffalo.Context) error { t := c.Value("translator").(*i18n.Translator) user := &User{} if err := DB.First(user, c.Param("id")).Error; err != nil { return c.Error(http.StatusNotFound, err) } welcomeMsg := user.GetWelcomeMessage(t) c.Set("welcome_msg", welcomeMsg) return c.Render(http.StatusOK, r.HTML("users/show.plush.html")) }
方式2:直接传递buffalo.Context
如果模型方法需要用到上下文的其他能力(不止翻译),可以直接传上下文进去:
func (u *User) GetWelcomeMessage(c buffalo.Context) string { t := c.Value("translator").(*i18n.Translator) return t.Translate("user.welcome", map[string]interface{}{ "Name": u.Name, }) }
调用时直接传c即可:
welcomeMsg := user.GetWelcomeMessage(c)
方案二:针对模型验证场景的优化
如果是在模型验证时需要翻译错误消息(比如用github.com/gobuffalo/validate/v3),可以封装带翻译器的验证函数:
// models/user.go func ValidateUserWithTranslator(user *User, t *i18n.Translator) error { v := validate.New() if user.Name == "" { v.AddError("name", t.Translate("user.name.required")) } if len(user.Password) < 6 { v.AddError("password", t.Translate("user.password.min_length")) } return v.Error() }
在actions里调用这个验证函数,传入当前翻译器:
// actions/users.go func CreateUser(c buffalo.Context) error { t := c.Value("translator").(*i18n.Translator) user := &User{} if err := c.Bind(user); err != nil { return err } if err := ValidateUserWithTranslator(user, t); err != nil { c.Set("errors", err.(validate.Errors)) return c.Render(http.StatusUnprocessableEntity, r.HTML("users/new.plush.html")) } DB.Create(user) return c.Redirect(http.StatusSeeOther, "/users/%d", user.ID) }
方案三:全局注入(谨慎使用)
如果你的应用是单语言场景,且不需要动态切换语言,可以考虑把翻译器设为全局变量。但多语言应用绝对不要用这个方式——会出现并发请求的语言混乱问题。
示例代码:
// models/translator.go var GlobalTranslator *i18n.Translator // 在应用启动时初始化全局翻译器 func init() { var err error GlobalTranslator, err = i18n.New(&i18n.Options{ DefaultLanguage: "en", Translations: i18n.Translations{ // 加载翻译文件逻辑 }, }) if err != nil { panic(err) } }
然后在模型里直接调用:
func (u *User) GetWelcomeMessage() string { return GlobalTranslator.Translate("user.welcome", map[string]interface{}{ "Name": u.Name, }) }
总结
最推荐的是方案一,它完全符合Gobuffalo的请求上下文设计,既安全又灵活,不会引入额外的并发风险。
内容的提问来源于stack exchange,提问作者emurmotol
相关产品推荐
相关产品推荐

