Para guardar nuestras cadenas de texto, y poder tenerlas en diferentes idiomas, haremos uso de la librería Vue i18n. Antes de nada, para empezar a usarlo tenemos que descargar el paquete:
npm install vue-i18n
Hay diferentes formas de organizar esto en nuestro proyecto, pasamos a verlas.
Inicializar i18n
Para inicializar i18n, crearemos la instancia en el archivo src/i18n.js, de la siguiente manera:
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: process.env.VUE_APP_I18N_LOCALE || 'es',
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'es',
silentTranslationWarn: true,
messages: loadLocaleMessages(),
});
Además, al crear la instancia de Vue, tendremos que importarlo e incluirlo en el new Vue del archivo main.js:
import i18n from '@/i18n'
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount("#app");
Definir mensajes
Podemos definir los mensajes de dos maneras diferentes, o bien en archivos .js dedicados, o dentro de los mismos componentes.
En un archivos aparte
La forma más intuitiva de gestionar los diferentes locales disponibles, será tener cada uno en un archivo JSON dentro de src/locales. Tendremos, al menos, español e inglés, en los archivos es.json y en.json, respectivamente, y seguirán la siguiente estructura:
// es.js
{
"helloworld": "¡Hola mundo!",
"test": "Esto es una prueba",
}
// en.js
{
"helloworld": "Hello world!",
"test": "This is a test",
}
Por último, el como hemos visto previamente, los dos archivos se importan en el src/locales/index.js, se juntan en una variable y se pasa en la creación de la instancia de VueI18n.
En los propios componentes
Otra opción, que puede ser útil para, por ejemplo, compartir componentes en el repositorio, es definir los mensajes en los propios archivos .vue de los componentes.
Para esto, es necesario añadir el i18n-loader:
npm install @intlify/vue-i18n-loader
Después, en la raíz del proyecto, debemos crear el archivo vue.config.js, que contenga lo siguiente:
module.exports = {
chainWebpack: config => {
config.module
.rule("i18n")
.resourceQuery(/blockType=i18n/)
.type('javascript/auto')
.use("i18n")
.loader("@intlify/vue-i18n-loader")
.end();
}
}
Con esto, nos podemos definir los mensajes en un bloque entre tags <i18n>, por ejemplo:
<i18n>
{
"es": {
"helloworld": "¡Hola mundo!",
"test": "Esto es una prueba"
},
"en": {
"helloworld": "Hello world!",
"test": "This is a test"
}
}
</i18n>
Mostrar los mensajes
Para mostrar las cadenas de texto, lo haremos con $t('nombreCadena') en el template, y en la parte javascript con this.$t('nombreCadena'):
<Column :header="$t('tituloColumna')" />
<span>
{{ $t('texto') }}
</span>
...
unaFuncion() {
...
this.$toast.add({ severity: "error", summary: "Error", detail: this.$t('error_descarga'), life: 10000 });
}
Mostrar los mensajes en Vuex
En Vuex, al estar en otro contexto, no podemos acceder a this, por lo que tendremos que importar i18n y utilizarlo así:
import i18n from '@/locales'
i18n.t("nombreCadena")
Parametrizar los mensajes
Podemos poner parámetros en los mensajes de declarados en en.js y es.js de forma:
export default {
introduccion: "La descripcion de {nombre} es la siguiente:",
};
y usarlos de forma:
$t('introduccion', {nombre: nombreUsuario})
Cambiar idioma
En las aplicaciones, lo normal es que queramos cambiar el idioma en la aplicación completa, en todos los compones. Para cambiar el idioma globalmente tendremos que modificar this.$root.$i18n.locale:
onClick() {
if (this.$root.$i18n.locale === "es") this.$root.$i18n.locale = "en";
else this.$root.$i18n.locale = "es";
}
Con esto es importante tener en cuenta un detalle, por si nos topamos con que no funciona: no se puede acceder al $root en funciones con la sintaxis flecha () => { ... }. Esto se debe a que este tipo de funciones cogen el contexto de dónde se definen, es decir, el del componente, mientras que para acceder a $root se necesita estar en el contexto de la instancia de Vue, lo que se hace con las funciones normales (nombreFuncion(param) / nombreFuncion: function(param)).
Tenemos otra forma de cambiar el idioma, pero en este caso se cambia para el componente actual y sus hijos. Se haría igual, pero modificando this.$i18n.locale:
onClick() {
if (this.$i18n.locale === "es") this.$i18n.locale = "en";
else this.$i18n.locale = "es";
}
Esto se puede utilizar también para cambiar el idioma en toda la aplicación si lo hacemos en el componente inicial, en el App.vue, pero si lo hacemos en otro componente tenemos que tener en cuenta que se perderá al navegar a otro componente y volver. Si por algún caso de uso de nuestras aplicaciones es necesario, se puede utilizar, pero lo más habitual será cambiar el idioma globalmente.
Más documentación
Para consultar la documentación oficial, con todas las opciones disponibles, podemos irnos aquí. Algunas opciones útiles que podemos consultar en la documentación son la pluralización (cadenas en singular o plural), gestión de fechas, o números.