Skip to content

Cambios importantes en la versión 9

La mayoría de las API ofrecidas en Vue I18n v9 (para Vue 3) buscan mantener compatibilidad, para facilitar el dolor de migración desde v8 (para Vue 2). Pero aún hay algunos cambios importantes que podrías encontrar mientras migras tu aplicación. Esta guía muestra cómo adaptar tu aplicación para que funcione con Vue I18n v9.

APIs

new VueI18n se convierte en createI18n

Vue I18n ya no es una clase sino un conjunto de funciones. En lugar de escribir new VueI18n(), ahora tienes que llamar a createI18n:

Vue I18n v8.x:

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

Vue.use(VueI18n)

const i18n = new VueI18n({
  // ...
})

new Vue({
  i18n,
  // ...
})

Vue I18n v9 o posterior:

js
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'

const i18n = createI18n({
  // ...
})

const app = createApp({
  // ...
})
app.use(i18n)

Motivo: Cambios en la API global de Vue 3 Global API changes, y cambios en la arquitectura de la API de Vue 3 relacionados con las instancias de componentes.

Cambiar nombre a datetimeFormats de dateTimeFormats

Vue I18n v8.x:

js
const i18n = new VueI18n({
  // ...
  dateTimeFormats: {
    // ...
  }
})

Vue I18n v9 o posterior:

js
const i18n = createI18n({
  // ...
  datetimeFormats: {
    // ...
  }
})

Valor de retorno de la API de traducción

La API de traducción como $t y la función t devuelven solo string. Ya no se devuelven valores de objeto ni de matriz.

Vue I18n v8.x:

js
// e.g. Estructura de mensajes locales como array
const i18n = new VueI18n({
  messages: {
    en: {
      errors: [
        'invalid argument',
        // ...
        'unexpected errors'
      ]
    }
  }
})

// e.g. Componente de error
const ErrorMessage = {
  props: {
    code: {
      type: Number,
      required: true
    }
  },
  template: `<p class="error">{{ getErrorMessage(code) }}</p>`,
  methods: {
    getErrorMessage(code) {
      return this.$t('errors')[code]
    }
  }
}

En Vue I18n v9 y posterior, se ha cambiado para obtener mensajes locales con $tm / tm, y resolver mensajes locales con $rt o rt. El siguiente ejemplo de la API de composición:

js
// e.g. Estructura de mensajes locales como array
const i18n = createI18n({
  messages: {
    en: {
      errors: [
        'invalid argument',
        // ...
        'unexpected errors'
      ]
    }
  }
})

// e.g. Componente de error
const ErrorMessage = {
  props: {
    code: {
      type: Number,
      required: true
    }
  },
  template: `<p class="error">{{ errors(code) }}</p>`,
  setup() {
    const { tm, rt } = useI18n()
    const errors = (code) => rt(tm('errors')[code])
    return { errors }
  }
}

Motivo: Para hacer cumplir la obligación simple al devolver los resultados de traducción, y también para soportar tipos de TypeScript.

Valor de retorno de la API de pluralización

Similar a Valor de retorno de la API de traducción, la API de pluralización como $tc y la función tc devuelven solo string. Ya no se devuelven valores de objeto ni de matriz.

Motivo: Para hacer cumplir la obligación simple al devolver los resultados de traducción, y también para soportar tipos de TypeScript.

Eliminar getChoiceIndex

CAUTION

El código de implementación de la opción getChoiceIndex será totalmente eliminado en v10.

Para personalizar las reglas de pluralización, Vue I18n v8.x extiende getChoiceIndex de la clase VueI18n.

Vue I18n v8.x:

js
VueI18n.prototype.getChoiceIndex = function (choice, choicesLength) {
  // this === VueI18n instance, por lo tanto, la propiedad locale existe
  if (this.locale !== 'ru') {
    // continuar con la implementación por defecto
  }

  if (choice === 0) {
    return 0;
  }

  const teen = choice > 10 && choice < 20;
  const endsWithOne = choice % 10 === 1;

  if (!teen && endsWithOne) {
    return 1;
  }
  if (!teen && choice % 10 >= 2 && choice % 10 <= 4) {
    return 2;
  }
  return (choicesLength < 4) ? 2 : 3;
}

En Vue I18n v9 y posterior, puedes personalizarlo con las siguientes opciones:

Modo de API heredada:

js
import { createI18n } from 'vue-i18n'

function customRule(choice, choicesLength, orgRule) {
  if (choice === 0) {
    return 0
  }

  const teen = choice > 10 && choice < 20
  const endsWithOne = choice % 10 === 1
  if (!teen && endsWithOne) {
    return 1
  }
  if (!teen && choice % 10 >= 2 && choice % 10 <= 4) {
    return 2
  }

  return choicesLength < 4 ? 2 : 3
}

const i18n = createI18n({
  // ...
  pluralizationRules: {
    ru: customRule,
    // ...
  },
  // ...
})

Modo de API de composición:

js
import { useI18n } from 'vue-i18n'

function customRule(choice, choicesLength, orgRule) {
  if (choice === 0) {
    return 0
  }

  const teen = choice > 10 && choice < 20
  const endsWithOne = choice % 10 === 1
  if (!teen && endsWithOne) {
    return 1
  }
  if (!teen && choice % 10 >= 2 && choice % 10 <= 4) {
    return 2
  }

  return choicesLength < 4 ? 2 : 3
}

const MyComp = {
  setup() {
    const { t } = useI18n({
      // ...
      pluralRules: {
        ru: customRule,
        // ...
      },
      // ...
    })

    // ...
  }
}

Motivo: La clase VueI18n ha sido eliminada.

Cambiar valor predeterminado de la opción warnHtmlInMessage

En Vue I18n v8.x, el valor de warnHtmlInMessage era "off". Por lo tanto, por defecto, no se emite ninguna advertencia en la consola incluso si el mensaje contiene HTML.

En Vue I18n v9 y posterior, cambia los valores predeterminados de la siguiente manera:

  • Modo de API heredada: propiedad warnHtmlInMessage: "warn"
  • Modo de API de composición: propiedad booleana warnHtmlMessage, por defecto true

En modo de desarrollo, a menos que cambies este valor, recibirás una advertencia en la consola por defecto.

En modo de producción, no detecta si el mensaje contiene HTML para maximizar el rendimiento.

Motivo: para hacer más seguros los mensajes locales

Información de versión

La información de la versión ahora es accesible mediante sintaxis de importación en lugar de la propiedad estática de la clase VueI18n.

Vue I18n v8.x:

js
import VueI18n from 'vue-i18n'

console.log(VueI18n.version)

Vue I18n v9 o posterior:

js
import { VERSION } from 'vue-i18n'

console.log(VERSION)

Motivo: Optimización de tree shaking, y la clase VueI18n ha sido eliminada.

Eliminar disponibilidad de Intl

Eliminado porque los navegadores principales ahora admiten la API de Internacionalización de ECMAScript.

Vue I18n v8.x:

js
import VueI18n from 'vue-i18n'

console.log(VueI18n.availability)

Motivo: Fin de vida de IE9, y la clase VueI18n ha sido eliminada.

Eliminar formateador personalizado

CAUTION

El código de implementación de la opción formatter será totalmente eliminado en v10. Como alternativa, vue-i18n tiene el formato de mensaje personalizado como característica experimental.

Motivo: Debido a la dificultad de proporcionar formatos personalizados en las nuevas API del compilador y tiempo de ejecución. Estamos planeando soportarlo en la próxima versión principal para que sea compatible con estas API. Si quieres usar el formato de mensaje ICU, puedes usar @formatjs/vue-intl

Eliminar la opción preserveDirectiveContent

CAUTION

El código de implementación de la opción preserveDirectiveContent será totalmente eliminado en v10.

La directiva v-t para Vue 3 ahora preserva el contenido predeterminado. Por lo tanto, esta opción y sus propiedades han sido eliminadas de la instancia VueI18n.

Vue I18n v8.x:

js
import VueI18n from 'vue-i18n'

const i18n = new VueI18n({
  // ...
  preserveDirectiveContent: true,
  // ...
})

Motivo: Mantener el contenido en el elemento con la directiva v-t

Sintaxis de formato de mensaje

Eliminar objeto tipo array para interpolación de lista

En Vue I18n v8.x, la interpolación de lista podía usar un objeto tipo array como parámetro, como el siguiente:

js
import VueI18n from 'vue-i18n'

const i18n = new VueI18n({
  // ...
  messages: {
    en: {
      greeting: 'hello, {0}!'
    }
  },
  // ...
})
html
<p>{{ $t('greeting', { '0': 'kazupon' }) }}</p>

En Vue I18n v9 y posterior, no puedes usar objetos tipo array para interpolación de lista, debes usar arrays:

html
<p>{{ $t('greeting', ['kazupon']) }}</p>

Motivo: proporcionar una API de traducción con una interfaz de argumento consistente

Manejo de caracteres especiales

Los mensajes que pueden ser traducidos por Vue I18n pueden ser altamente traducidos usando la sintaxis de formato de mensaje, como el siguiente:

txt
@.caml:{'no apples'} | {0} apple | {n} apples

La sintaxis de formato de mensaje puede expresarse usando los siguientes caracteres especiales que son usados:

  • {, }, @, $, |

Desde Vue I18n v9 y posterior, la sintaxis de formato de mensaje ahora es manejada por el compilador de formato de mensaje, si usas estos caracteres especiales como parte de un mensaje, el mensaje causará un error al compilar. Si quieres usar estos caracteres especiales, debes usar interpolación literal.

txt
// e.g. uso de `@` para dirección de correo electrónico
{emailIdentity}{'@'}{emailDomain}

Motivo: Para que el compilador de formato de mensaje maneje correctamente los caracteres especiales de la sintaxis utilizada en la sintaxis de formato de mensaje, es necesario limitarlos.

Eliminar agrupamiento de corchetes para mensajes vinculados

En Vue I18n v8.x, se hacía una distinción entre referencias de claves en mensajes vinculados y mensajes usando paréntesis () para distinguir entre ellos.

Vue I18n v8.x:

js
const messages = {
  en: {
    message: {
      dio: 'DIO',
      linked: 'There\'s a reason, you lost, @:(message.dio).'
    }
  }
}

En Vue I18n v9 y posterior, los corchetes ya no son necesarios, ya que el compilador de formato de mensaje permite manejar interpolaciones nombradas, de lista y literales.

Vue I18n v9 o posterior:

js
const messages = {
  en: {
    message: {
      dio: 'DIO',
      linked: "There's a reason, you lost, @:{'message.dio'}."
    }
  }
}

Directiva v-t

Eliminar modificador preserve

CAUTION

El código de implementación del modificador preserve será totalmente eliminado en v10.

Similar a Eliminar opción preserveDirectiveContent, la directiva v-t para Vue 3 ahora preserva el contenido predeterminado. Por lo tanto, el modificador preserve y su funcionamiento han sido eliminados de la directiva v-t.

Vue I18n v8.x:

html
<p v-t.preserve="'hello'"></p>

Motivo: Mantener el contenido en el elemento con la directiva v-t

Componente de traducción

Cambiar nombre a i18n-t de i18n

El nombre de etiqueta del componente de traducción (llamado componente funcional i18n en Vue I18n v8.x) ha cambiado.

Vue I18n v8.x:

html
<i18n path="message.greeting" />

Vue I18n v9 o posterior:

html
<i18n-t keypath="message.greeting" />

Motivo: nombre de etiqueta igual a bloques personalizados i18n <i18n>, por lo que es confuso con los nombres de los bloques y propenso a errores en SFC.

La propiedad tag es opcional

En Vue I18n v8.x, la propiedad tag podía usarse para renderizar elementos secundarios sin el elemento raíz especificando un nombre de etiqueta y el valor booleano false.

Vue I18n v8.x:

html
<i18n :tag="false" path="message.greeting">
  <span>hello!</span>
</i18n>

Desde Vue I18n v9 o posterior, puedes hacer lo mismo omitiendo la propiedad tag.

Vue I18n v9 o posterior:

html
<i18n-t keypath="message.greeting">
  <span>hello!</span>
</i18n-t>

Motivo: Ya que Vue 3 ahora soporta Fragmentos

Cambiar nombre a la propiedad keypath de la propiedad path

Vue I18n v8.x:

html
<i18n path="message.greeting" />

Vue I18n v9 o posterior:

html
<i18n-t keypath="message.greeting" />

Eliminar sintaxis de lugar con atributo place y propiedad places

En Vue I18n v9 y posterior, los atributos place y propiedades places han sido eliminados de la interpolación de componentes.

Vue I18n v8.x:

html
<i18n path="info" tag="p" :places="{ limit: refundLimit }">
  <span place="limit">{{ refundLimit }}</span>
  <a place="action" :href="refundUrl">{{ $t('refund') }}</a>
</i18n>

Vue I18n v9 o posterior:

html
<i18n-t keypath="info" tag="p">
  <template #limit>
    <span>{{ refundLimit }}</span>
  <template>
  <template #action>
    <a :href="refundUrl">{{ $t('refund') }}</a>
  <template>
</i18n-t>

Motivo: Ya se puede hacer lo mismo con ranuras

Componente NumberFormat

La propiedad tag es opcional

Similar a Sección de componente de traducción, en el componente NumberFormat (llamado componente funcional i18n-n en Vue I18n v8.x), la propiedad tag podía usarse para renderizar elementos secundarios sin el elemento raíz especificando un nombre de etiqueta y el valor booleano false.

Vue I18n v8.x:

html
<i18n-n :tag="false" :value="100" format="currency">
  <span v-slot:integer="slotProps" styles="font-weight: bold">{{ slotProps.integer }}</span>
</i18n-n>

Desde Vue I18n v9 o posterior, puedes hacer lo mismo omitiendo la propiedad tag.

Vue I18n v9 o posterior:

html
<i18n-n :value="100" format="currency">
  <span v-slot:integer="slotProps" styles="font-weight: bold">{{ slotProps.integer }}</span>
</i18n-n>

Motivo: Ya que Vue 3 ahora soporta Fragmentos