Construyendo una app multi-lenguaje con Vue JS. 馃寪

franklin030601

Franklin Martinez

Posted on January 13, 2024

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

馃挅 馃挭 馃檯 馃毄
franklin030601
Franklin Martinez

Posted on January 13, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related