Aviso: Este contenido fue traducido automáticamente. Enviar feedback

Portafolio multilingüe: llegar a una audiencia global

Rol: Desarrollador Full-Stackdic 2025

Un portafolio que habla seis idiomas, donde lo difícil fue decidir qué no traducir.


La decisión que dio forma a todo

Una persona desarrolladora en Brasil que lee sobre "data pipelines" espera ver data pipelines, no canalizaciones de datos. El término en inglés es el de la industria. Traducirlo suena raro en el mejor de los casos y condescendiente en el peor.

Ese solo ejemplo fijó la regla de todo el sistema: el trabajo no es traducir un portafolio a seis idiomas. Es decidir, término a término, qué debe sobrevivir sin traducir — y luego hacer esa decisión reproducible.

Qué hace el sistema

El sitio corre sobre next-intl con localePrefix: 'always', así que toda ruta queda anidada bajo un segmento de locale. i18n/config.ts define seis:

export const locales = ['en', 'pt-BR', 'es', 'ja', 'fr', 'de'] as const;
Fuente en inglés
Escribe una vez en inglés
DeepL o Claude
Traducción o transcreación
Reglas de localización
Aplicar reglas de términos técnicos
Archivos de locale
Seis versiones de locale

El contenido vive en archivos con sufijo de locale. hello-world.mdx es la base en inglés; hello-world.pt-BR.mdx y hello-world.ja.mdx están al lado. lib/content.ts busca el archivo del locale pedido y cae a la base en inglés cuando no existe.

Los metadatos de orden siempre vienen del archivo base. Fecha, pinned y lastUpdated se leen de la fuente en inglés sin importar el locale que se renderice, así que un post no puede ocupar una posición distinta en la lista en japonés y en la lista en inglés.

Las cadenas de interfaz caen por deep merge. i18n/request.ts carga messages/en.json como base y fusiona el catálogo del locale encima, clave por clave. Una clave ausente renderiza la cadena en inglés en vez de un error MISSING_MESSAGE, y un catálogo a medias es seguro de publicar.

El fallback está señalizado, no silencioso

Una versión anterior de esta página afirmaba que el fallback al inglés ocurría en silencio. Ese era el objetivo equivocado, y no es lo que hace el sitio.

Cuando una página cae al inglés, getContentLocaleStatus() devuelve 'fallback', y pasan dos cosas: el elemento de contenido se marca con lang="en", de modo que lectores de pantalla y buscadores sepan qué idioma están recibiendo realmente, y aparece un aviso de traducción visible sobre el contenido.

Servir inglés calladamente bajo una URL /ja/ engañaría tanto a quien lee como al crawler. Decirlo cuesta una línea de interfaz.

Dos pipelines, trabajos distintos

DeepL se encarga de la traducción directa: rápida, consistente y propensa a traducir de más el vocabulario técnico. Un agente Claude se encarga de la transcreación: adapta modismos, reordena frases para que fluyan con naturalidad y mantiene los términos técnicos en inglés según las reglas de abajo.

npm run translate      # DeepL: messages/*.json
npm run translate:mdx  # DeepL: MDX content
npm run i18n:mdx       # Claude: transcreation
npm run i18n:sync      # Claude: fill missing translations

Ambos escriben archivos con sufijo de locale junto a la fuente en inglés. Ninguno se usa a ciegas: la salida se lee antes de publicar, comprobando que las claves del frontmatter siguen en inglés, que las rutas de imagen y las URLs no cambiaron, que los bloques de código y las tablas sobrevivieron intactos y que los valores de className no se tradujeron.

Reglas de localización en la práctica

Siempre traducir: navegación y etiquetas de interfaz, contenido de artículos, campos de formulario, llamadas a la acción.

Siempre mantener en inglés: nombres de producto (Next.js, TypeScript, Claude), nombres de empresa (Nike, Meta) y el vocabulario técnico que cada audiencia ya usa en inglés: API, dashboard, data pipeline, template.

Por locale:

  • pt-BR — "dashboard" y no "painel", "template" y no "modelo", "e-commerce" y no "comércio eletrônico"
  • es — "dashboard" y no "panel de control", "marketers" y no "vendedores"
  • ja — nombres de producto en alfabeto latino, no en katakana; katakana para préstamos comunes
  • fr — "dashboard" y no "tableau de bord"; CTAs naturales ("Contactez-moi")
  • de — "du" informal, préstamos del inglés para términos técnicos, sustantivos en mayúscula
Cómo aparece 'Projects' en cada idioma

Projects

ENTraducción literal

canalizações de dados

PT-BRLocalizada (preservada)

data pipelines

Lo que me diría al principio

La localización es una decisión de producto disfrazada de decisión técnica. El pipeline fue lo fácil; las reglas sobre qué dejar en paz fueron el trabajo, y son la parte que hay que escribir, porque son la parte que una herramienta de traducción se equivocará alegremente cada vez.

La medida del éxito no es que el sitio tenga seis idiomas. Es que alguien en São Paulo o en Tokio encuentre el vocabulario que habría usado.

Una nota sobre las traducciones

Las traducciones aquí se generan por máquina y luego se revisan según las reglas anteriores. La traducción automática es un punto de partida, no un producto terminado.

Si algo suena raro en tu idioma, agradezco la corrección a través del formulario de contacto. Los hablantes nativos captan lo que la automatización pasa por alto.

Resultados

  • Seis locales: inglés, portugués (Brasil), español, japonés, francés y alemán
  • Dos pipelines: DeepL para traducción directa, un agente Claude para transcreación
  • URLs por locale con alternates hreflang para cada idioma
  • Las traducciones ausentes caen al inglés, señalizadas en vez de ocultas
  • Las reglas de localización mantienen en inglés los términos técnicos que cada audiencia espera