You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

vue-i18n切换语言时表单校验提示未同步翻译问题

问题根因

校验提示不跟随语言同步切换的核心原因:初始化rules时直接执行t()方法,将返回的静态字符串赋值给了message字段,该值仅会在组件setup初始化阶段计算一次,后续语言切换时不会自动重新执行t()拉取新文案,因此会一直停留在默认语言。
之前编写的watch逻辑报getters未定义,是因为setup中没有先实例化store就直接访问store.getters,属于变量未定义的基础错误;就算修复该问题,单纯修改i18n.locale也不会让已经写入rules的静态字符串自动更新,无法实现提示同步翻译的效果。

另外注意:vue-i18n 9.x版本默认是legacy(传统Options API)模式,如果要在setup中通过useI18n调用组合式API,需要在初始化时加上legacy: false配置,否则会出现实例调用异常,main.js的i18n配置需要调整为:

import { createI18n } from 'vue-i18n'
const app = createApp(App)
const i18n = createI18n({
  legacy: false, // 开启组合式API支持
  locale: 'ee',
  fallbackLocale: 'ee',
  messages
})
app.use(i18n);
app.mount('#app');
实现方案

方案1:message传函数(推荐,代码量最少无额外监听)

Element Plus表单校验规则原生支持message字段传入函数,每次触发校验时都会重新执行该函数获取最新提示文案,不需要额外编写语言监听逻辑,只要全局i18n.locale切换正常,就能自动拿到对应语言的提示:

import { reactive } from 'vue'
import { useI18n } from 'vue-i18n';
export default {
  setup() {
    const {t} = useI18n();
    const rules = reactive<FormRules>({
      name: [
        // 不要直接调用t()传静态值,改为传入函数
        { required: true, message: () => t('message.name_helper'), trigger: "blur" },
        { min: 3, message: () => t('message.name_helper2'), trigger: "blur" },
      ]
    })

    return {
      rules
    }
  }
}

用这个写法不需要写任何额外的监听逻辑,失焦、提交表单等触发校验的场景都会自动读取当前语言的翻译文案,已经弹出的旧提示会在下一次校验触发时自动更新,覆盖绝大多数业务场景。

方案2:监听语言变化手动更新rules(适合需要即时更新已弹出提示的场景)

如果需要切换语言的瞬间,页面上已经显示的校验提示立刻更新,不需要等下一次校验触发,可以使用该方案,同时修复之前watch的报错问题:

import { reactive, watch, nextTick, ref } from 'vue'
import { useI18n } from 'vue-i18n';
// Vuex引入useStore,Pinia则引入对应store的初始化方法
import { useStore } from 'vuex'
export default {
  setup() {
    const {t, locale} = useI18n();
    const store = useStore() // 必须先实例化store,否则访问getters会报未定义
    // 提前拿表单ref,用于后续刷新校验状态
    const formRef = ref()
    const rules = reactive<FormRules>({
      name: [
        { required: true, message: t('message.name_helper'), trigger: "blur" },
        { min: 3, message: t('message.name_helper2'), trigger: "blur" },
      ]
    })

    watch(
      () => store.getters.currentLang,
      async (newLang) => {
        // 同步全局语言状态
        locale.value = newLang
        // 重新给所有校验规则赋值最新翻译
        rules.name[0].message = t('message.name_helper')
        rules.name[1].message = t('message.name_helper2')
        // 可选:清空旧校验提示后重新触发校验,实现已弹出提示即时更新
        if (formRef.value) {
          formRef.value.clearValidate()
          await nextTick()
          formRef.value.validate().catch(() => {})
        }
      },
      { immediate: true }
    )

    return {
      rules,
      formRef
    }
  }
}

优化建议:全局语言切换逻辑最好统一封装在store的action或者全局公共方法中,不需要在每个业务组件里重复写i18n.locale.value = newLang的逻辑,避免多组件状态不同步。

内容的提问来源于stack exchange,提问作者EagerToSing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:06:23