Suporte à internacionalização
O Node.js possui muitos recursos que facilitam a escrita de programas internacionalizados. Alguns deles são:
Funções sensíveis à localidade ou compatíveis com Unicode na Especificação da Linguagem ECMAScript:
Todas as funcionalidades descritas na Especificação da API de Internacionalização ECMAScript (também conhecida como ECMA-402):
- Objeto
Intl
- Métodos sensíveis à localidade como
String.prototype.localeCompare()
eDate.prototype.toLocaleString()
- Objeto
Suporte a nomes de domínio internacionalizados (IDNs) do analisador de URL WHATWG
Edição de linha REPL mais precisa
O Node.js e o mecanismo V8 subjacente usam Componentes Internacionais para Unicode (ICU) para implementar esses recursos em código C/C++ nativo. O conjunto completo de dados ICU é fornecido pelo Node.js por padrão. No entanto, devido ao tamanho do arquivo de dados ICU, várias opções são fornecidas para personalizar o conjunto de dados ICU durante a construção ou execução do Node.js.
Opções para construir o Node.js
Para controlar como o ICU é usado no Node.js, quatro opções de configure
estão disponíveis durante a compilação. Detalhes adicionais sobre como compilar o Node.js são documentados em BUILDING.md.
--with-intl=none
/--without-intl
--with-intl=system-icu
--with-intl=small-icu
--with-intl=full-icu
(padrão)
Uma visão geral dos recursos disponíveis do Node.js e JavaScript para cada opção configure
:
Recurso | none | system-icu | small-icu | full-icu |
---|---|---|---|---|
String.prototype.normalize() | nenhum (função é no-op) | completo | completo | completo |
String.prototype.to*Case() | completo | completo | completo | completo |
Intl | nenhum (objeto não existe) | parcial/completo (depende do SO) | parcial (somente em inglês) | completo |
String.prototype.localeCompare() | parcial (não reconhece o locale) | completo | completo | completo |
String.prototype.toLocale*Case() | parcial (não reconhece o locale) | completo | completo | completo |
Number.prototype.toLocaleString() | parcial (não reconhece o locale) | parcial/completo (depende do SO) | parcial (somente em inglês) | completo |
Date.prototype.toLocale*String() | parcial (não reconhece o locale) | parcial/completo (depende do SO) | parcial (somente em inglês) | completo |
Analisador de URL Legado | parcial (sem suporte a IDN) | completo | completo | completo |
Analisador de URL WHATWG | parcial (sem suporte a IDN) | completo | completo | completo |
require('node:buffer').transcode() | nenhum (função não existe) | completo | completo | completo |
REPL | parcial (edição de linha imprecisa) | completo | completo | completo |
require('node:util').TextDecoder | parcial (suporte a codificações básicas) | parcial/completo (depende do SO) | parcial (somente Unicode) | completo |
RegExp Unicode Property Escapes | nenhum (erro RegExp inválido) | completo | completo | completo |
A designação "(não reconhece o locale)" indica que a função realiza sua operação exatamente como a versão não-Locale
da função, caso exista. Por exemplo, no modo none
, a operação de Date.prototype.toLocaleString()
é idêntica à de Date.prototype.toString()
.
Desativar todos os recursos de internacionalização (none
)
Se esta opção for escolhida, o ICU será desativado e a maioria dos recursos de internacionalização mencionados acima não estará disponível no binário node
resultante.
Construir com um ICU pré-instalado (system-icu
)
O Node.js pode ser vinculado a uma versão do ICU já instalada no sistema. Na verdade, a maioria das distribuições Linux já vem com o ICU instalado, e esta opção tornaria possível reutilizar o mesmo conjunto de dados usado por outros componentes do SO.
Funcionalidades que exigem apenas a biblioteca ICU, como String.prototype.normalize()
e o analisador WHATWG URL, são totalmente suportadas em system-icu
. Recursos que exigem dados de localidade ICU adicionais, como Intl.DateTimeFormat
podem ser total ou parcialmente suportados, dependendo da completude dos dados ICU instalados no sistema.
Incorporar um conjunto limitado de dados ICU (small-icu
)
Esta opção faz com que o binário resultante seja vinculado à biblioteca ICU estaticamente e inclua um subconjunto de dados ICU (normalmente apenas o local inglês) dentro do executável node
.
Funcionalidades que exigem apenas a biblioteca ICU, como String.prototype.normalize()
e o analisador WHATWG URL, são totalmente suportadas em small-icu
. Recursos que exigem dados de localidade ICU adicionais, como Intl.DateTimeFormat
, geralmente funcionam apenas com o local inglês:
const january = new Date(9e8)
const english = new Intl.DateTimeFormat('en', { month: 'long' })
const spanish = new Intl.DateTimeFormat('es', { month: 'long' })
console.log(english.format(january))
// Imprime "January"
console.log(spanish.format(january))
// Imprime "M01" ou "January" em small-icu, dependendo da localidade padrão do usuário
// Deve imprimir "enero"
Este modo fornece um equilíbrio entre recursos e tamanho binário.
Fornecendo dados da ICU em tempo de execução
Se a opção small-icu
for usada, ainda é possível fornecer dados de localidade adicionais em tempo de execução para que os métodos JS funcionem para todas as localidades da ICU. Supondo que o arquivo de dados esteja armazenado em /runtime/directory/with/dat/file
, ele pode ser disponibilizado para a ICU por meio de:
- A opção de configuração
--with-icu-default-data-dir
: Isso apenas incorpora o caminho do diretório de dados padrão no binário. O arquivo de dados real será carregado em tempo de execução a partir deste caminho de diretório. - A variável de ambiente
NODE_ICU_DATA
: - O parâmetro CLI
--icu-data-dir
:
Quando mais de um deles é especificado, o parâmetro CLI --icu-data-dir
tem a maior precedência, seguido pela variável de ambiente NODE_ICU_DATA
e, por fim, a opção de configuração --with-icu-default-data-dir
.
A ICU é capaz de encontrar e carregar automaticamente uma variedade de formatos de dados, mas os dados devem ser apropriados para a versão da ICU e o arquivo deve ter o nome correto. O nome mais comum para o arquivo de dados é icudtX[bl].dat
, onde X
indica a versão pretendida da ICU e b
ou l
indica a endianness do sistema. O Node.js falhará ao carregar se o arquivo de dados esperado não puder ser lido do diretório especificado. O nome do arquivo de dados correspondente à versão atual do Node.js pode ser calculado com:
;`icudt${process.versions.icu.split('.')[0]}${os.endianness()[0].toLowerCase()}.dat`
Consulte o artigo "Dados da ICU" no Guia do Usuário da ICU para obter outros formatos suportados e mais detalhes sobre os dados da ICU em geral.
O módulo npm full-icu pode simplificar bastante a instalação de dados da ICU ao detectar a versão da ICU do executável node
em execução e baixar o arquivo de dados apropriado. Após instalar o módulo por meio de npm i full-icu
, o arquivo de dados estará disponível em ./node_modules/full-icu
. Este caminho pode ser passado para NODE_ICU_DATA
ou --icu-data-dir
, conforme mostrado acima, para habilitar o suporte total para Intl
.
Incorporar o ICU inteiro (full-icu
)
Esta opção faz com que o binário resultante se vincule ao ICU estaticamente e inclua um conjunto completo de dados do ICU. Um binário criado desta forma não tem mais dependências externas e suporta todos os locais, mas pode ser bastante grande. Este é o comportamento padrão se nenhum sinalizador --with-intl
for passado. Os binários oficiais também são construídos neste modo.
Detetando suporte de internacionalização
Para verificar se o ICU está habilitado (system-icu
, small-icu
ou full-icu
), verificar simplesmente a existência de Intl
deve ser suficiente:
const hasICU = typeof Intl === 'object'
Alternativamente, verificar por process.versions.icu
, uma propriedade definida apenas quando o ICU está habilitado, também funciona:
const hasICU = typeof process.versions.icu === 'string'
Para verificar o suporte a um local não inglês (ou seja, full-icu
ou system-icu
), Intl.DateTimeFormat
pode ser um bom fator de distinção:
const hasFullICU = (() => {
try {
const january = new Date(9e8)
const spanish = new Intl.DateTimeFormat('es', { month: 'long' })
return spanish.format(january) === 'enero'
} catch (err) {
return false
}
})()
Para testes mais detalhados para suporte a Intl
, os seguintes recursos podem ser úteis: