Sequelize模型定义唯一约束时i18next.t自定义错误翻译不生效问题
问题原因
- Sequelize v5 会在模型初始化阶段一次性读取并缓存
unique.msg的配置值,不会在每次触发唯一约束错误时动态取值。你定义的getter仅会在模型初始化时执行一次,此时i18next大概率还未完成语言包加载,也没有绑定对应请求的用户语言上下文,所以配置的自定义信息无法生效,Sequelize会自动 fallback 到通用唯一约束错误提示。 - 模型是全局单例初始化的,而i18next的
t函数依赖当前请求的语言上下文,初始化阶段的调用结果是固定的,即便成功读取也只会是默认语言内容,无法随用户请求的语言动态切换。
解决方案
方案1:全局错误拦截(最推荐,适配当前版本)
不需要在模型字段的unique属性中配置msg,在全局接口错误处理中间件中统一识别Sequelize唯一约束错误,再绑定当前请求的i18n实例返回翻译结果:
- 模型定义简化:
docTin : { // 其他原有配置保留 unique: { args: 'candidates_unique_doctin_company_unity' } }
- 全局错误中间件新增判断逻辑:
// 你的全局错误处理中间件 app.use(async (err, req, res, next) => { // 识别Sequelize唯一约束错误 if (err.name === 'SequelizeUniqueConstraintError') { const errorMessages = err.errors.map(errorItem => { // 按错误字段匹配对应翻译key switch(errorItem.path) { case 'docTin': // 调用绑定了当前请求语言的t函数 return req.i18n.t('invalid-candidate-unique-doc-tin') // 其他字段的唯一错误可在此扩展 default: return errorItem.message } }) return res.status(400).json({ errors: errorMessages }) } // 原有其他错误逻辑保留 next(err) })
方案2:模型自定义验证钩子
如果需要在模型层面处理错误,可使用beforeValidate钩子实现,注意调用模型操作时要把当前请求的i18n实例透传进去:
- 调用模型操作时透传i18n实例:
// 示例:创建数据时透传 await Candidate.create(提交的数据, { i18n: req.i18n, // 其他原有参数比如transaction保留 })
- 模型中新增钩子逻辑:
const Candidate = sequelize.define('Candidate', { // 原有字段定义保留 }, { hooks: { async beforeValidate(instance, options) { // 检查docTin是否已存在 const existedRecord = await Candidate.findOne({ where: { docTin: instance.docTin }, transaction: options.transaction }) if (existedRecord) { throw new Error(options.i18n.t('invalid-candidate-unique-doc-tin')) } } } })
内容的提问来源于stack exchange,提问作者Guilherme Bragamonte
相关产品推荐
相关产品推荐

