Cómo dividir archivos de traducción grandes: Carga por namespace para apps más rápidas
Tus archivos de traducción están matando silenciosamente los tiempos de carga de tu página. Una aplicación internacionalizada típica con más de 500 claves...
Índice
Tus archivos de traducción están matando silenciosamente los tiempos de carga de tu página. Una aplicación internacionalizada típica con más de 500 claves genera paquetes de traducción de 400-800KB por idioma. Multiplica eso por 15 idiomas y estarás sirviendo 6-12MB de traducciones — la mayoría de las cuales los usuarios nunca ven.
Esta guía cubre por qué sucede esto, cómo la división por namespace lo resuelve y los patrones de implementación prácticos que reducen las cargas de traducción en un 90-97%.
El costo oculto de los archivos de traducción monolíticos
La mayoría de las configuraciones i18n comienzan simple: un archivo translations.json por idioma. Funciona bien con 50 claves. Pero las aplicaciones en producción crecen rápido:
| Escala | Claves | Tamaño (gzip) | Impacto |
|---|---|---|---|
| App pequeña | 50 | ~2 KB | Insignificante |
| App mediana | 500 | ~18 KB | Notable en 3G |
| App grande | 2.000 | ~70 KB | Significativo |
| Empresarial | 5.000+ | ~200 KB | Cuello de botella crítico |
El problema se multiplica con varios idiomas. Una app de 500 claves en 15 idiomas significa que el CDN sirve 270KB de datos de traducción antes de que el usuario vea cualquier contenido — y solo necesitan las traducciones de la página actual (típicamente 20-50 claves, ~2KB).
Ejemplo real: Nuestra propia landing page en Better i18n creció a 699 claves en 59 namespaces. El translations.json en inglés era de 478KB. La traducción al hindi era de 841KB. Cada visitante descargaba el archivo completo, incluso si solo visitaba la página de precios (14 claves, ~2KB necesarios).
¿Qué son los namespaces en i18n?
Los namespaces son grupos lógicos dentro de tus traducciones — típicamente organizados por página, característica o dominio:
{
"hero": {
"title": "Envía traducciones más rápido",
"subtitle": "Localización impulsada por IA para apps modernas"
},
"pricing": {
"title": "Precios simples y transparentes",
"monthly": "Mensual",
"yearly": "Anual"
},
"footer": {
"copyright": "© 2026 Acme Inc.",
"privacy": "Política de Privacidad"
}
}
Librerías como i18next, react-intl y Better i18n soportan namespaces. El uso típico es useTranslations("pricing") — ya le dices al SDK qué namespace necesitas. El SDK simplemente no usa esa información para optimizar la carga.
Tres estrategias para dividir archivos de traducción
Estrategia 1: Archivos CDN por namespace
En lugar de un archivo monolítico, publica cada namespace como un archivo separado:
Antes:
/en/translations.json → 478 KB (los 59 namespaces)
Después:
/en/translations.json → 478 KB (compatibilidad)
/en/hero.json → 1.2 KB
/en/pricing.json → 2.1 KB
/en/footer.json → 0.8 KB
...59 archivos individuales
Cuando una página necesita hero + pricing + footer:
- Antes: 1 petición × 478 KB = 478 KB
- Después: 3 peticiones × ~1.4 KB prom = 4.1 KB (99% reducción)
El compromiso son más peticiones HTTP. Pero con HTTP/2 multiplexing, 3-6 peticiones pequeñas paralelas se completan más rápido que 1 petición grande. Y cada archivo de namespace se cachea independientemente.
Estrategia 2: Parámetro de consulta por namespace
Mantén la estructura CDN de archivo único pero agrega filtrado del lado del servidor:
GET /en/translations.json?ns=hero,pricing,footer
← Devuelve solo los namespaces solicitados (~4 KB)
Ventajas: Petición HTTP única, sin overhead de almacenamiento, compatible con versiones anteriores.
Desventajas: Requiere lógica en el CDN worker, complejidad de cache key, difícil cachear en el edge.
Estrategia 3: Code splitting en tiempo de build
Frameworks como Next.js y Vite pueden dividir traducciones en tiempo de build:
const i18nConfig = {
ns: ['common', 'pricing'],
resourceLoader: (language, namespace) =>
import(`./locales/${language}/${namespace}.json`),
};
Ventajas: Cero overhead en runtime, funciona con SSR/SSG, tree-shaking elimina claves no usadas.
Desventajas: Solo funciona con traducciones basadas en archivos, requiere rebuild para actualizar, no ayuda con actualizaciones OTA.
La arquitectura óptima: CDN + carga inteligente
El mejor enfoque combina archivos namespace a nivel CDN con carga inteligente a nivel SDK:
CDN publica:
├── /en/translations.json ← paquete completo (compat)
├── /en/hero.json ← por namespace
├── /en/pricing.json
├── /en/footer.json
└── /manifest.json ← incluye lista de namespaces
Comportamiento SDK:
1. Obtener manifest.json (cacheado, pequeño)
2. Detectar qué namespaces necesita la página actual
3. Obtener solo esos archivos de namespace
4. Cachear cada namespace independientemente
5. En navegación, obtener namespaces faltantes
Benchmarks de rendimiento
Medimos el impacto en nuestra landing page (699 claves, 59 namespaces, 15 idiomas):
| Métrica | Antes (monolítico) | Después (namespace) | Mejora |
|---|---|---|---|
| Carga de traducción | 478 KB | 12 KB (prom/página) | 97.5% menor |
| Time to First Byte | 180ms | 45ms | 75% más rápido |
| Ancho de banda CDN/mes | 48 GB | 2.1 GB | 95.6% menos |
| Tasa de cache hit | 62% | 94% | +32 puntos |
Cuándo NO dividir
- Apps pequeñas (< 100 claves): Las traducciones gzip son ~4KB. Dividir agrega complejidad sin beneficio.
- Sitios estáticos con SSG: Si las traducciones se empaquetan en build time, no hay payload runtime que optimizar.
- SPAs con precarga: Si tu SPA precarga todas las traducciones durante la splash screen, dividir no mejora la percepción.
Regla práctica: Si tu archivo de traducción supera 50KB gzip (~1.000+ claves), la división por namespace mejorará significativamente los tiempos de carga.
Conclusión
Los archivos de traducción grandes son un problema de rendimiento resoluble:
- Publica archivos por namespace junto a tu paquete completo
- Deja que el SDK cargue solo lo necesario basándose en llamadas
useTranslations() - Cachea independientemente para que actualizar un namespace no invalide otros
Para apps con 15+ idiomas y 500+ claves, este cambio puede reducir payloads de traducción un 90-97% y el ancho de banda CDN un 95%.