Internacionalização
O AdonisJs tem suporte de primeira classe para internacionalização construído sobre os padrões formatjs.io.
Usando o Antl Provider, você pode facilmente traduzir números, datas e mensagens para vários idiomas.
Configuração
Como o Antl Provider não é instalado por padrão, precisamos obtê-lo do npm:
adonis install @adonisjs/antlEm seguida, precisamos registrar o provedor dentro do arquivo start/app.js:
// .start/app.js
const providers = [
'@adonisjs/antl/providers/AntlProvider'
]Seu objeto de configuração locales deve ser salvo dentro do arquivo config/app.js com as seguintes opções:
| Opção | Valor | Descrição |
|---|---|---|
locale | ISO 639 | O local padrão do aplicativo (deve ser um dos locais disponíveis em códigos ISO 639). |
loader | database ou file | O carregador a ser usado para carregar suas traduções em diferentes idiomas. |
// .config/app.js
module.exports = {
locales: {
loader: 'file',
locale: 'en'
}
}Armazenamento de Localidades
Arquivo
Ao usar o carregador file, todas as localidades são armazenadas dentro do diretório resources/locales.
Cada diretório de localidade deve conter uma lista de arquivos de tradução de grupo, como:
└── resources
└── locales
├── en
│ ├── alerts.json
│ ├── cart.json
│ └── store.json
└── fr
├── alerts.json
├── cart.json
└── store.jsonOBSERVAÇÃO
No exemplo acima, cada localidade contém 3 grupos de tradução hipotéticos: alerts, cart e store. Crie quantos arquivos de grupo por localidade conforme as necessidades do seu aplicativo.
Você também pode criar um diretório chamado fallback para armazenar mensagens que são usadas quando a mensagem para o idioma atual não pode ser encontrada:
└── resources
└── locales
├── en
│ └── messages.json
├── fallback
│ └── messages.json
└── fr
└── messages.jsonBanco de Dados
Ao usar o carregador database, todas as localidades são obtidas da tabela de banco de dados locales.
OBSERVAÇÃO
O comando adonis install cria a migração para a tabela locales.
DICA
Você sempre pode referenciar o arquivo de origem de migração mais recente no Github.
Um exemplo de tabela de banco de dados locales pode se parecer com isto:
| id | locale | group | item | text |
|---|---|---|---|---|
| 1 | en | messages | greeting | Hello {name} |
| 2 | fr | messages | greeting | Bonjour {name} |
| 3 | en | cart | total | Cart total is {total, number, usd} |
| 4 | fr | cart | total | Le panier est total {total, number, usd} |
OBSERVAÇÃO
Você deve definir um valor de grupo para cada item locales.
Acessando Localidades
Você pode acessar a localidade atual e padrão por meio do objeto Antl:
const Antl = use('Antl')
Antl.currentLocale()
Antl.defaultLocale()Sintaxe de Mensagem ICU
O AdonisJs usa o padrão da indústria sintaxe de Mensagem ICU para formatar mensagens.
Os tópicos a seguir definem o uso da sintaxe de mensagem ICU.
Valores
Para recuperar um valor de tradução, basta referenciá-lo por sua chave group.item:
// .resources/locales/en/messages.json
{
"greeting": "Hello"
}Antl.formatMessage('messages.greeting')Argumentos
Você pode passar argumentos dinâmicos para injetar em espaços reservados que são definidos por chaves { } dentro de suas mensagens:
// .resources/locales/en/messages.json
{
"greeting": "Hello {name}"
}Antl.formatMessage('messages.greeting', { name: 'virk' })Argumentos formatados
Os valores passados para uma mensagem podem ser formatados opcionalmente por tipo.
NOTA
Você deve registrar seus formatos antes de poder usá-los (consulte Registrando formatos).
Por exemplo, ao passar um número, podemos formatá-lo como uma moeda:
// .resources/locales/en/cart.json
{
"total": "Cart total is {total, number, usd}"
}Para o espaço reservado {total, number, usd} na mensagem acima:
totalé o valor passado.numberé o tipo do valor.usdé o formato para esse tipo de valor.
Como a sintaxe da mensagem ICU não entende formatos diretamente, precisamos passá-los manualmente ao formatar uma mensagem:
const Antl = use('Antl')
const Formats = use('Antl/Formats')
Antl.formatMessage(
'cart.total',
{ total: 20 },
[Formats.pass('usd', 'number')]
)No exemplo acima, estamos simplesmente chamando formatMessage com 3 argumentos:
cart.totalé a referência à mensagem a ser formatada.{ total: 20 }são os dados passados para essa mensagem.[Formats.pass('usd', 'number')]é um array de formatos possíveis.
Selecione o formato
O formato select define a saída condicional com base no valor passado:
{gender, select,
male {He}
female {She}
other {They}
} will respond shortlyDICA
Tente editar a mensagem acima no seu navegador.
Formato plural
O formato plural define opções de plurilização com base no valor passado:
{count, plural,
=0 {No candy left}
one {Got # candy left}
other {Got # candies left}
}DICA
Tente editar a mensagem acima em seu navegador.
Formatando valores
Abaixo está a lista de métodos que você pode usar para formatar mensagens ou valores brutos.
formatMessage(key, [data], [formats])
O método formatMessage espera que a key seja formatada (group.item):
const Antl = use('Antl')
Antl.formatMessage('messages.greeting')Ele também pode aceitar um objeto de data dinâmico para passar para a mensagem:
const Antl = use('Antl')
Antl.formatMessage('response.eta', { gender: 'male' })Finalmente, ele também pode aceitar uma matriz de formats para analisar os dados passados com:
const Antl = use('Antl')
const Formats = use('Antl/Formats')
Antl.formatMessage(
'cart.total',
{ total: 20 },
[
Formats.pass('usd', 'number')
]
)formatNumber(value, [options])
Formate value como um número (aceita NumberFormat options conforme definido aqui):
Antl.formatNumber(10)
// as currency
Antl.formatNumber(10, {
style: 'currency',
currency: 'usd'
})
// as percentage
Antl.formatNumber(10, {
style: 'percent'
})formatAmount(value, currency, [options])
Formatar valor com style definido como moeda:
Antl.formatAmount(100, 'usd')formatDate(value, [options])
Formatar valor como data (aceita options DateTimeFormat conforme definido aqui):
Antl.formatDate(new Date())
// pull weekday for the date
Antl.formatDate(new Date(), {
weekday: 'long'
})
// pull day only
Antl.formatDate(new Date(), {
day: '2-digit'
})formatRelative(value, [options])
Formatar uma data relativa à data atual data/hora (aceita opções RelativeFormat conforme definido aqui):
Antl.formatRelative(new Date())
// always in numeric style
Antl.formatRelative(new Date(), {
style: 'numeric'
})Registrando formatos
O método formatMessage aceita apenas uma matriz de formatos pré-registrados.
Para registrar seus formatos para um determinado tipo:
const Formats = use('Antl/Formats')
Formats.add('usd', {
style: 'currency',
currency: 'usd'
})Use-o da seguinte forma:
Antl.formatMessage(
'cart.total'
{ total: 20 },
[
Formats.pass('usd', 'number')
]
)O método Formats.pass recebe dois argumentos:
- O primeiro argumento é o formato a ser usado.
- O segundo argumento é o tipo ao qual o formato deve ser aplicado.
Vários formatos de tipo
Você pode passar vários formatos para um determinado tipo. Por exemplo:
// .resources/locales/en/cart.json
{
"total": "USD total { usdTotal, number, usd } or in GBP { gbpTotal, number, gbp }"
}Em seguida, registre os formatos usd e gbp.
Formats.add('usd', {
style: 'currency',
currency: 'usd'
})
Formats.add('gbp', {
style: 'currency',
currency: 'gbp'
})Finalmente, você pode formatar a mensagem da seguinte forma:
Antl.formatMessage(
'cart.total',
{ usdTotal: 20, gbpTotal: 13 },
[
Formats.pass('usd', 'number'),
Formats.pass('gbp', 'number')
]
)# Saída:
USD total $20.00 or in GBP £13.00Trocar localidade
O Antl Provider simplifica a formatação da localidade em tempo de execução.
Para fazer isso, basta chamar forLocale antes de formatMessage:
Antl
.forLocale('fr')
.formatMessage('response.eta')Trocar carregador
Você pode alternar entre carregadores em tempo de execução chamando o método loader:
const Antl = use('Antl')
// asynchronous
await Antl.bootLoader()
// get antl instance for a booted loader
const AntlDb = Antl.loader('database')
// all methods are available
AntlDb.formatMessage()NOTA
Sempre chame bootLoader antes de Antl.loader (você só precisa chamar bootLoader uma vez).
Localidade de solicitação Http
O Provedor Antl vincula a propriedade locale ao objeto Contexto Http:
Route.get('/', ({ locale }) => {
return `User language is ${locale}`
})A propriedade locale é resolvida da seguinte forma:
- O cabeçalho HTTP
Accept-Languageou o parâmetro de consultalangé examinado para detectar o idioma do usuário. - O idioma do usuário é comparado à lista de localidades disponíveis configuradas pelo seu aplicativo. As localidades configuradas são determinadas por mensagens salvas dentro do banco de dados ou sistema de arquivos para determinados idiomas.
- Se o idioma do usuário não for suportado pelo seu aplicativo, ele retornará para a localidade padrão definida dentro do arquivo
config/app.js.
Formatação Http
Como podemos acessar a localidade do usuário com base em convenções padrão, você pode formatar mensagens de uma das seguintes maneiras.
Importar globalmente
Você pode importar o Antl Provider globalmente e chamar manualmente o método forLocale ao formatar valores:
const Antl = use('Antl')
Route.get('/', ({ locale }) => {
return Antl
.forLocale(locale)
.formatNumber(20, { style: 'currency', currency: 'usd' })
})Instância de contexto
Você também pode usar o objeto antl que é passado para todos os manipuladores de rota como request e response:
Route.get('/', ({ antl }) => {
return antl
.formatNumber(20, { style: 'currency', currency: 'usd' })
})Por exemplo, você pode alternar a localidade para uma visualização assim:
Route.get('/', ({ antl, view }) => {
antl.switchLocale('fr')
return view.render('some-view')
}Visualização global
Como a instância de contexto antl #context-instance é compartilhada com todas as visualizações, você pode acessar seus métodos dentro de seus modelos de visualização assim:
{{ antl.formatNumber(20, currency = 'usd', style = 'currency') }}Alternativamente, você pode usar a tag @mustache para escrever várias linhas:
@mustache(antl.formatNumber(
20,
{ currency: 'usd', style: 'currency }
))OBSERVAÇÃO
Não há como alternar o carregador dentro dos modelos.