API Intl.NumberFormat
Formatea números para cualquier idioma con la API de internacionalización integrada de JavaScript
Introducción
Considera mostrar el número 1234567.89 en tu aplicación. Usar toString() produce "1234567.89", que es difícil de leer y asume que todos usan puntos para decimales y leen números de izquierda a derecha. Los estadounidenses esperan "1,234,567.89", los alemanes esperan "1.234.567,89", y los usuarios en India esperan "12,34,567.89" con reglas de agrupación diferentes.
La API Intl.NumberFormat resuelve esto formateando números según las convenciones específicas del idioma. Maneja separadores de miles, puntos decimales, agrupación de dígitos, símbolos de moneda, signos de porcentaje, unidades de medida y sistemas de numeración. Esto elimina la necesidad de manipulación manual de cadenas o bibliotecas de terceros.
Esta guía explica cómo usar Intl.NumberFormat para formatear números correctamente para usuarios de todo el mundo, comenzando con el uso básico y avanzando hacia funciones avanzadas como formato de moneda, notación compacta y modos de redondeo personalizados.
Formatear un número con configuración predeterminada
Crea un formateador llamando a new Intl.NumberFormat() con una cadena de idioma, luego llama a su método format() con un número.
const formatter = new Intl.NumberFormat('en-US');
formatter.format(1234567.89);
// "1,234,567.89"
El formateador añade separadores de miles y formatea el punto decimal según el idioma. Sin especificar un idioma, el formateador usa el idioma predeterminado del entorno de ejecución, típicamente basado en la configuración del sistema del usuario.
const formatter = new Intl.NumberFormat('de-DE');
formatter.format(1234567.89);
// "1.234.567,89"
Las convenciones alemanas usan puntos para separadores de miles y comas para puntos decimales, lo contrario de las convenciones estadounidenses. El formateador maneja estas diferencias automáticamente.
Comprender los códigos de idioma
Un código de idioma identifica un idioma y opcionalmente una región, escrito como language-REGION. El idioma usa un código ISO 639-1 de dos letras como en o es. La región usa un código ISO 3166-1 de dos letras como US o MX.
new Intl.NumberFormat('en-US').format(1234.56);
// "1,234.56" (American English)
new Intl.NumberFormat('en-GB').format(1234.56);
// "1,234.56" (British English)
new Intl.NumberFormat('es-ES').format(1234.56);
// "1234,56" (European Spanish)
new Intl.NumberFormat('es-MX').format(1234.56);
// "1,234.56" (Mexican Spanish)
Ambas variantes del inglés utilizan el mismo formato, pero las variantes del español difieren. El español europeo omite los separadores de miles para números de cuatro dígitos y utiliza comas para decimales, mientras que el español mexicano sigue las convenciones americanas.
Elige las configuraciones regionales según las ubicaciones de tus usuarios o sus preferencias de idioma. Las aplicaciones normalmente determinan la configuración regional a partir de los ajustes del usuario, el idioma del navegador o la geolocalización por IP.
Elige un estilo de formato
La opción style determina la categoría de formato. Pasa un objeto de opciones como segundo argumento al constructor.
new Intl.NumberFormat('en-US', {
style: 'decimal'
}).format(1234.56);
// "1,234.56"
El estilo decimal es el predeterminado. Los otros estilos son currency, percent y unit.
Formatea moneda con símbolos y códigos
El estilo currency requiere una opción currency con un código de moneda ISO 4217.
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(1234.56);
// "$1,234.56"
El formateador añade el signo de dólar y formatea a dos decimales por defecto, el estándar para la mayoría de las monedas. Diferentes configuraciones regionales posicionan el símbolo de manera diferente.
new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
}).format(1234.56);
// "1.234,56 €"
El formato alemán coloca el símbolo del euro después de la cantidad con un espacio. La opción currency determina qué moneda mostrar, no qué convenciones de configuración regional seguir. La configuración regional determina las convenciones de formato, mientras que la moneda determina el símbolo.
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'EUR'
}).format(1234.56);
// "€1,234.56"
Las convenciones de formato americanas con el símbolo del euro producen un signo de euro antes de la cantidad, siguiendo las convenciones de colocación americanas en lugar de las europeas.
Controla el formato de visualización de moneda
La opción currencyDisplay cambia cómo aparece la moneda en la cadena formateada.
const amount = 1234.56;
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol'
}).format(amount);
// "$1,234.56"
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'code'
}).format(amount);
// "USD 1,234.56"
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'name'
}).format(amount);
// "1,234.56 US dollars"
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
currencyDisplay: 'narrowSymbol'
}).format(amount);
// "$1,234.56"
La opción symbol es la predeterminada y muestra el símbolo de moneda como $ o €. La opción code muestra el código de moneda de tres letras. La opción name escribe el nombre completo de la moneda. La opción narrowSymbol utiliza el símbolo de moneda estrecho de una configuración regional, que puede ser ambiguo pero ahorra espacio.
La diferencia entre symbol y narrowSymbol se hace evidente con monedas que comparten símbolos.
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'CAD',
currencyDisplay: 'symbol'
}).format(100);
// "CA$100.00"
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'CAD',
currencyDisplay: 'narrowSymbol'
}).format(100);
// "$100.00"
Los dólares canadienses se muestran como CA$ con la opción symbol para distinguirlos de los dólares estadounidenses, pero se muestran como solo $ con narrowSymbol.
Formatear importes de moneda negativos con notación contable
La opción currencySign controla cómo aparecen los importes negativos.
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
currencySign: 'standard'
}).format(-1234.56);
// "-$1,234.56"
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
currencySign: 'accounting'
}).format(-1234.56);
// "($1,234.56)"
La opción standard es la predeterminada y utiliza un signo menos. La opción accounting envuelve los importes negativos entre paréntesis, siguiendo las convenciones contables. Esto hace que los números negativos sean más visualmente distintos en los informes financieros.
Formatear porcentajes
El estilo percent multiplica el número por 100 y añade un signo de porcentaje.
new Intl.NumberFormat('en-US', {
style: 'percent'
}).format(0.1234);
// "12%"
new Intl.NumberFormat('en-US', {
style: 'percent'
}).format(0.1256);
// "13%"
El formateador redondea al entero más cercano de forma predeterminada. Controla los decimales con las opciones de dígitos.
new Intl.NumberFormat('en-US', {
style: 'percent',
minimumFractionDigits: 2
}).format(0.1234);
// "12.34%"
Pasa la forma decimal del porcentaje, no la forma multiplicada. El formateador maneja la multiplicación.
Formatear medidas con unidades
El estilo unit requiere una opción unit con un identificador de unidad.
new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer-per-hour'
}).format(100);
// "100 km/h"
new Intl.NumberFormat('en-GB', {
style: 'unit',
unit: 'mile-per-hour'
}).format(100);
// "100 mph"
Las unidades disponibles incluyen medidas de longitud (meter, kilometer, mile), duraciones de tiempo (second, minute, hour), almacenamiento digital (byte, kilobyte, megabyte), temperaturas (celsius, fahrenheit) y muchas otras. Las unidades compuestas como kilometer-per-hour combinan unidades simples con guiones.
La opción unitDisplay controla el formato de la unidad.
const distance = 1234.5;
new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'long'
}).format(distance);
// "1,234.5 kilometers"
new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'short'
}).format(distance);
// "1,234.5 km"
new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer',
unitDisplay: 'narrow'
}).format(distance);
// "1,234.5km"
La opción long escribe el nombre completo de la unidad. La opción short utiliza abreviaturas. La opción narrow utiliza la forma más compacta, que puede ser ambigua.
Mostrar números grandes con notación compacta
La opción notation cambia cómo se expresan los números. El valor compact utiliza formas cortas específicas del idioma para números grandes.
new Intl.NumberFormat('en-US', {
notation: 'compact'
}).format(1234567);
// "1.2M"
new Intl.NumberFormat('en-US', {
notation: 'compact'
}).format(987654321);
// "988M"
La notación compacta redondea a un decimal de forma predeterminada y añade sufijos como K para miles, M para millones y B para miles de millones. Este formato aparece en contadores de seguidores de redes sociales, contadores de visualizaciones de vídeos y paneles de análisis.
La opción compactDisplay controla la longitud del sufijo.
new Intl.NumberFormat('en-US', {
notation: 'compact',
compactDisplay: 'short'
}).format(1234567);
// "1.2M"
new Intl.NumberFormat('en-US', {
notation: 'compact',
compactDisplay: 'long'
}).format(1234567);
// "1.2 million"
La opción short es la predeterminada y utiliza símbolos. La opción long escribe la palabra de magnitud completa. Diferentes idiomas utilizan diferentes sufijos.
new Intl.NumberFormat('zh-CN', {
notation: 'compact'
}).format(123456789);
// "1.2亿"
El chino utiliza 亿 para cien millones, reflejando el sistema de agrupación numérica del idioma.
Expresar números muy grandes o pequeños en notación científica
La notación scientific expresa números como un coeficiente multiplicado por una potencia de diez.
new Intl.NumberFormat('en-US', {
notation: 'scientific'
}).format(123456789);
// "1.235E8"
new Intl.NumberFormat('en-US', {
notation: 'scientific'
}).format(0.00000123);
// "1.23E-6"
Este formato funciona bien para números muy grandes (distancias astronómicas, recuentos moleculares) y números muy pequeños (masas de partículas, mediciones a nanoescala). El exponente siempre aparece como múltiplo de uno.
Usar notación de ingeniería para aplicaciones técnicas
La notación engineering es similar a la notación científica pero restringe los exponentes a múltiplos de tres.
new Intl.NumberFormat('en-US', {
notation: 'engineering'
}).format(123456789);
// "123.457E6"
new Intl.NumberFormat('en-US', {
notation: 'engineering'
}).format(1234);
// "1.234E3"
La notación de ingeniería se alinea con los prefijos de unidades del SI (kilo, mega, giga), lo que la convierte en estándar en contextos de ingeniería y física. El coeficiente varía de 1 a 999.
Controlar decimales con dígitos fraccionarios
Las opciones minimumFractionDigits y maximumFractionDigits controlan cuántos dígitos aparecen después del punto decimal.
new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(1234.5);
// "1,234.50"
new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(1234.567);
// "1,234.57"
El mínimo asegura que aparezcan ceros finales cuando sea necesario. El máximo redondea decimales más largos. Los formateadores de moneda tienen dos decimales por defecto. Los formateadores decimales tienen cero mínimo y tres máximo por defecto.
new Intl.NumberFormat('en-US', {
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(1234.567);
// "1,235"
Establecer ambos en cero redondea al entero más cercano.
Controlar la precisión general con dígitos significativos
Las opciones minimumSignificantDigits y maximumSignificantDigits controlan la precisión total independientemente de la posición del punto decimal.
new Intl.NumberFormat('en-US', {
minimumSignificantDigits: 3,
maximumSignificantDigits: 3
}).format(1234.567);
// "1,230"
new Intl.NumberFormat('en-US', {
minimumSignificantDigits: 3,
maximumSignificantDigits: 3
}).format(0.001234);
// "0.00123"
Los dígitos significativos cuentan todos los dígitos excepto los ceros iniciales. El primer ejemplo redondea a tres dígitos, produciendo 1230. El segundo ejemplo mantiene tres dígitos después de los ceros iniciales, produciendo 0.00123.
Las opciones de dígitos significativos anulan las opciones de dígitos fraccionarios cuando se especifican ambas.
Elige una estrategia de redondeo con modos de redondeo
La opción roundingMode determina cómo se redondean los números cuando es necesario truncar.
const value = 1.5;
new Intl.NumberFormat('en-US', {
maximumFractionDigits: 0,
roundingMode: 'halfExpand'
}).format(value);
// "2"
new Intl.NumberFormat('en-US', {
maximumFractionDigits: 0,
roundingMode: 'halfTrunc'
}).format(value);
// "1"
El modo halfExpand es el predeterminado y redondea 0,5 alejándose de cero, una estrategia de redondeo común enseñada en las escuelas. El modo halfTrunc redondea 0,5 hacia cero.
Otros modos incluyen:
ceil: Siempre redondea hacia el infinito positivofloor: Siempre redondea hacia el infinito negativoexpand: Siempre redondea alejándose de cerotrunc: Siempre redondea hacia cerohalfCeil: Redondea 0,5 hacia el infinito positivohalfFloor: Redondea 0,5 hacia el infinito negativohalfEven: Redondea 0,5 hacia el número par más cercano
const prices = [1.5, 2.5, 3.5];
prices.map(price =>
new Intl.NumberFormat('en-US', {
maximumFractionDigits: 0,
roundingMode: 'halfEven'
}).format(price)
);
// ["2", "2", "4"]
El modo halfEven, también llamado redondeo bancario, reduce el sesgo de redondeo en cálculos repetidos. Al redondear 0,5, elige el número par más cercano. Esto produce 2 tanto para 1.5 como para 2.5, pero 4 para 3.5.
Las aplicaciones financieras utilizan ceil para redondear hacia arriba los cargos y floor para redondear hacia abajo los reembolsos. Las aplicaciones estadísticas utilizan halfEven para minimizar los errores acumulativos de redondeo.
Controla los separadores de miles con opciones de agrupación
La opción useGrouping controla si aparecen los separadores de miles.
new Intl.NumberFormat('en-US', {
useGrouping: true
}).format(123456);
// "123,456"
new Intl.NumberFormat('en-US', {
useGrouping: false
}).format(123456);
// "123456"
El valor true es el predeterminado. El valor false elimina todos los separadores. Los valores de cadena proporcionan un control más preciso.
new Intl.NumberFormat('en-US', {
useGrouping: 'always'
}).format(1234);
// "1,234"
new Intl.NumberFormat('en-US', {
useGrouping: 'min2'
}).format(1234);
// "1234"
El valor always utiliza separadores en todos los casos. El valor min2 omite los separadores para números de cuatro dígitos. El valor auto sigue las preferencias del idioma, que normalmente coinciden con el comportamiento de min2.
La notación compacta utiliza min2 de forma predeterminada porque los números compactos rara vez necesitan separadores internos.
Muestra los signos explícitamente con opciones de visualización de signos
La opción signDisplay controla cuándo aparecen los signos positivos y negativos.
new Intl.NumberFormat('en-US', {
signDisplay: 'auto'
}).format(100);
// "100"
new Intl.NumberFormat('en-US', {
signDisplay: 'always'
}).format(100);
// "+100"
El valor auto es el predeterminado y muestra signos menos para números negativos pero no signos más para números positivos. El valor always muestra ambos.
new Intl.NumberFormat('en-US', {
signDisplay: 'exceptZero'
}).format(0);
// "0"
new Intl.NumberFormat('en-US', {
signDisplay: 'always'
}).format(0);
// "+0"
El valor exceptZero omite los signos para valores cero incluso con el comportamiento always. Esto evita visualizaciones confusas de +0 y -0.
new Intl.NumberFormat('en-US', {
signDisplay: 'never'
}).format(-100);
// "100"
El valor never elimina los signos por completo, mostrando solo el valor absoluto.
Las aplicaciones financieras utilizan always para resaltar las ganancias con signos más. Las visualizaciones de temperatura utilizan exceptZero para evitar mostrar +0° o -0°.
Dividir la salida formateada en partes
El método formatToParts() devuelve un array de objetos que representan cada componente de la cadena formateada.
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).formatToParts(1234.56);
Esto devuelve:
[
{ type: 'currency', value: '$' },
{ type: 'integer', value: '1' },
{ type: 'group', value: ',' },
{ type: 'integer', value: '234' },
{ type: 'decimal', value: '.' },
{ type: 'fraction', value: '56' }
]
Cada objeto tiene un type que identifica el componente y un value que contiene la cadena. El type puede ser currency, integer, group, decimal, fraction, literal, minusSign, plusSign, percentSign u otros.
Esto permite aplicar estilos personalizados a componentes individuales.
const parts = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).formatToParts(1234.56);
const formatted = parts.map(part => {
if (part.type === 'currency') {
return `<span class="currency">${part.value}</span>`;
}
if (part.type === 'integer') {
return `<span class="integer">${part.value}</span>`;
}
return part.value;
}).join('');
// <span class="currency">$</span><span class="integer">1</span>,<span class="integer">234</span>.56
Esto produce HTML con componentes estilizados. El mismo enfoque funciona para aplicar diferentes colores a cantidades negativas, ampliar símbolos de moneda o animar dígitos individuales.
Formatear rangos de números
El método formatRange() formatea dos números como un rango.
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).formatRange(100, 200);
// "$100.00 – $200.00"
El formateador utiliza un separador de rango específico del idioma (una raya en inglés) e incluye ambos símbolos de moneda. Si los valores se formatean a la misma cadena, el formateador devuelve un único valor con una tilde.
new Intl.NumberFormat('en-US', {
notation: 'compact'
}).formatRange(1200, 1800);
// "~1K"
Tanto 1200 como 1800 se formatean como 1K en notación compacta, por lo que el formateador muestra aproximadamente 1K.
El método formatRangeToParts() devuelve las partes del rango.
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).formatRangeToParts(100, 200);
Esto devuelve:
[
{ type: 'currency', value: '$', source: 'startRange' },
{ type: 'integer', value: '100', source: 'startRange' },
{ type: 'decimal', value: '.', source: 'startRange' },
{ type: 'fraction', value: '00', source: 'startRange' },
{ type: 'literal', value: ' – ', source: 'shared' },
{ type: 'currency', value: '$', source: 'endRange' },
{ type: 'integer', value: '200', source: 'endRange' },
{ type: 'decimal', value: '.', source: 'endRange' },
{ type: 'fraction', value: '00', source: 'endRange' }
]
La propiedad source identifica si la parte proviene del valor inicial, el valor final o el separador de rango.
Los rangos de precios, rangos de fechas y rangos de medidas utilizan este método para un formato adecuado sensible a la configuración regional.
Inspeccionar opciones resueltas
El método resolvedOptions() devuelve un objeto que muestra las opciones reales utilizadas por el formateador.
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
formatter.resolvedOptions();
Esto devuelve:
{
locale: 'en-US',
numberingSystem: 'latn',
style: 'currency',
currency: 'USD',
currencyDisplay: 'symbol',
currencySign: 'standard',
minimumIntegerDigits: 1,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
useGrouping: 'auto',
notation: 'standard',
signDisplay: 'auto',
roundingMode: 'halfExpand'
}
El objeto incluye opciones establecidas explícitamente y valores predeterminados. La locale puede diferir de la configuración regional solicitada si el sistema resolvió a una configuración regional diferente pero compatible. El numberingSystem muestra qué caracteres de dígitos utiliza el formateador.
Este método ayuda a depurar formatos inesperados al revelar todas las configuraciones activas.
Reutilizar formateadores para mejor rendimiento
Crear una instancia de NumberFormat implica la carga de datos de configuración regional y el procesamiento de opciones. Reutiliza las instancias al formatear múltiples valores con la misma configuración.
// Inefficient: creates new formatter for each value
prices.map(price =>
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(price)
);
// Efficient: creates formatter once
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
prices.map(price => formatter.format(price));
El segundo enfoque es significativamente más rápido al formatear muchos valores. Crea formateadores fuera de bucles y funciones de renderizado de componentes.
Los motores de JavaScript modernos almacenan en caché las instancias de NumberFormat internamente, pero la reutilización explícita proporciona mejor rendimiento y código más claro.
Verificar compatibilidad del navegador
La API Intl.NumberFormat es compatible con todos los navegadores modernos. Chrome, Firefox, Safari y Edge han admitido la API básica desde 2016. Las funciones avanzadas como formatRange(), formatRangeToParts() y las opciones extendidas de roundingMode obtuvieron compatibilidad más recientemente, pero ahora están disponibles en las versiones actuales de los navegadores.
Verifica la compatibilidad usando:
if (typeof Intl !== 'undefined' && Intl.NumberFormat) {
// NumberFormat is supported
const formatter = new Intl.NumberFormat('en-US');
}
Verifica funciones específicas:
const formatter = new Intl.NumberFormat('en-US');
if (typeof formatter.formatRange === 'function') {
// formatRange is supported
}
Las aplicaciones que requieren compatibilidad con navegadores más antiguos pueden usar polyfills como @formatjs/intl-numberformat, pero la mayoría de las aplicaciones modernas pueden usar la API nativa sin alternativas.
Cuándo usar NumberFormat
Usa Intl.NumberFormat para:
- Mostrar números a los usuarios en cualquier contexto de interfaz de usuario
- Formatear cantidades de moneda en aplicaciones de comercio electrónico
- Mostrar porcentajes en paneles de análisis
- Mostrar recuentos de seguidores, recuentos de visualizaciones y otras métricas sociales
- Formatear medidas y valores científicos
- Construir aplicaciones internacionalizadas que admitan múltiples configuraciones regionales
No utilices Intl.NumberFormat para:
- Cálculos internos o procesamiento de datos
- Almacenar valores en bases de datos
- Serializar datos para APIs
- Analizar la entrada del usuario de vuelta a números
NumberFormat es una herramienta de capa de presentación. Mantén los valores numéricos sin procesar en cálculos y almacenamiento, aplicando el formato solo al mostrar valores a los usuarios.