La pregunta que se hace todo desarrollador
Estás añadiendo internacionalización a tu aplicación. Tu primera búsqueda en Google te lleva a la documentación de la API Intl de MDN. Parece prometedor: formato de fecha, formato de número, incluso formato de hora relativa, todo integrado en el navegador.
¿Por qué necesitarías algo más?
La cuestión es la siguiente: la API Intl es fantástica para formatear, pero la internacionalización no es sólo formatear. Es gestión de contenidos, flujos de trabajo de traducción, contexto para traductores, control de versiones y automatización.
Esta guía desglosa exactamente lo que el navegador puede (y no puede) hacer, y cuándo necesitas realmente un sistema de gestión de la traducción.
Qué hace realmente la API de Intl del navegador
El objeto JavaScript Intl proporciona un formato adaptado a la localización. Eso es todo. Ni traducciones, ni gestión de contenidos: formato.
Capacidades de la API internacional
Formateo numérico:
JavaScript1// US format 2new Intl.NumberFormat('en-US').format(1234567.89); 3// "1,234,567.89" 4 5// German format 6new Intl.NumberFormat('de-DE').format(1234567.89); 7// "1.234.567,89" 8 9// Currency 10new Intl.NumberFormat('ja-JP', { 11 style: 'currency', 12 currency: 'JPY' 13}).format(99000); 14// "¥99,000"
Fecha/Hora Formato:
JavaScript1const date = new Date('2026-01-15'); 2 3// US format 4new Intl.DateTimeFormat('en-US').format(date); 5// "1/15/2026" 6 7// UK format 8new Intl.DateTimeFormat('en-GB').format(date); 9// "15/01/2026" 10 11// Long format with time 12new Intl.DateTimeFormat('fr-FR', { 13 dateStyle: 'full', 14 timeStyle: 'short' 15}).format(date); 16// "mercredi 15 janvier 2026 à 00:00"
Formato de hora relativa:
JavaScript1const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }); 2 3rtf.format(-1, 'day'); // "yesterday" 4rtf.format(2, 'week'); // "in 2 weeks" 5rtf.format(-3, 'month'); // "3 months ago"
Reglas de pluralización:
JavaScript1const rules = new Intl.PluralRules('en-US'); 2rules.select(0); // "other" 3rules.select(1); // "one" 4rules.select(2); // "other" 5 6const rulesArabic = new Intl.PluralRules('ar-EG'); 7rulesArabic.select(0); // "zero" 8rulesArabic.select(1); // "one" 9rulesArabic.select(2); // "two" 10rulesArabic.select(5); // "few" 11rulesArabic.select(11); // "many"
Formateo de listas:
JavaScript1const list = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' }); 2list.format(['apples', 'oranges', 'bananas']); 3// "apples, oranges, and bananas" 4 5const listFr = new Intl.ListFormat('fr', { style: 'long', type: 'conjunction' }); 6listFr.format(['pommes', 'oranges', 'bananes']); 7// "pommes, oranges et bananes"
Esto es muy potente. ¿Qué falta?
Lo que la API Intl no puede hacer
Aquí es donde los desarrolladores se atascan. La API Intl no maneja:
1. Contenido de la traducción
La API Intl no almacena ni gestiona cadenas traducidas. Usted todavía necesita:
JavaScript1// ❌ This doesn't exist 2const t = Intl.translate('welcome.title', 'fr'); 3 4// ✅ You build this yourself 5const translations = { 6 en: { "welcome.title": "Welcome" }, 7 fr: { "welcome.title": "Bienvenue" }, 8 es: { "welcome.title": "Bienvenido" } 9};
Usted es responsable de:
- Cargar los archivos de traducción
- Organizar la estructura de claves
- Gestionar las fallbacks
- Detectar la configuración regional del usuario
- Cambiar de idioma dinámicamente
2. Formato de mensajes complejos
La API Intl no puede manejar variables en las traducciones:
JavaScript1// What you need 2"Hello {name}, you have {count} new messages" 3 4// What Intl.MessageFormat can do (newer API) 5const msg = new Intl.MessageFormat( 6 "Hello {name}, you have {count, plural, one {# message} other {# messages}}", 7 "en" 8); 9msg.format({ name: "Sarah", count: 3 }); 10// "Hello Sarah, you have 3 messages"
Pero Intl.MessageFormat sí:
- Aún en propuesta de Fase 1 (no estandarizada)
- Sólo está disponible en Chrome 117+ con una bandera
- No está listo para la producción a partir de 2026
La mayoría de los desarrolladores utilizan ICU Message Format a través de bibliotecas como @formatjs/intl o messageformat.
3. Flujo de trabajo de traducción
Cero soporte para:
- Envío de cadenas a los traductores
- Seguimiento del estado de la traducción
- Gestión de los ciclos de revisión
- Control de versiones de las traducciones
- Colaboración entre desarrolladores y lingüistas
4. Contexto para los traductores
Los traductores necesitan ver
- Dónde aparece el texto en la interfaz de usuario
- Límites de caracteres
- Capturas de pantalla
- Notas de uso
La API Intl no tiene este concepto.
5. Automatización
No hay soporte incorporado para:
- Extraer cadenas del código
- Detección automática de traducciones no realizadas
- Integración CI/CD
- Envío de actualizaciones por aire
El enfoque híbrido: Lo mejor de ambos mundos
La mayoría de las aplicaciones de producción utilizan la API Intl para el formato y una biblioteca/TMS para la gestión de las traducciones.
Ejemplo: React App con next-intl
TSX1import { useTranslations } from 'next-intl'; 2import { useFormatter } from 'next-intl'; 3 4function ProductCard({ product }) { 5 const t = useTranslations('products'); 6 const format = useFormatter(); 7 8 return ( 9 <div> 10 {/* Translation from TMS/files */} 11 <h2>{t('title', { name: product.name })}</h2> 12 13 {/* Formatting from Intl API */} 14 <p>{format.number(product.price, { style: 'currency', currency: 'USD' })}</p> 15 <time>{format.dateTime(product.releaseDate, { dateStyle: 'medium' })}</time> 16 </div> 17 ); 18}
La biblioteca (next-intl) maneja:
- La carga de archivos de traducción
- La gestión de la configuración regional actual
- Proporcionar la función
t() - Lógica de Fallback
La API Intl (a través de format) maneja:
- Formato de números
- Formato de fecha
- Símbolos de moneda
- Convenciones locales específicas
Cuando el navegador nativo es suficiente
Utilice sólo la API Intl cuando:
1. Necesidades sencillas de formato
Sólo necesita formatear correctamente fechas, números y divisas:
JavaScript1// A dashboard showing metrics 2const dashboard = { 3 users: Intl.NumberFormat(locale).format(1543298), 4 revenue: Intl.NumberFormat(locale, { style: 'currency', currency }).format(42000), 5 lastUpdated: Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(new Date()) 6};
2. Sin texto de cara al usuario
Su aplicación tiene un texto de interfaz de usuario mínima (por ejemplo, una herramienta de visualización de datos, panel de administración interna).
3. Enfoque de mercado único
Está construyendo para una región y sólo quiere un formato adecuado de números/fechas.
4. Aprendizaje/Prototipos
Está creando una demostración o aprendiendo conceptos de internacionalización.
Cuando necesita un sistema de gestión de la traducción
Utilice un TMS (como IntlPull, Lokalise o Phrase) cuando:
1. 1. Múltiples idiomas
Su objetivo son más de 3 idiomas. Gestionar manualmente los archivos de traducción se convierte rápidamente en una tarea penosa.
**Puntos débiles sin TMS
- Los traductores editan los archivos JSON/YAML directamente (rompe la sintaxis)
- No hay visibilidad de lo que está traducido y lo que falta
- No hay forma de saber "quién tradujo qué y cuándo"
- Conflictos de fusión en Git cuando trabajan varios traductores
- No hay flujo de trabajo de revisión
**Con TMS
- Interfaz web para traductores (no es necesario acceder al código)
- Seguimiento automático del estado de la traducción
- Flujo de trabajo de revisión/aprobación integrado
- Sin conflictos de fusión (TMS se encarga de la sincronización)
2. Actualizaciones frecuentes de contenidos
Se añaden funciones semanalmente. Aparecen nuevas cadenas constantemente.
Flujo de trabajo manual:
- El desarrollador añade cadenas en inglés
- Exportar cadenas a hoja de cálculo
- Enviar correo electrónico a los traductores
- Esperar respuesta
- Copiar y pegar en JSON
- Despliegue
**Flujo de trabajo de TMS
- El desarrollador envía el código con las nuevas cadenas
- TMS detecta automáticamente las traducciones que faltan
- Notificación a los traductores
- Las traducciones se sincronizan automáticamente con el código
- Despliegue
La CLI de IntlPull hace esto en un solo comando:
Terminal1npx @intlpullhq/cli upload 2# Extracts new strings, uploads to platform 3# Translators see them immediately 4 5npx @intlpullhq/cli download 6# Downloads latest translations
3. Traductores no técnicos
Sus traductores no son desarrolladores. No pueden trabajar con archivos JSON o Git.
**Lo que necesitan los traductores
- Contexto visual (¿dónde aparece este texto?)
- Límites de caracteres
- Notas de uso ("Esto aparece en los botones, sea breve")
- Capacidad para ver marcadores de posición:
Nombre,{count} - Preview of their translations in the actual UI
TMSs provide translator-friendly interfaces. IntlPull shows live previews so translators see their changes in context.
4. Machine Translation + Human Review
You want to use AI for initial translations but have humans review.
Typical workflow:
- Auto-translate with ChatGPT/DeepL for all strings
- Humans review and fix errors
- Track what's been reviewed vs auto-generated
TMSs integrate with MT engines and track translation source (human vs machine).
5. Over-the-Air Updates
You want to update translations without redeploying your app.
Use case: You launch in Spanish, but users report a translation error. Without OTA:
- Fix translation in code
- Commit to Git
- CI/CD build
- Deploy to production
- Users get update (maybe days later)
With OTA (IntlPull's approach):
- Fix translation in web UI
- Click "Publish"
- Apps fetch new translations instantly
- No deployment needed
This is critical for mobile apps where app store review takes days.
6. Collaboration at Scale
Multiple people working on translations:
- Developers adding source content
- Translators translating
- Reviewers approving
- Marketing editing copy
Without a TMS, this is chaos. Everyone's overwriting each other in Git.
Decision Framework
| Scenario | Solution | Why |
|---|---|---|
| Internal tool, 1 language, date/number formatting | Intl API only | Simple, no translation management needed |
| Marketing site, 3-5 languages, static content | Intl API + JSON files | Translation files are manageable without TMS |
| SaaS product, 10+ languages, frequent updates | Intl API + TMS | Need workflow automation, collaboration, OTA |
| Mobile app, 5+ languages, app store delays | Intl API + TMS with OTA | Can't wait for app store approval for translation fixes |
| E-commerce, 20+ languages, product descriptions | Intl API + TMS | High volume of content, need MT + human review |
Common Misconceptions
"I can build my own TMS"
You can, but it'll take 6+ months to match what existing TMSs do.
What you'll build:
- Web UI for translators
- String extraction script
- Sync logic (code ↔ platform)
- Access control (who can edit what)
- Translation memory
- Search/filtering
- Version history
- API
- CLI
That's a product, not a weekend project. Unless translation management is your core competency, use an existing solution.
"TMSs are expensive"
Some are (Lokalise, Phrase charge $500+/month).
But indie-friendly options exist:
- IntlPull: Free tier, $29/month for small teams, OTA updates included
- Tolgee: Open-source option
- Crowdin: Free for open-source projects
"TMSs lock you in"
Most support standard formats (JSON, YAML, XLIFF). You can export and migrate.
IntlPull stores translations in your Git repo by default. You own your data.
The IntlPull Approach
IntlPull combines the best of both:
Uses Intl API for formatting:
JavaScript1// IntlPull SDKs wrap Intl API for formatting 2const { t, format } = useIntlPull(); 3 4// Translation management 5t('welcome.title'); 6 7// Formatting via Intl API 8format.number(1234.56, { style: 'currency', currency: 'USD' });
Adds what's missing:
- CLI for syncing translations:
npx @intlpullhq/cli sync --watch - Web UI for translators (visual context, screenshots)
- Git integration (bi-directional sync)
- OTA updates (instant translation pushes)
- Built-in machine translation (ChatGPT, DeepL)
- Translation memory (reuse past translations)
Developer experience:
Terminal1# Day 1: Setup 2npx @intlpullhq/cli init 3 4# Daily workflow 5npx @intlpullhq/cli upload # Upload new strings 6npx @intlpullhq/cli download # Download translations 7 8# Deploy 9npm run build # Translations bundled automatically
Translators work in the web UI. Developers never leave their terminal.
Migration Path
If you're currently using just the Intl API and JSON files, here's how to add a TMS:
Step 1: Audit Current Setup
Terminal1# Count your translation files 2find . -name "*.json" -path "*/locales/*" | wc -l 3 4# Count your translation keys 5cat locales/en.json | jq 'keys | length'
If you have <100 keys and 1-2 languages, you might be fine without a TMS.
If you have 500+ keys and 3+ languages, a TMS will save you hours weekly.
Step 2: Choose a TMS
Evaluate based on:
- Pricing (check enterprise features vs your needs)
- Git integration (do you want translations in Git?)
- OTA support (mobile app? You'll want this)
- Frameworks (React, Vue, React Native SDKs?)
- API quality (good docs, rate limits)
Step 3: Import Existing Translations
Most TMSs support JSON import:
Terminal# IntlPull example npx @intlpullhq/cli import --format json --file locales/en.json --language en npx @intlpullhq/cli import --format json --file locales/fr.json --language fr
Step 4: Set Up CI/CD
Add translation sync to your pipeline:
YAML1# GitHub Actions example 2- name: Pull latest translations 3 run: npx @intlpullhq/cli download 4 env: 5 INTLPULL_API_KEY: ${{ secrets.INTLPULL_API_KEY }} 6 7- name: Build app 8 run: npm run build
Step 5: Invite Translators
Give translators access to the TMS. They'll never touch your code again.
Real-World Examples
Company A: Stuck with Browser API Only
- SaaS app, 12 languages
- Translations in JSON files in Git
- Translators submit PRs (!)
- 40% of PRs are translation updates
- Developers spend 5 hours/week reviewing translation PRs
- Translation errors make it to production regularly
Annual cost: ~260 developer hours = $26,000 (assuming $100/hour)
Company B: Using IntlPull
- SaaS app, 15 languages
- Translations managed in IntlPull
- Translators use web UI, zero PRs
- Developers run
npx @intlpullhq/cli downloadbefore deploys - OTA updates fix errors instantly
- Developers spend 0 hours on translation management
Annual cost: $348 (IntlPull: $29/month) Savings: $25,652/year
The Bottom Line
The browser Intl API is excellent at what it does: formatting. Use it for dates, numbers, currencies, and locale-aware display logic.
But internationalization is more than formatting. It's:
- Managing translated content
- Collaborating with translators
- Automating workflows
- Deploying updates quickly
For anything beyond a simple app with 1-2 languages, you'll want a translation management system.
Start with the Intl API for formatting. Add a TMS when you have more than 2 languages or more than 100 translation keys. Your future self will thank you.
Ready to stop managing translations manually?
Try IntlPull free. CLI-first TMS with Git integration, OTA updates, and visual context for translators. No credit card required.
Or stick with DIY if you're still in the "100 keys, 2 languages" zone. We'll be here when you outgrow it.
