Traduciendo contenidos estáticos de Vue.js con diccionario

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

Por Jose Manuel Sanz Prieto

Desarrollador web. En este blog hablo de fotografía, programación con Django, Python, PHP y privacidad.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *