Intl MessageFormat
Esta página foi traduzida por PageTurner AI (beta). Não é oficialmente endossada pelo projeto. Encontrou um erro? Reportar problema →
Formata strings de mensagem ICU com espaços reservados para números, datas, plural e select para criar mensagens localizadas.
Visão Geral
Objetivos
Este pacote visa fornecer uma forma de gerenciar e formatar mensagens de string do seu aplicativo JavaScript em textos localizados para os usuários. Você pode usar este pacote no navegador e no servidor via Node.js.
Esta implementação é baseada na proposta Strawman, mas existem alguns pontos onde esta implementação diverge.
A API IntlMessageFormat pode mudar para se manter alinhada com a ECMA-402, mas este pacote seguirá semver.
Funcionamento
As mensagens são fornecidas ao construtor como uma string String ou um objeto AST pré-analisado.
const msg = new IntlMessageFormat(message, locales, [formats], [opts])
A string message é analisada e armazenada internamente em formato compilado, otimizado para o método format() produzir a string formatada para exibição ao usuário.
const output = msg.format(values)
Exemplo Comum de Uso
Um exemplo muito comum é formatar mensagens com números e rótulos de plural. Com este pacote você garante que o texto seja formatado corretamente para o idioma do usuário, por exemplo:
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})
Sintaxe da Mensagem
A sintaxe de mensagem utilizada não é proprietária - é um padrão comum que funciona entre linguagens de programação e conhecido por tradutores profissionais. Este pacote utiliza a sintaxe de mensagem ICU e funciona para todos os idiomas CLDR com regras de pluralização definidas.
Recursos
-
Utiliza padrões do setor: Sintaxe de mensagem ICU e dados de localidade CLDR.
-
Suporta argumentos de mensagem plural, select e selectordinal.
-
Formata números e datas/horas em mensagens usando
Intl.NumberFormateIntl.DateTimeFormat, respectivamente. -
Otimizado para chamadas repetidas ao método
format()de instânciasIntlMessageFormat. -
Permite definir estilos/opções de formatação personalizados.
-
Suporta sequências de escape para caracteres de sintaxe, ex.:
"'{foo}'"produz"{foo}"na saída formatada em vez de interpretar como argumentofoo.
Uso
Dependência Moderna Intl
Este pacote assume que o objeto global Intl existe no runtime. Intl está presente em todos os navegadores modernos (IE11+) e Node (com ICU completo). Os métodos Intl utilizados são:
-
Intl.NumberFormatpara formatação numérica (pode ser preenchido via polyfill usando @formatjs/intl-numberformat) -
Intl.DateTimeFormatpara formatação de datas/horas (pode ser polipreenchido usando @formatjs/intl-datetimeformat) -
Intl.PluralRulespara formatação plural/ordinal (pode ser polipreenchido usando @formatjs/intl-pluralrules)
Carregando Intl MessageFormat no navegador
<script src="intl-messageformat/intl-messageformat.min.js"></script>
Carregando Intl MessageFormat no Node.js
Faça um dos seguintes:
import IntlMessageFormat from 'intl-messageformat'
const IntlMessageFormat = require('intl-messageformat').default
NOTA: Seu Node deve incluir ICU completo
API Pública
Construtor IntlMessageFormat
Para criar uma mensagem para formatação, use o construtor IntlMessageFormat. Ele recebe três parâmetros:
-
message: string | AST- Mensagem em string (ou AST pré-analisada) que serve como padrão de formatação. -
locales: string | string[]- String com tag de idioma BCP 47 ou array dessas strings. Se não fornecido, será usado o locale padrão. Com array, cada item e seus locais ancestrais são verificados, retornando o primeiro com dados registrados. Veja: Resolução de Locale para detalhes. -
formats?: object- Objeto opcional com opções de estilo definidas pelo usuário. -
opts?: { formatters?: Formatters, ignoreTag?: boolean }- Opções opcionais.formatters: Mapa contendo formatadores memorizados para desempenho.ignoreTag: Trata tags HTML/XML como literais em vez de tokens. Quandofalse, permite apenas tags simples sem atributos.
const msg = new IntlMessageFormat('My name is {name}.', 'en-US')
Resolução de Locale
IntlMessageFormat usa Intl.NumberFormat.supportedLocalesOf() para determinar os dados de locale baseados no valor locales passado ao construtor. O resultado pode ser obtido via método resolvedOptions().
Método resolvedOptions()
Retorna um objeto com as opções resolvidas durante a criação da instância. Atualmente contém apenas a propriedade locale:
new IntlMessageFormat('', 'en-us').resolvedOptions().locale
Note como o locale especificado em minúsculas "en-us" foi resolvido e normalizado para "en-US".
Método format(values)
Após criar a mensagem, formate-a chamando format() na instância com uma coleção de values:
new IntlMessageFormat('My name is {name}.', 'en-US').format({name: 'Eric'})
Um valor deve ser fornecido para cada argumento no padrão de mensagem usado no construtor.
Suporte a Rich Text
new IntlMessageFormat('hello <b>world</b>', 'en').format({ b: chunks => <strong>{chunks}</strong>, })
Suportamos tags XML incorporadas na mensagem, ex: this is a <b>strong</b> tag. Isto não se destina a ser um método completo para incorporar HTML, mas sim para marcar trechos específicos de texto para que a tradução possa ser mais contextual. Portanto, aplicam-se as seguintes restrições:
-
Atributos em tags HTML são ignorados.
-
Tags auto-fechadas são tratadas como literais (não suportadas) - use placeholders ICU como
{placeholder}. -
Todas as tags devem ter valores correspondentes - ausência causa erro:
function () { try { return new IntlMessageFormat('a <foo>strong</foo>').format() } catch (e) { return String(e) } }
- Tags XML/HTML são escapadas com apóstrofes como outros constructs ICU. Exemplo de escape:
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'} )
- Tags HTML válidas incorporadas são uma área cinzenta atualmente (suporte limitado à especificação completa).
Método getAst
Retorna a AST subjacente da mensagem compilada.
Esqueleto de Data/Hora/Número
Suportamos o esqueleto de números do ICU e um subconjunto do esqueleto de data/hora para personalização avançada de formatos.
Esqueleto de Número
Exemplo:
new IntlMessageFormat( 'The price is: {price, number, ::currency/EUR}', 'en-GB' ).format({price: 100})
O conjunto completo de opções e sintaxe pode ser encontrado aqui
Esqueleto de Data/Hora
O ICU oferece uma ampla variedade de padrões para personalizar formatos de data e hora. Entretanto, nem todos estão disponíveis através da API Intl do ECMA402. Portanto, nosso analisador suporta apenas os seguintes padrões:
| 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 |
Exemplo:
new IntlMessageFormat('Today is: {now, date, ::yyyyMMdd}', 'en-GB').format({ now: new Date(), })
Uso Avançado
Passando AST
Você pode passar ASTs pré-analisadas para o IntlMessageFormat desta forma:
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
Isso melhora o desempenho em casos como SSR ou plataformas com suporte a pré-carregamento/pré-compilação, pois a AST pode ser armazenada em cache.
Se todas suas mensagens estiverem em ASTs, você pode criar um alias para @formatjs/icu-messageformat-parser como {default: undefined} para economizar bytes no empacotamento.
Formatadores
Para mensagens complexas, inicializar construtores Intl.* pode ser custoso. Por isso, permitimos que o usuário passe formatters para fornecer instâncias memoizadas desses objetos Intl. Esta opção combinada com passar AST e fast-memoize pode acelerar em até 30x conforme o benchmark abaixo.
Por exemplo:
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)