在 Vue 应用程序中动态更改语言环境不会更新页面上的翻译值

Posted

技术标签:

【中文标题】在 Vue 应用程序中动态更改语言环境不会更新页面上的翻译值【英文标题】:Changing locale dynamically in Vue app doesn't update translated values on pages 【发布时间】:2020-07-01 22:08:52 【问题描述】:

我有一个大型的 Vue 应用程序(使用 Vuetify),我最近将 vue-i18n 合并到其中。我的 json 翻译文件已设置并正常工作,我对 $t() 的调用在我的组件和其他 .js 文件中运行良好。但是,我一直无法做的是即时更改语言环境,以便我所有翻译字段中的文本都显示适当的语言。如果我更改我的 new Vue18n() 定义并保存文件,它可以正常工作,并且我的所有翻译值都可以正常显示。

在我的情况下,我可以选择菜单上的项目,

    <v-icon color="primary" dark slot="activator">
        person
    </v-icon>
    <v-list dark class="primary">
      <v-list-tile>
        <v-list-tile-title> getUser.userId </v-list-tile-title>
      </v-list-tile>

      <v-divider />

      <v-list-tile @click="passDialog = !passDialog">
        <v-list-tile-title>Password</v-list-tile-title>
      </v-list-tile>
      <v-list-tile @click="logoutClick">
        <v-list-tile-title>Logout</v-list-tile-title>
      </v-list-tile>
      <v-list-tile>
        <v-list-tile-title @click="setLocale('en')">English</v-list-tile-title>
      </v-list-tile>
      <v-list-tile>
        <v-list-tile-title @click="setLocale('es')">Spanish</v-list-tile-title>
      </v-list-tile>
    </v-list>

以及将适当的语言环境传递给方法的点击处理程序:

setLocale(locale) 
  this.$root.$i18n.locale = locale;
,

这里定义了VueI18n

import Vue from 'vue';
import VueI18n from 'vue-i18n';

Vue.use(VueI18n);

function loadLocaleMessages() 
  const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i);
  const messages = ;
  locales.keys().forEach((key) => 
    const matched = key.match(/([A-Za-z0-9-_]+)\./i);
    if (matched && matched.length > 1) 
      const locale = matched[1];
      messages[locale] = locales(key);
    
  );
  return messages;


export default new VueI18n(
  locale: 'en',
  localeDir: 'locales',
  fallbackLocale: 'en',
  messages: loadLocaleMessages(),
);

我也尝试过变体,例如

this.$i18n.locale = locale;

i18n.locale = locale;

也做了之后

import i18n from `@/i18n'; 

在组件中。但是,几乎没有一个会更改我所有具有翻译的字段名称值。就好像我必须在语言更改后强制重新呈现我的翻译值。

在我选择了不同的语言后,我需要做些不同的事情来更新我的所有翻译值吗?

更新:根据下面 Romain Vincent 的评论,我意识到我错过了设置的一个重要部分。每个字段都有多个 Vuetify 属性,它们被提取到单独的fields.js 文件中。例如,以下是来自模板的几个字段定义:

<v-layout row>
  <v-flex xs6>
    <v-text-field 
      v-bind="fields.userId" 
      v-model="userModel.userId"
      :disabled="!canSave"
    />
  </v-flex>
  <v-flex xs6>
    <v-text-field v-bind="fields.id" v-model="userModel.id" disabled />
  </v-flex>
</v-layout>

...

import  fields, buttons, csvFields  from '@/components/config/users';

...

data: () => (
    fields,
...
)

然后这里是fields.js:

import RuleGenerator from '@/utils/RuleGenerator';
import i18n from '@/i18n';

const fields = 
  userId: 
    label: i18n.t('users.generalInfo.userId'),
    // Set label to 'Email' because the username is required to be an email address.
    rules: new RuleGenerator('Email')
      .setRequired()
      .setMin(1)
      .setMax(255)
      // eslint-disable-next-line no-useless-escape
      .setRegEx(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]1,3\.[0-9]1,3\.[0-9]1,3\.[0-9]1,3])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]2,))$/)
      .getRules(),
    hint: 'Must be a valid email address',
    counter: '255',
  ,
  id: 
    label: i18n.t('users.generalInfo.id'),
  ,
;

export default fields;

这些字段不会改变语言环境。但是,如果我直接在组件中绑定label

<v-text-field 
  v-bind="fields.userId" 
  v-model="userModel.userId"
  :disabled="!canSave"
  :label="$t('users.generalInfo.userId')"
/>

更改语言环境可以很好地更新标签值。因此,即使它包含 i18n.js(这是设置 locale 的位置),也似乎存在该绑定文件的问题。

更新 2: 其他人似乎也遇到了这个问题 (see this GitHub issue)。

【问题讨论】:

我认为您还有另一个问题是阻止反应发生,因为据我所知,您用于更改语言环境的代码是正确的。我刚刚在控制台中使用 $vm.$i18n.locale = 'en'/'xxx' 进行了尝试,它可以立即运行 @RomainVincent 我用更多细节更新了这个问题。 【参考方案1】:

如果您指的是label: i18n.t(...),它只会运行一次。语言的任何变化都不会改变标签。一种解决方案是将文本键放在您的字段中,并在组件中对包含文本键的变量使用 $t:

field.js

...
const fields = 
  userId: 
    label: 'users.generalInfo.userId',
...

component

<v-text-field 
  :label="$t(fields.userId.label)"
/>

【讨论】:

以上是关于在 Vue 应用程序中动态更改语言环境不会更新页面上的翻译值的主要内容,如果未能解决你的问题,请参考以下文章

在 VueJS 中更改环境变量后,有没有办法热重载我的 Vue 页面?

Vue 组件 prop 更改不会触发重新渲染

当用户在 Symfony 中更改语言环境时更新用户会话

vue中一些方法的原理

在“打开链接”页面更改语言

Vue.js 更新的属性不会在子组件上更改