DEV Community

Cover image for Construyendo una app multi-lenguaje con Vue JS. 🌐
Franklin Martinez
Franklin Martinez

Posted on

Construyendo una app multi-lenguaje con Vue JS. 🌐

Hoy les presentare un forma fácil de crear aplicaciones que soporten varios idiomas, usando Vue JS

Image description

Tecnologías a utilizar.

  • Vue 3.3.11
  • @tolgee/vue 5.19.0
  • Vite JS 5.0.8
  • TypeScript 5.2.2
  • Tailwind CSS 3.4.0

Creando el proyecto

Para crear el proyecto con Vue, usaremos vite js
Al proyecto le colocaremos el nombre de: multi-lang-app (opcional, tu le puedes poner el nombre que gustes).

npm create vite@latest
Enter fullscreen mode Exit fullscreen mode

Después de colocar el nombre, seleccionamos la opción de Vue y luego la opción de TypeScript (aunque no es necesario para esta ocasión)
Creamos el proyecto con Vite JS y seleccionamos React con TypeScript.

Luego ejecutamos el siguiente comando para navegar al directorio que se acaba de crear.

cd multi-lang-app
Enter fullscreen mode Exit fullscreen mode

Luego instalamos las dependencias.

npm install
Enter fullscreen mode Exit fullscreen mode

Después abrimos el proyecto en un editor de código (en mi caso VS code).

code .
Enter fullscreen mode Exit fullscreen mode

Instalando Tailwind

Solamente seguimos los pasos que indica la documentación de Vite
Primero instalamos las dependencias.

npm install -D tailwindcss postcss autoprefixer
Enter fullscreen mode Exit fullscreen mode

Después ejecutamos este comando para crear los archivos de configuración de tailwind.

npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

Luego en nuestro archivo tailwind.config.js agregamos la siguiente configuración

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
Enter fullscreen mode Exit fullscreen mode

Y en nuestro archivo style.css agregamos:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Y eso es suficiente.

🈵 Primeros pasos.

Primero vamos a crear una TO-DO list sencillo.

Creamos un nuevo archivo src/components/MainContent.vue
En el cual definiremos dos nuevos estados:

  • task: Es la descripción de la tarea.
  • collectionTasks: un arreglo de tareas (y una tarea se compone de objeto que contiene la descripción y si esta completada).
<script setup lang="ts">
import { ref } from 'vue'

interface Task {
  task: string
  isCompleted: boolean
}

const task = ref('')
const collectionTasks = ref<Task[]>([])
</script>

<template>
</template>
Enter fullscreen mode Exit fullscreen mode

Seguido de eso, creamos dos simples funciones.

  • createTask: agrega una nueva tarea a la lista y reinicia el input donde ingresas dicha tarea.
  • handleToggleComplete: marca la tarea como completada
<script setup lang="ts">

// ...

const createTask = () => {

  if(task.value.trim().length === 0) return

  collectionTasks.value.push({
    task: task.value,
    isCompleted: false
  })

  task.value = ''
}

const handleToggleComplete = (index:number) => {
  const taskSelected = collectionTasks.value.find( (_,i) => i === index )
  if(taskSelected) {
    taskSelected.isCompleted = !taskSelected?.isCompleted
  }
}
</script>

<template>
</template>
Enter fullscreen mode Exit fullscreen mode

Ahora seguimos con el HTML.

Nota: En este punto se supone que deberías tener nociones de como usar Vue, asi que no se te debe hacer raro dichas características que usa Vue, como el @submit.prevent, @click, v-model, v-show, v-for, v-bind (usando su forma corta ":") o la sintaxis de "Mustache" para la interpolación de texto.

<script setup lang="ts">
// ...
</script>

<template>
  <div class="flex items-center flex-col gap-2 p-5">

    <h1 class="text-6xl font-black mt-28 mb-10 text-wrap">
      THIS IS THE MAIN TITLE
    </h1>

    <main class="max-w-2xl ">
      <form
        @submit.prevent="createTask"
        class="flex items-center gap-5"
      >
        <input
          type="text"
          placeholder="TASK PLACEHOLDER"
          autofocus
          v-model="task"
          class="p-3 px-4 text-xl rounded-lg flex-1 min-w-[420px]"
        />
        <button class="bg-blue-500 p-3 px-4 rounded-md hover:bg-blue-600">
          ADD NEW TASK
        </button>
      </form>

      <section
        class="bg-[#272932] p-5 rounded-md my-10"
        v-show="collectionTasks.length !== 0"
      >
        <h2
          class="mt-2 mb-5 text-3xl font-bold text-white/50 border-b pb-3 border-white/50"
        >
          SECTION LIST TASK TITLE
        </h2>

        <div
          v-for="(item, index) in collectionTasks"
          :key="index"
          class="flex items-center gap-5"
        >
          <span
            :class="['p-2 text-xl cursor-pointer', item.isCompleted && 'line-through']"
            @click="handleToggleComplete(index)"
          >
            👉 {{ item.task }}</span
          >

          <span
            v-show="item.isCompleted"
            class="p-2 rounded-lg bg-green-500/20 text-green-300 border-green-500 border text-xs"
          >
            COMPLETED
          </span>
        </div>
      </section>
    </main>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Nota que en el código de arriba puse ciertas palabras en mayúsculas, esto es porque es ahí donde queremos aplicar el cambio de idioma.
Y con esto terminamos nuestra mini aplicación, solo falta mostrarla en App.vue

Dentro del archivo src/App.vue, borramos todo y colocamos lo siguiente:

<script setup lang="ts">
import MainContent from './components/MainContent.vue';
</script>

<template>
  <MainContent />
</template>
Enter fullscreen mode Exit fullscreen mode

Image description

Los estilos pueden cambiar, checa el repositorio al final de este post

Configurando las traducciones para la app.

Antes de seguir con el código, vamos a configurar las traducciones, para ello, usaremos Tolgee.

"Tolgee es una plataforma de localización que te permite traducir tu aplicación a cualquier idioma sin modificar tu código. Está diseñada para su uso con aplicaciones web, pero puede utilizarse también con apps para móviles y aplicaciones de escritorio."

Puedes saber más hacer de esta plataforma en su web Tolgee

  1. Primero creamos una cuenta en https://app.tolgee.io/sign_up.

Una vez creada la cuenta te llevara a tu proyectos, el cual no tendrá ninguno creado aun.

Image description

  1. Agregar un proyecto nuevo.
  • Agregas un nombre al proyecto (ejemplo: demo-vue)
  • Agregas los idiomas que quieras configurar.
  • Seleccionas un lenguaje base.
  • Finalmente das click en el botón "Save"

Image description

Una vez creado el proyecto, te llevara al dashboard de dicho proyecto.
Ahora dirígete a la parte de "Translations" que debe estar en el menú lateral izquierdo.

Image description

  1. Agregar traducciones. Una vez en la sección de "Translations", presiona el botón de "+" para agregar una nueva traducción. Te pedirá agregar los siguiente:
  • key: es la palabra clave que identifica la traducción y debe ser única. Normalmente siguen una convección que se usa "_" por ejemplo: "about_page_title", mira más sobre eso en la documentación
  • namespaces (opcional): es una llave que ayuda a separar las traducciones en multiples archivos, es util cuando tienes una app grande que contenga muchas traducciones (más de 1000 keys)
  • tags: que pueden ser usadas para agrupar keys.
  • languages text(s): El texto que debería ser desplegado en cada idioma.
    • Puede seleccionar los idiomas que desea mostrar aquí seleccionándolos en el menú desplegable de la parte superior. Si no especifica el texto para un idioma, la tecla se marcará como "Untranslated" para ese idioma.

Image description

Revisa bien que se muestren los lenguajes en los que quieras agregar la traducción. En la parte superior derecha puedes seleccionar que lenguajes quieres traducir.

Nota que cuando agregas el texto en en campo del idioma que seleccionaste como "base language" y luego te colocas en otro campo para agregar otro idioma, se te despliega un panel con dos secciones

  • TRANSLATION MEMORY: busca textos similares en tu proyecto y te los sugiere. Esto te ayuda a reutilizar traducciones y ahorrar tiempo. mira más en la sección translation memory
  • MACHINE TRANSLATION: es una forma de traducir contenidos utilizando servicios externos y obtener una traducción aproximada del contenido.

Solamente selecciona una opción, si no conoces la traducción exacta.

Image description

Finalmente presiona "Save" para agregar la traducción

Para este proyecto agregare 3 idiomas "español mexicano", "inglés" y "francés".

Agregando Tolgee a nuestro proyecto.

Para agregar Tolgee a nuestra proyecto es muy sencillo, ejecutamos:

npm install @tolgee/vue
Enter fullscreen mode Exit fullscreen mode

Ahora vamos a crear un nuevo archivo src/lib/tolgee.ts y agregaremos la siguiente configuración.

Primero vamos a llamar la función Tolgee.

import { Tolgee } from '@tolgee/vue';

export const tolgee = Tolgee()
Enter fullscreen mode Exit fullscreen mode

Después vamos a configurar algunos plugins para Tolgee.

  • DevTools: combinación de varios plugins que nos ayudaran en modo desarrollo, como por ejemplo comunicar nuestra app con la plataforma de Tolgee. Este plugin es omitido en producción por defecto.
  • FormatSimple: Es un formateador que nos habilita poder pasar variables dentro las traducciones.

Para definir un plugin usamos el método use()

import { Tolgee, DevTools, FormatSimple, BackendFetch } from '@tolgee/vue';

export const tolgee = Tolgee()
  .use(DevTools())
  .use(FormatSimple())
Enter fullscreen mode Exit fullscreen mode

Luego llamamos el método init, pasándole un objeto con las siguientes propiedades.

  • language: el lenguaje inicial de tu app.
  • apiUrl: una URL que te proporciona tolgee, para conectarse a la plataforma.
  • apiKey: una KEY que te proporciona tolgee, para conectarse a la plataforma.

Esta función init() tiene mas propiedades, pero las que mencionamos son suficientes por el momento.

import { Tolgee, DevTools, FormatSimple, BackendFetch } from '@tolgee/vue';

export const tolgee = Tolgee()
  .use(DevTools())
  .use(FormatSimple())
  .init({
    language: 'es-MX',
    apiUrl: '',
    apiKey: ''
  });
Enter fullscreen mode Exit fullscreen mode

Obteniendo la API KEY.

Volvemos a la plataforma Tolgee, buscamos en el menú lateral la sección de integrate.

Image description

Te aparecerá una serie de pasos:

  1. Escoger la tecnología que vas a usar para tu proyecto.
  2. Después te pedirá seleccionar una API KEY. Si es que ya tienes una creada, si no, solo selecciona la opción de "Create new +". Ahi mismo puedes configurar el nombre, expiración y el alcance.
  3. Te mostrara un breve Quick start. En esa parte te mostrara tanto la variable API_URL y API_KEY.

Solo copia las variables en un archivo .env dentro de tu proyecto. Y finalmente hacemos referencia a dichas variables de entorno.

import { Tolgee, DevTools, FormatSimple, BackendFetch } from '@tolgee/vue';

export const tolgee = Tolgee()
  .use(DevTools())
  .use(FormatSimple())
  .init({
    language: 'es-MX',
    apiUrl: import.meta.env.VITE_APP_TOLGEE_API_URL,
    apiKey: import.meta.env.VITE_APP_TOLGEE_API_KEY
  });
Enter fullscreen mode Exit fullscreen mode

Terminando la configuración de Tolgee

Ahora en nuestro archivo src/main.ts usamos el plugin de tolgee que hemos creado en la app de Vue de la siguiente manera:

import { createApp } from 'vue';
import './style.css';
import App from './App.vue';

import { VueTolgee } from '@tolgee/vue';
import { tolgee } from './lib/tolgee';

const app = createApp(App);

app.use(VueTolgee, { tolgee });

app.mount('#app');
Enter fullscreen mode Exit fullscreen mode

Agregando el proveedor

Ahora necesitamos agregar un proveedor en src/App.vue y envolvemos nuestro componente

<script setup lang="ts">
import { TolgeeProvider } from '@tolgee/vue';
import MainContent from './components/MainContent.vue';
</script>

<template>
  <TolgeeProvider>
    <MainContent />
  </TolgeeProvider>
</template>
Enter fullscreen mode Exit fullscreen mode

Ahora dentro del proveedor necesitamos especificar un componente fallback que se mostrará mientras se carga las traducciones del idioma que esta por defecto.

Nota que cree un componente por separado llamado Loading en src/components/Loading.vue

<script setup lang="ts">
import { TolgeeProvider } from '@tolgee/vue';
import MainContent from './components/MainContent.vue';
import Loading from './components/Loading.vue';
</script>

<template>
  <TolgeeProvider>

    <template v-slot:fallback>
      <Loading />
    </template>

    <MainContent />
  </TolgeeProvider>
</template>
Enter fullscreen mode Exit fullscreen mode

Y ahora ya estamos listos para traducir.

Traduciendo los textos

Una vez terminada la configuración, tenemos acceso a varias formas de traducir los textos, en este caso usare la función global $t, porque no necesito importar nada gracias a la configuración que hicimos.
También existen otras formas, como usar un componente T o un composable useTranslate

Devuelta en el archivo src/components/MainContent.vue, usamos la función global $t de esta manera:

  • Dentro de la función, le mandamos la key que definimos en la plataforma de Tolgee.
<h1 class="text-6xl font-black mt-28 mb-10 text-wrap">
  {{ $t('title_page') }}
</h1>
Enter fullscreen mode Exit fullscreen mode

Y de esta manera vemos como se muestra correctamente el titulo en el lenguaje por defecto que configuramos.

Ahora vamos a remplazar los demás textos de los elementos:

  • el placeholder del input
<template>
<!-- all the rest ... -->
  <input
    type="text"
    :placeholder="$t('placeholder_task_input')"
    autofocus
    v-model="task"
    class="p-3 px-4 text-xl rounded-lg flex-1 min-w-[420px]"
  />
  <!-- all the rest ... -->
</template>
Enter fullscreen mode Exit fullscreen mode
  • el label del botón
<button class="bg-blue-500 p-3 px-4 rounded-md hover:bg-blue-600">
  {{ $t('button_add_task') }}
</button>
Enter fullscreen mode Exit fullscreen mode

el titulo de la sección del listado

<h2
  class="mt-2 mb-5 text-3xl font-bold text-white/50 border-b pb-3 border-white/50"
>
  {{ $t('title_section_list_tasks') }}
</h2>
Enter fullscreen mode Exit fullscreen mode

Y asi sucesivamente lo que te gustaría traducir.

Cambiando el idioma.

Ya podemos mostrar los textos, ahora necesitamos seleccionar otro idioma para mostrar las otras traducciones.
Para ello crearemos un componente src/components/SelectLang.vue

Primero crearemos la funcionalidad.
Estaremos usando un composable de tolgee, useTolgee.
Dicho composable nos retorna una instancia de Tolgee permitiendo suscribirnos a diferentes eventos

Nota como especificamos "language", lo que significa que solamente queremos escuchar el evento cuando un idioma cambia.
También nota que estamos pasándole un arreglo a useTolgee, debido a que podemos escuchar varios eventos.

Después creamos una función que recibirá un evento () y vamos a ejecutar la función changeLanguage de tolgee, mandando el valor del input.
Básicamente usaremos un elemento select y cada vez que se haga un cambio se ejecutara el changeLanguage, pasando el valor que hemos seleccionado.

<script setup lang="ts">
import { useTolgee } from '@tolgee/vue';

const tolgee = useTolgee(['language']);

const changeLanguage = (e: Event) => {
  tolgee.value.changeLanguage((e.target as HTMLSelectElement).value);
};
</script>
Enter fullscreen mode Exit fullscreen mode

Finalmente solo implementamos el template.

  • Nota que en el atributo value del select, estamos llamando la función getLanguage() de tolgee, el cual nos provee el idioma actual que hemos configurado (NO es el idioma de tu navegador), que en es 'es-MX'.

  • Nota también que en en evento @change del select estamos llamando la función que creamos "changeLanguage".

  • Por último nota que en cada elemento option debe llevar un atributo value que hace referencia al lenguaje, justo como esta en la plataforma de Tolgee.

<script setup lang="ts">
// ---
</script>

<template>
  <select
    :value="tolgee.getLanguage()"
    @change="changeLanguage"
    class="p-1 rounded-md text-lg font-semibold"
  >
    <option value="es-MX">🇲🇽 Spanish</option>
    <option value="en">🇺🇲 English</option>
    <option value="fr">🇫🇷 French</option>
  </select>
</template>
Enter fullscreen mode Exit fullscreen mode

Listo, tenemos nuestro componente para cambiar de idioma nuestra app.

Ahora vamos a crear un pequeño NavBar para colocarlo.

Dentro de src/components/NavBar.vue y colocamos lo siguiente.

<script setup lang="ts">
import SelectLang from './SelectLang.vue';
</script>

<template>
  <nav
    class="flex justify-between items-center gap-5 bg-black/50 backdrop-blur-md fixed top-0 left-0 w-full p-7 px-10"
  >
    <div class="flex gap-5 items-center">
      <span>{{ $t('label_select_idiom') }}</span>

      <SelectLang />

    </div>
  </nav>
</template>
Enter fullscreen mode Exit fullscreen mode

No olvides colocar el componente Navbar.vue en src/components/MainContent.vue

Image description

Usando variables en las traducciones

Para usar variables tienes hacer configuraciones en la plataforma de Tolgee.

Tolgee siguen el formato de mensaje ICU aprende más de este formato para aprender más reglas, ya que aquí solo te voy a mostrar la más básica.

Supongamos que quieres crear algo como esto:

"Hola, 'VAR_NAME' es mi nombre"

Siendo VAR_NAME la variable que quieres mostrar y puede ser cualquier nombre.

Bueno cuando estés creando las traducciones en Tolgee, y quieras agregar una variable, lo harías de esta forma en cada traducción:

  • Se encierra la variable entre estos símbolos '{}'.
  • Nota que dentro de los corchetes esta el nombre de la variable "name". El nombre que le coloques debe ser el mismo en cada traducción y el el mismo que usaremos en nuestra app para hacer referencia a esa variable.
Hola, {name} es mi nombre.
Enter fullscreen mode Exit fullscreen mode

Ahora vamos al src/components/NavBar.vue
Vamos a crear una simple variable.

<script setup lang="ts">
// ....
const userName = 'Barry Allen'
</script>

<template>
  <!-- .... -->
</template>
Enter fullscreen mode Exit fullscreen mode

Y ahora para colocar una variable lo haremos de esta manera:

<span>{{ $t('title_navbar',{ name: userName })  }}</span>
Enter fullscreen mode Exit fullscreen mode

Seguimos mandando la key como primer parámetro, después un objeto con el nombre de la propiedad exactamente como la definiste en la plataforma de Tolgee, que en mi caso le puse '{name}'.

Y asi podemos usar variables en nuestras traducciones.

<script setup lang="ts">
import SelectLang from './SelectLang.vue';

const name = 'Barry Allen'
</script>

<template>
  <nav
    class="flex justify-between items-center gap-5 bg-black/50 backdrop-blur-md fixed top-0 left-0 w-full p-7 px-10"
  >
    <span>{{ $t('title_navbar',{ name })  }}</span>

    <div class="flex gap-5 items-center">
      <span>{{ $t('label_select_idiom') }}</span
      ><SelectLang />
    </div>
  </nav>
</template>
Enter fullscreen mode Exit fullscreen mode

Preparando para producción

Cuando vayas a desplegar tu app a producción, NO vas a incluir las variables de entorno. Esto es porque el SDK y las variables de entorno solo deben ser usadas en el desarrollo y no en producción.

Para producción debes usar los datos exportados de la plataforma de Tolgee.

Tienes estas opciones:

  1. Exportar los datos manualmente de la plataforma Tolgee.

En la plataforma de Tolgee, en el menu lateral hay una opción "Export", que te lleva a configurar que lenguajes quieres exportar y otras configuraciones.
Una vez que configuras y exportas las traducciones en archivos como por ejemplo archivos formato JSON, los colocas en la carpeta public/i18n.

Y haces unas configuraciones en el archivo src/lib/tolgee.ts algo asi.

export const tolgee = Tolgee()
  // ...
  .init({
    // ...
    staticData: {
      'es-MX': () => import('./i18n/es-MX.json'),
      fr: () => import('./i18n/fr.json'),
      en: () => import('./i18n/en.json'),
    },
  });
Enter fullscreen mode Exit fullscreen mode
  1. Usar plugin BackendFetch

Existe otra forma más fácil si es que no quieres descargar esos archivos. Y es usando el plugin BackendFetch

En la plataforma de Tolgee, ve al menú lateral y busca la sección de "Developer settings".
Una vez ahí, en la parte de "CONTENT DELIVERY" le darás al botón "+ CONTENT DELIVERY". Básicamente es para desplegar tus archivos de traducción en un almacenamiento en la nube y puedas usarlos en tu app.

Al presionar el botón te pedirá un par de configuraciones como el nombre, que lenguajes vas a desplegar, en que formato, entre otros.
Una vez que terminas de configurar eso, y presionas "SAVE", te creara una CDN la cual usaras en tu app.

Mediante el plugin de BackendFetch, le pasamos un objeto con la propiedad prefix y colocamos la CDN que creamos.

export const tolgee = Tolgee()
// ...
.use(
    BackendFetch({
      prefix: 'https://cdn.tolg.ee/19c2f74a3835f11cab85f',
    })
)
.init({
  // ....
});
Enter fullscreen mode Exit fullscreen mode

Lo mejor es que, con el BackendFetch y "Content delivery", cuando actualices tus traducciones en Tolgee, estos se reflejaran en tu app.

Ahora si puedes desplegar tu app.

🈵 Demostración simple.

https://vue-tolgee-multi-lang.netlify.app/

🈵 Código fuente.

https://github.com/Franklin361/vue-tolgee

Top comments (0)