En esta ocasión voy a retomar el proyecto que se llevó a cabo para montar el CRUD con una base de datos de películas hace unas semanas, para configurar la traducción de contenidos estáticos en la aplicación VUE.js.
Lo primero y fundamental, es la instalación de la libreria vue-I18n, que nos permitirá la internacionalización de los contenidos, usando diccionarios.
La instalación de la librería es trivial y se realiza igual que cualquier otra:
yarn add vue-i18n
Una vez instalada, toca empezar a configurar el código de nuestra aplicación para poder usarla.
Preparando el entorno
Para poder tener acceso a las capacidades de la librería desde cualquier parte de la aplicación, configuraremos el fichero main.js.
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createI18n } from 'vue-i18n'
// Función para cargar dinámicamente las traducciones
function loadLocaleMessages() {
// Indicamos cual es el fichero de traducciones, en funcion de la estructura
const locales = require.context('./translations', 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
}
const i18n = createI18n({
// creamos el idioma por defecto
locale: 'es',
messages: loadLocaleMessages()
})
createApp(App).use(router).use(i18n).mount('#app')
La configuración anterior, nos permitirá tener separada la lógica de la traducción de los diccionarios, que se almacenarán en la carpeta /src/translations y se tratan de ficheros json, con una estructura muy sencilla.
Los diccionarios tienen el nombre del idioma al que representan, para que está línea del fichero main.js, puede identificarlos rápidamente
const locales = require.context('./translations', true, /[A-Za-z0-9-_,\s]+\.json$/i)
En este caso y para este ejemplo, hemos establecido un idioma por defecto: el español, aunque podríamos dejarlo vacío.
const i18n = createI18n({
// creamos el idioma por defecto
locale: 'es',
messages: loadLocaleMessages()
})
Montando el servicio de traducción
Como siempre, voy a diferenciar los servicios a los que se tendrá acceso desde cualquier parte de la aplicación, para hacer más limpio el código. En este caso voy a crear en /logic, un fichero llamado translate.js, que será el servicio de traduccion.
En realidad es un simple método, que recoge el evento del cambio de estado de un desplegable con una lista de idiomas, como veremos enseguida:
// /logic/translate.js
export default {
methods: {
// Método para cambiar el idioma seleccionado
changeLanguage(event) {
// Establecer español por defecto si no se proporciona un idioma
const selectedLanguage = event.target.value || 'es';
// Configurar el nuevo idioma en vue-i18n
this.$i18n.locale = selectedLanguage;
},
// Otros métodos relacionados con la traducción pueden ir aquí
},
};
Una vez configurado el servicio, vamos a importarlo desde otras partes de la aplicación, en este caso, desde el componente movies.js que ya vimos en otros ejemplos y que nos muestra el listado de películas.
A esta vista, le vamos a añadir un desplegable para poder seleccionar los idiomas existentes
<div>
<select id="language" @change="changeLanguage">
<option selected value="">Selecciona el idioma</option>
<option value="es">Español</option>
<option value="en">Inglés</option>
</select>
</div>
Ahora necesitaremos importar el servicio translate.js que hemos creado antes y crear un metodo que responda al cambio de idioma en esta vista.
<script>
// Otras importaciones
import translateMethods from '@/logic/translate.js'; // Asegúrate de ajustar la ruta
// Añadimos el método
methods: {
methods: {
...translateMethods.methods,
// Otros métodos del componente
Creando los diccionarios
Una vez preparados los metodos y acciones, llega el momento de preparar los diccionarios.
Los diccionarios que vamos a usar son unos ficheros json, con la siguiente estructura
{
"message": {
"nombre_clave": "texto_a_mostrar",
...
// otras claves
...
}
}
De esta manera, cuando en el código queramos representar el texto a traducir, tendremos que incluir la cadena
$t('message.nombre_clave')
De esta forma, servirá como «comodin» y cada vez que seleccionemos un idioma, ser representará el contenido de la clave en cada idioma.
Esto es más fácil verlo que explicarlo : )
En nuestro caso, hemos creado dos diccionarios: uno en español (es.json) y otro en inglés (en.json), con este contenido:
{
"message": {
"crear_peliculas": "Crear Película",
"editando_peliculas": "Editando Película",
"titulo": "Título",
"genero": "Género",
"año": "Año",
"director": "Director",
"boton_guardar": "Guardar",
"acciones": "Acciones",
"boton_editar": "Editar",
"boton_borrar": "Borrar",
"pagina": "Página",
"anterior": "Anterior",
"siguiente": "Siguiente",
"boton_crear": "Crear Película",
"mensaje_ok_actualizacion": " ¡La película se ha actualizado correctamente!",
"mensaje_ok_borrado": "¡La película se ha eliminado correctamente!",
"mensaje_ok_creacion": "¡La película se ha creado correctamente!",
"mensaje_error_conexion_api": "Error al conectar con la API"
}
}
{
"message": {
"crear_peliculas": "Create Movie",
"editando_peliculas": "Edit Movie",
"titulo": "Title",
"genero": "Gender",
"año": "Year",
"director": "Director",
"boton_guardar": "Save",
"acciones": "Actions",
"boton_editar": "Edit",
"boton_borrar": "Delete",
"pagina": "Page",
"anterior": "Previous",
"siguiente": "Next",
"boton_crear": "Create Movie",
"mensaje_ok_actualizacion": " The movie has been successfully updated!",
"mensaje_ok_borrado": "The movie has been removed successfully!",
"mensaje_ok_creacion": "The movie has been created successfully!",
"mensaje_error_conexion_api": "Error connecting to the API"
}
}
Así por ejemplo, cuando vayamos a representar la tabla de películas, en la cabecera de la misma deberán aparecer las claves para que puedan ser traducidas cuando sean necesario:
De la misma manera, podemos incluir los mensajes que el usuario va a recibir durante el uso de la aplicación en el diccionario y así los recibirá en su idioma seleccionado.
Vamos a ver esto en funcionamiento en un breve vídeo
Hasta aquí el post de esta semana. Como siempre, es solamente un punto de partida para que se pueda seguir investigando sobre los temas que planteo.
Si quieres ver el código, lo tienes disponible en mi repositorio de GitHub