Interpolación de Componentes
Uso Básico
A veces, necesitamos hacer la traducción con un mensaje local que fue incluido en una etiqueta HTML o componente. Por ejemplo:
<p>Acepto xxx <a href="/term">Términos del Acuerdo de Servicio</a></p>En el mensaje anterior, si usas $t, probablemente intentarás componer los siguientes mensajes locales:
const messages = {
en: {
term1: 'I Accept xxx\'s',
term2: 'Terms of Service Agreement'
}
}Y tu plantilla localizada podría verse así:
<p>{{ $t('term1') }}<a href="/term">{{ $t('term2') }}</a></p>Salida:
<p>Acepto xxx <a href="/term">Términos del Acuerdo de Servicio</a></p>Esto es muy incómodo, y si configuras la etiqueta <a> en un mensaje local, hay posibilidad de vulnerabilidades XSS debido a la localización con v-html="$t('term')".
Puedes evitarlo usando el componente de Traducción (i18n-t). Por ejemplo, el siguiente:
Plantilla:
<div id="app">
<!-- ... -->
<i18n-t keypath="term" tag="label" for="tos">
<a :href="url" target="_blank">{{ $t('tos') }}</a>
</i18n-t>
<!-- ... -->
</div>JavaScript:
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'
const i18n = createI18n({
locale: 'en',
messages: {
en: {
tos: 'Term of Service',
term: 'I accept xxx {0}.'
},
ja: {
tos: '利用規約',
term: '私は xxx の{0}に同意します。'
}
}
})
const app = createApp({
data: () => ({ url: '/term' })
})
app.use(i18n)
app.mount('#app')La salida siguiente:
<div id="app">
<!-- ... -->
<label for="tos">
Acepto xxx <a href="/term" target="_blank">Término del Servicio</a>.
</label>
<!-- ... -->
</div>Sobre el ejemplo anterior, consulta el ejemplo
Los hijos del componente de traducción son interpolados con el mensaje local de la propiedad keypath. En el ejemplo anterior,
<a :href="url" target="_blank">{{ $t('tos') }}</a>
Es interpolado con el mensaje local term.
En el ejemplo anterior, la interpolación de componentes sigue la interpolación de lista. Los hijos del componente de traducción son interpolados en el orden de su aparición.
Puedes elegir el tipo de elemento raíz especificando una propiedad tag. Si se omite, por defecto es Fragmentos.
Uso de sintaxis de ranuras
Es más conveniente usar la sintaxis de ranuras con nombre. Por ejemplo:
Plantilla:
<div id="app">
<!-- ... -->
<i18n-t keypath="info" tag="p">
<template v-slot:limit>
<span>{{ changeLimit }}</span>
</template>
<template v-slot:action>
<a :href="changeUrl">{{ $t('change') }}</a>
</template>
</i18n-t>
<!-- ... -->
</div>JavaScript:
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'
const i18n = createI18n({
locale: 'en',
messages: {
en: {
info: 'You can {action} until {limit} minutes from departure.',
change: 'change your flight',
refund: 'refund the ticket'
}
}
})
const app = createApp({
data: () => ({
changeUrl: '/change',
refundUrl: '/refund',
changeLimit: 15,
refundLimit: 30
})
})
app.use(i18n)
app.mount('#app')Salidas:
<div id="app">
<!-- ... -->
<p>
Puedes <a href="/change">cambiar tu vuelo</a> hasta <span>15</span> minutos antes de la salida.
</p>
<!-- ... -->
</div>También puedes usar la siguiente forma abreviada de ranuras en plantillas:
<div id="app">
<!-- ... -->
<i18n-t keypath="info" tag="p">
<template #limit>
<span>{{ changeLimit }}</span>
</template>
<template #action>
<a :href="changeUrl">{{ $t('change') }}</a>
</template>
</i18n-t>
<!-- ... -->
</div>LÍMITE
⚠️ En el componente de traducción, no se admiten las propiedades de ranuras.
Uso de pluralización
Puedes usar la pluralización en la interpolación de componentes usando la propiedad plural. Por ejemplo:
Plantilla:
<div id="app">
<!-- ... -->
<i18n-t keypath="message.plural" locale="en" :plural="count">
<template #n>
<b>{{ count }}</b>
</template>
</i18n-t>
<!-- ... -->
</div>JavaScript:
const { createApp, ref } = Vue
const { createI18n } = VueI18n
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: {
message: {
plural: 'no bananas | {n} banana | {n} bananas'
}
}
}
})
const app = createApp({
setup() {
const count = ref(2)
return { count }
}
})
app.use(i18n)
app.mount('#app')La salida siguiente:
<div id="app" data-v-app="">
<!-- ... -->
<b>2</b> bananas
<!-- ... -->
</div>Resolución de ámbito
La resolución de Ámbito del componente de traducción es parent por defecto.
Esto significa que el componente de traducción usa el ámbito habilitado en el componente padre que lo utiliza.
Si el componente padre tiene useI18n con useScope: 'global', usará el Ámbito Global; de lo contrario, si useScope: 'local', usará el Ámbito Local del componente padre.
Sin embargo, a veces ves el mensaje de advertencia en la consola de tu navegador:
[intlify] No se encontró el ámbito padre. Se utilizará el ámbito global.Este mensaje se muestra cuando no has ejecutado useI18n en el componente padre que usa el componente de traducción.
En esa situación, el Ámbito del Componente de Traducción retrocederá al ámbito global como indica el mensaje de advertencia.
Una solución alternativa para suprimir esta advertencia es especificar global como la propiedad scope del componente de traducción.
<i18n-t keypath="message.foo" scope="global">
...
</i18n-t>NOTA
Esta advertencia no se muestra en la consola del navegador en las compilaciones de producción.
NOTA
Esto no está disponible en petite-vue-i18n