Sequelize模型定义中调用i18next.t返回翻译键而非对应译文
问题根因
- 执行时机不匹配:Sequelize 模型定义代码会在应用启动阶段同步执行,你在验证规则的
msg字段中直接调用i18next.t(),该调用会在模型加载时立刻运行,此时大概率 i18next 还未完成初始化(未加载翻译资源、未设置生效语言),无法匹配到对应翻译值,只会返回原始翻译键。 - 不支持动态语言切换:即便 i18next 初始化完成,这个写法也只会保留应用启动时的单次翻译结果,后续不同用户请求携带不同语言偏好时,错误消息无法动态切换,不符合多语言业务的使用要求。
解决方案
方案1:业务层统一捕获翻译(更推荐)
模型定义阶段只存储翻译键,不要直接执行翻译:
// candidate.js 模型定义 validate: { isIn: { args: [allowedTypes], msg: 'candidate-invalid-type' } }
在业务逻辑层捕获 Sequelize 验证错误时,结合当前请求的语言上下文执行翻译:
// 业务代码中调用模型操作的位置 try { await Candidate.create(params) } catch (err) { if (err.name === 'SequelizeValidationError') { const translatedErrors = err.errors.map(item => { return i18next.t(item.message, { allowedTypes, joinArrays: ', ' }) }) // 后续返回翻译后的错误信息即可 } }
该方案可以完全和当前请求的语言上下文绑定,灵活适配多语言切换场景,也方便统一管理所有验证错误的翻译逻辑。
方案2:模型层使用自定义验证函数
如果希望翻译逻辑放在模型层,可以替换静态的msg配置为自定义验证函数,在验证触发时才执行翻译:
type: { type: DataTypes.ENUM, values: [types.CANDIDATE, types.EMPLOYEE], validate: { isInAllowedTypes(value) { if (!allowedTypes.includes(value)) { throw new Error(i18next.t('candidate-invalid-type', { allowedTypes, joinArrays: ', ' })) } } } }
注意如果是多请求并发的服务场景,需要确保i18next实例和当前请求的语言上下文绑定,不要直接使用全局i18next实例,避免不同请求的语言设置互相串扰。
内容的提问来源于stack exchange,提问作者Guilherme Bragamonte
相关产品推荐
相关产品推荐

