Formato de Mensajes Intl
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Formatea cadenas de mensajes ICU con marcadores de posición para números, fechas, plurales y selecciones para crear mensajes localizados.
Visión general
Objetivos
Este paquete proporciona una forma de gestionar y formatear los mensajes de texto de tu aplicación JavaScript en cadenas localizadas para los usuarios. Puedes usarlo tanto en el navegador como en el servidor mediante Node.js.
Esta implementación se basa en la propuesta Strawman, aunque difiere en algunos aspectos.
La API de IntlMessageFormat podría cambiar para mantenerse alineada con ECMA-402, pero este paquete seguirá semver.
Funcionamiento
Los mensajes se proporcionan al constructor como una cadena String o como un objeto AST pre-analizado.
const msg = new IntlMessageFormat(message, locales, [formats], [opts])
La cadena message se analiza y luego se almacena internamente en forma compilada, optimizada para que el método format() genere la cadena formateada para mostrar al usuario.
const output = msg.format(values)
Ejemplo común de uso
Un ejemplo muy frecuente es formatear mensajes con números y etiquetas de plural. Con este paquete puedes asegurarte de que la cadena se formatea correctamente según el locale del usuario, por ejemplo:
new IntlMessageFormat( `{numPhotos, plural, =0 {You have no photos.} =1 {You have one photo.} other {You have # photos.} }`, 'en-US' ).format({numPhotos: 1000})
new IntlMessageFormat( `{numPhotos, plural, =0 {Usted no tiene fotos.} =1 {Usted tiene una foto.} other {Usted tiene # fotos.} }`, 'es-ES' ).format({numPhotos: 1000})
Sintaxis de mensajes
La sintaxis de mensajes que utiliza este paquete no es propietaria; de hecho, es un estándar común que funciona en múltiples lenguajes de programación y que los traductores profesionales conocen. Este paquete utiliza la sintaxis de mensajes ICU y funciona para todos los idiomas CLDR que tienen reglas de pluralización definidas.
Características
-
Utiliza estándares de la industria: Sintaxis de mensajes ICU y datos de locale CLDR.
-
Soporta argumentos de mensaje plural, select y selectordinal.
-
Formatea números y fechas/horas en mensajes usando
Intl.NumberFormateIntl.DateTimeFormat, respectivamente. -
Optimizado para llamadas repetidas al método
format()de una instancia deIntlMessageFormat. -
Permite definir estilos/opciones de formato personalizados.
-
Soporta secuencias de escape para caracteres de sintaxis de mensajes, ej.:
"'{foo}'"producirá"{foo}"en lugar de interpretarlo como un argumentofoo.
Uso
Dependencia moderna de Intl
Este paquete asume que existe el objeto global Intl en el entorno de ejecución. Intl está presente en todos los navegadores modernos (IE11+) y Node (con ICU completo). Los métodos de Intl que utilizamos son:
-
Intl.NumberFormatpara formateo numérico (se puede aplicar polyfill usando @formatjs/intl-numberformat) -
Intl.DateTimeFormatpara formateo de fechas y horas (se puede aplicar polyfill mediante @formatjs/intl-datetimeformat) -
Intl.PluralRulespara formateo plural/ordinal (se puede aplicar polyfill mediante @formatjs/intl-pluralrules)
Carga de Intl MessageFormat en el navegador
<script src="intl-messageformat/intl-messageformat.min.js"></script>
Carga de Intl MessageFormat en Node.js
Se puede hacer de dos maneras:
import IntlMessageFormat from 'intl-messageformat'
const IntlMessageFormat = require('intl-messageformat').default
NOTA: Tu Node debe incluir ICU completo
API Pública
Constructor IntlMessageFormat
Para crear un mensaje para formatear, usa el constructor IntlMessageFormat. Este toma tres parámetros:
-
message: string | AST- Mensaje en formato string (o AST preanalizado) que sirve como patrón de formateo. -
locales: string | string[]- Cadena con etiqueta de idioma BCP 47, o array de dichas cadenas. Si no se proporciona locale, se usará el predeterminado. Cuando se pasa un array de locales, se verifica cada elemento y sus locales ancestros, devolviendo el primero con datos de locale registrados. Ver: Resolución de Locale para más detalles. -
formats?: object- Objeto opcional con opciones de formato definidas por el usuario. -
opts?: { formatters?: Formatters, ignoreTag?: boolean }- Opciones opcionales.formatters: Mapa que contiene formateadores memorizados para rendimiento.ignoreTag: Si se deben tratar etiquetas HTML/XML como literales de texto en lugar de tokens. Cuando esfalsesolo permitimos etiquetas simples sin atributos.
const msg = new IntlMessageFormat('My name is {name}.', 'en-US')
Resolución de Locale
IntlMessageFormat usa Intl.NumberFormat.supportedLocalesOf() para determinar qué datos de locale usar según el valor locales pasado al constructor. El resultado se puede obtener llamando al método prototipo resolvedOptions().
Método resolvedOptions()
Este método devuelve un objeto con los valores de opciones resueltos durante la creación de la instancia. Actualmente solo contiene la propiedad locale; ejemplo:
new IntlMessageFormat('', 'en-us').resolvedOptions().locale
Observa cómo el locale especificado en minúsculas: "en-us", se resolvió y normalizó a: "en-US".
Método format(values)
Una vez creado el mensaje, el formateo se realiza llamando al método format() de la instancia pasando una colección de values:
new IntlMessageFormat('My name is {name}.', 'en-US').format({name: 'Eric'})
Debe proporcionarse un valor para cada argumento en el patrón de mensaje usado en la construcción de la instancia.
Soporte de texto enriquecido
new IntlMessageFormat('hello <b>world</b>', 'en').format({ b: chunks => <strong>{chunks}</strong>, })
Admitimos etiquetas XML incrustadas en el mensaje, ej: this is a <b>strong</b> tag. Esto no es un método completo para incrustar HTML, sino etiquetar fragmentos de texto para contextualizar traducciones. Se aplican restricciones:
-
Se ignoran los atributos en las etiquetas HTML.
-
Las etiquetas de autocierre se tratan como literales y no son compatibles; usa placeholders ICU normales como
{placeholder}. -
Todas las etiquetas especificadas deben tener valores correspondientes, de lo contrario se lanzará error, ej:
function () { try { return new IntlMessageFormat('a <foo>strong</foo>').format() } catch (e) { return String(e) } }
- Las etiquetas XML/HTML se escapan con apóstrofes como otras construcciones ICU. Para escapar puedes hacer:
new IntlMessageFormat("I '<'3 cats").format()
new IntlMessageFormat("raw '<b>HTML</b>'").format()
new IntlMessageFormat("raw '<b>HTML</b>' with '<a>'{placeholder}'</a>'").format( {placeholder: 'some word'} )
- La incrustación de etiquetas HTML válidas es un área gris actualmente, pues no admitimos especificaciones completas HTML/XHTML/XML.
Método getAst
Devuelve el AST subyacente del mensaje compilado.
Esqueleto de Fecha/Hora/Número
Admitimos el esqueleto de números ICU y un subconjunto del esqueleto de fecha/hora para personalización avanzada de formatos.
Esqueleto de Números
Ejemplo:
new IntlMessageFormat( 'The price is: {price, number, ::currency/EUR}', 'en-GB' ).format({price: 100})
Puede encontrar el conjunto completo de opciones y sintaxis aquí
Esqueleto de Fecha/Hora
ICU ofrece una amplia gama de patrones para personalizar formatos de fecha/hora. Sin embargo, no todos están disponibles en la API Intl de ECMA402. Por lo tanto, nuestro analizador solo admite los siguientes patrones:
| Symbol | Meaning | Notes |
|---|---|---|
| G | Era designator | |
| y | year | |
| M | month in year | |
| L | stand-alone month in year | |
| d | day in month | |
| E | day of week | |
| e | local day of week | e..eee is not supported |
| c | stand-alone local day of week | c..ccc is not supported |
| a | AM/PM marker | |
| h | Hour [1-12] | |
| H | Hour [0-23] | |
| K | Hour [0-11] | |
| k | Hour [1-24] | |
| m | Minute | |
| s | Second | |
| z | Time Zone |
Ejemplo:
new IntlMessageFormat('Today is: {now, date, ::yyyyMMdd}', 'en-GB').format({ now: new Date(), })
Uso Avanzado
Pasar AST
Puedes pasar AST preanalizados a IntlMessageFormat así:
new IntlMessageFormat('hello').format() // prints out hello
// is equivalent to
import IntlMessageFormat from 'intl-messageformat'
import {parse} from '@formatjs/icu-messageformat-parser'
new IntlMessageFormat(parse('hello')).format() // prints out hello
Esto mejora el rendimiento en casos como SSR o plataformas con precarga/precompilación, ya que el AST se puede almacenar en caché.
Si todos tus mensajes están en AST, puedes crear un alias de @formatjs/icu-messageformat-parser a {default: undefined} para ahorrar bytes en el bundling.
Formateadores
Para mensajes complejos, inicializar constructores Intl.* puede ser costoso. Por ello, permitimos pasar formatters para proporcionar instancias memoizadas de estos objetos Intl. Esta opción combinada con pasar AST y fast-memoize puede acelerar el proceso hasta 30x según el benchmark más abajo.
Por ejemplo:
import IntlMessageFormat from 'intl-messageformat'
import {memoize} from '@formatjs/fast-memoize'
const formatters = {
getNumberFormat: memoize(
(locale, opts) => new Intl.NumberFormat(locale, opts)
),
getDateTimeFormat: memoize(
(locale, opts) => new Intl.DateTimeFormat(locale, opts)
),
getPluralRules: memoize((locale, opts) => new Intl.PluralRules(locale, opts)),
}
new IntlMessageFormat('hello {number, number}', 'en', undefined, {
formatters,
}).format({number: 3}) // prints out `hello, 3`
Benchmark
format_cached_complex_msg x 153,868 ops/sec ±1.13% (85 runs sampled)
format_cached_string_msg x 21,661,621 ops/sec ±4.06% (84 runs sampled)
new_complex_msg_preparsed x 719,056 ops/sec ±2.83% (78 runs sampled)
new_complex_msg x 12,844 ops/sec ±1.97% (85 runs sampled)
new_string_msg x 409,770 ops/sec ±2.57% (79 runs sampled)
complex msg format x 12,065 ops/sec ±1.66% (81 runs sampled)
complex msg w/ formatters format x 11,649 ops/sec ±2.05% (78 runs sampled)
complex preparsed msg w/ formatters format x 597,153 ops/sec ±1.46% (90 runs sampled)
complex preparsed msg w/ new formatters format x 684,263 ops/sec ±1.37% (89 runs sampled)