Volver

Deja de envolver tus cadenas con llamadas a funciones

Ernest McCarter avatarErnest McCarter
gt-reacti18ntagged-templatemacrodeveloper-experience

El problema de t("Hello, {name}", { name })

Si alguna vez has internacionalizado una app de React, habrás escrito algo así:

const gt = useGT();

return <p>{gt("Hello, {name}! You have {count} items.", { name, count })}</p>;

Funciona. Pero es engorroso. Estás escribiendo a mano la sintaxis de ICU MessageFormat, duplicando cada nombre de variable en el objeto de parámetros y extrayendo t de un hook que requiere contexto de React. Para algo que se supone que debe ser una capa ligera sobre las cadenas que ya tienes, hay demasiada parafernalia.

Y va a peor. En cuanto necesitas una traducción fuera de un componente de React — en una función de utilidad, un manejador de eventos o una acción del servidor — te ves obligado a recurrir a apaños, porque los hooks no funcionan ahí.

Los literales de plantilla deberían funcionar sin problemas

Así se ve el mismo código con la macro t:

import { t } from "gt-react/browser";

return <p>{t`Hello, ${name}! You have ${count} items.`}</p>;

Eso es todo. Sintaxis estándar de literales de plantilla de JavaScript. Sin placeholders de ICU, sin objeto de parámetros, sin Hook, sin proveedor de contexto. Escribes la cadena igual que escribirías cualquier literal de plantilla, y el compilador se encarga del resto.

En tiempo de construcción, el compilador de GT transforma:

t`Hello, ${name}!`

a:

t("Hello, {0}!", { "0": name })

El tagged template es puro azúcar sintáctico: el comportamiento en tiempo de ejecución es idéntico al de llamar a t() con una cadena. Pero la experiencia de desarrollo mejora muchísimo.

Ya no depende del contexto de React

El cambio más importante aquí no es la sintaxis, sino la arquitectura. La función t exportada desde gt-react/browser no usa el contexto de React. No necesita un Hook. No necesita llamarse dentro de un componente.

Esto significa que puedes usar t en:

  • Manejadores de eventos: onClick={() => alert(tSaved!)}
  • Funciones utilitarias: function formatError(code) { return tError: $ }
  • Constantes y configuración: const LABELS = { save: tSave, cancel: tCancel }
  • Cualquier lugar del cliente donde se ejecute JavaScript

El patrón anterior — useGT() devolviendo una función limitada al contexto de React — era un cuello de botella. Hacía que la traducción pareciera algo propio de React, cuando en realidad es una cuestión de cadenas.

Registro global

Si no quieres importar t en cada archivo, puedes registrarlo de forma global:

// En el punto de entrada de tu aplicación
import "gt-react/macros";

Esto establece globalThis.t, lo que hace que el tagged template esté disponible en cualquier parte sin necesidad de importarlo. El compilador es lo bastante inteligente como para detectarlo: si t ya se importó desde una fuente de GT, no inyectará una importación duplicada. Si no, y has usado t como tagged template, el compilador inyectará la importación por ti.

La concatenación también funciona

La expansión de macros no se limita a los tagged templates. También admite literales de plantilla pasados como argumentos y concatenación de cadenas:

// Template literal como argumento — también se transforma
t(`Welcome back, ${user}`)

// Concatenación de cadenas — también se transforma
t("Hello, " + name + "! Welcome.")

Ambos se convierten en la misma llamada t("...", { ... }) en tiempo de construcción.

Primeros pasos

1. Instala la última versión de gt-react

npm install gt-react@latest

2. Usa la macro t

Puedes importarla directamente:

import { t } from "gt-react/browser";

export function Greeting({ name }) {
  return <p>{t`Hello, ${name}!`}</p>;
}

O regístralo de forma global y omite las importaciones:

// app/layout.tsx o punto de entrada
import "gt-react/macros";
// En cualquier parte de tu aplicación
export function Greeting({ name }) {
  return <p>{t`Hello, ${name}!`}</p>;
}

3. Eso es todo

El compilador de GT gestiona la transformación automáticamente durante la construcción. No se necesita ninguna configuración adicional: la expansión de macros está habilitada de forma predeterminada.


La macro t introduce un pequeño cambio en la API, pero refleja un cambio más amplio: las traducciones deben integrarse de forma natural en JavaScript, no sentirse como una solución específica de un framework. Escribe tus cadenas con naturalidad. Deja que la cadena de herramientas se encargue del resto.