Internacionalização
A internacionalização é um processo de tradução de seus aplicativos da web para vários idiomas diferentes. Como os aplicativos da web alcançam todas as partes do mundo, a internacionalização facilita a detecção do idioma do usuário e a tradução de seus aplicativos da web para uma experiência localizada.
Drivers
- Arquivo (file)
- Banco de dados (database)
Sobre a internacionalização
- Format.js.
- Sintaxe de mensagem ICU.
- Todas as strings de localidade são armazenadas em arquivos .json dentro do diretório
resources/localesou da tabela de banco de dadoslocalescom base no driver que você está usando. - Um middleware pode ser usado para detectar o idioma do usuário em tempo de execução.
- Mensagens genéricas (mesmas para todos os idiomas) são salvas dentro do diretório
resources/locales/fallbacke do grupofallbackao usar o driver de banco de dados.
Configuração
O pacote adonis-antl não é instalado/configurado por padrão, e você precisa instalá-lo quando necessário.
# Instalando via Npm
npm i --save adonis-antl// Registrando Provedor (bootstrap/app.js)
const providers = [
// ...
'adonis-antl/providers/AntlProvider'
// ...
]// Registrando Alias (bootstrap/app.js)
const aliases = {
// ...
Antl: 'Adonis/Addons/Antl',
Formats: 'Adonis/Addons/AntlFormats'
// ...
}Com base no driver padrão, você terá que armazenar seus locais dentro do diretório resources/locales ou da tabela de banco de dados locales. Para simplificar o processo de configuração, você pode executar o seguinte comando.
// Comando de registro (bootstrap/app.js)
const commands = [
// ...
'Adonis/Commands/Antl:Setup'
// ...
]./ace antl:setup
# para driver de banco de dados
./ace antl:setup --driver=databaseO comando acima criará o diretório resources/locales/* ou as migrações para criar a tabela de banco de dados.
Configuração
A configuração para Antl Provider é salva dentro do arquivo config/app.js. A versão de lançamento 3.1 inclui a configuração por padrão, mas certifique-se sempre de mantê-la atualizada.
// config/app.js
{
locales: {
driver: 'file',
locale: 'en',
fallbackLocale: 'en'
}
}| Chave | Valores possíveis | Descrição |
|---|---|---|
| driver | arquivo, banco de dados | O driver a ser usado para ler/escrever e remover strings de localidade. |
| locale | Qualquer localidade válida | A localidade padrão a ser usada quando não for possível detectar a localidade do usuário. |
| fallbackLocale | Qualquer localidade válida | A localidade de fallback quando a localidade do usuário detectada não é suportada. |
Exemplo básico
Vamos começar com um exemplo básico de formatação de valores brutos e mensagens escritas usando Sintaxe ICU. Desta vez, vamos brincar com o Ace REPL dentro da linha de comando.
./ace replOutput
repl+>Formatando valores
const Antl = use('Antl')
Antl.formatAmount(1000, 'usd')
// ou
Antl
.for('fr') <1>
.formatAmount(1000, 'usd')- O método
forpermitirá que você alterne o idioma para uma única operação.

Formatando mensagens
Usando o driver padrão file, podemos definir localidades dentro do diretório resources/locales. Cada idioma obtém seu próprio subdiretório.
// resources/locales/en/messages.json
{
"product.cost": "{product} will cost {price, number, usd}"
}// Formatting Product Cost Message
const Antl = use('Antl')
Antl.formatMessage('messages.product.cost', { product: 'Chair', price: 29 })# Output
Chair will cost $29.00Mensagens ICU
Antes de começar a usar o provedor Antl, é crucial entender a sintaxe de mensagem ICU, pois é um padrão adotado pela web globalmente.
Literais de string
Uma mensagem pode ser apenas um literal de string em vários idiomas diferentes.
// resources/locales/en/messages.json
{
"greeting": "Hello!"
}// resources/locales/fr/messages.json
{
"greeting": "Bonjour!"
}Argumentos simples
Você também pode definir marcadores de posição para argumentos simples e passar dados dinâmicos em tempo de execução para substituí-los por seus valores reais.
// resources/locales/en/messages.json
{
"greeting": "Hello {name}"
}// resources/locales/fr/messages.json
{
"greeting": "Bonjour {name}"
}// Formatting
use('Antl').formatMessage('messages.greeting', { name: 'Virk' })
// Returns - Hello Virk ou Bonjour VirkArgumentos formatados
Argumentos formatados fornecem a funcionalidade para definir a chave, o tipo e o formato do argumento como { key, type, format }.
| Nome | Descrição |
|---|---|
| key | A chave é usada para definir o nome do espaço reservado que é usado no objeto de dados. |
| type | Define o tipo de formato para o valor. A internacionalização tem um conjunto de tipos definidos. |
| format | Format é um objeto de valores que define como formatar o tipo. Por exemplo: o tipo number pode ser formatado como porcentagem, decimal ou moeda. |
// resource/locales/en/messages.json
{
"cart.total": "Your cart total is {total, number, curr}"
}Agora, ao formatar a mensagem acima, precisamos passar o formato curr para o tipo de número, para que o formatador embutido possa formatar o total como uma moeda.
const Antl = use('Antl')
Antl.formatMessage('messages.cart.total', { price: 59 }, (message) => {
message
.passFormat('curr')
.to('number')
.withValues({ currency: 'usd' })
})Além disso, você pode passar o formato como uma expressão em vez de anexar o retorno de chamada.
const Antl = use('Antl')
Antl.formatMessage('messages.cart.total', { price: 59 }, 'curr:number[currency=usd]')Você também pode acessar antl diretamente em suas visualizações usando o global antl.
{{ antl.formatMessage('messages.cart.total', { price: 59 }, 'curr:number[currency=usd]') }}Métodos Antl
Abaixo está a lista de métodos antl.
for(locale)
Alterne temporariamente o local para uma única chamada de método.
Antl.for('fr').formatNumber(1000)getLocale
Retorna o local ativo no momento
Antl.getLocale()setLocale(locale)
Alterna permanentemente o local para todas as traduções futuras.
Antl.setLocale('fr')
Antl.formatNumber(1000)isLocale(locale)
Detecte se um local fornecido é o local ativo.
Antl.isLocale('en')locales
Retorna uma lista de locais registrados como uma matriz. É baseado nas mensagens salvas dentro de um arquivo/banco de dados.
Antl.locales()strings([group])
Retorna uma lista de strings registradas para um local fornecido/padrão. Um grupo opcional pode ser passado para buscar strings apenas para um grupo fornecido.
DICA
Este método pode ser útil para preencher um menu suspenso.
Antl.strings()
// ou
Antl.strings('messages')
// ou
Antl.for('fr').strings()pair([group])
Este método é semelhante a strings, mas retorna um objeto simples unindo objetos aninhados com um (ponto).
Antl.pair()
// ou
Antl.pair('messages')
// ou
Antl.for('fr').pair()get(key)
Obtém string bruta para uma determinada chave
Antl.get('messages.cart.total')
// ou
Antl.for('fr').get('messages.cart.total')set(group, key, value)
Atualiza/Cria valor para uma determinada chave dentro de um grupo
OBSERVAÇÃO
Este método atualizará o armazenamento subjacente para o driver ativo no momento, o que significa que atualizará a linha do banco de dados ou o sistema de arquivos.
yield Antl.set('messages', 'cart.total', 'You will be paying {total, number, curr}')remove(group, key)
Remove uma determinada chave para o local ativo no momento.
yield Antl.remove('messages', 'cart.total')load()
Este método é usado para carregar os locais para o driver ativo no momento. A primeira vez que o Antl Provider carregará todas as strings para o driver padrão definido dentro do arquivo config/app.js, enquanto você precisa chamar este método manualmente sempre que alternar o driver em tempo de execução.
DICA
O método load armazena em cache de forma inteligente os valores retornados por um driver. O que significa que chamar o método várias vezes não terá efeitos colaterais.
const db = Antl.driver('database')
yield db.load()
db.formatMessage('messages.cart.total', {total: 1000})reload
Como o método load armazena em cache os valores, você pode usar reload para recarregar à força todas as strings para um determinado driver.
const db = Antl.driver('database')
yield db.reload()
db.formatMessage('messages.cart.total', {total: 1000})Métodos do Formatador
Abaixo está a lista de métodos do formatador e opções disponíveis que você pode passar para obter a saída desejada.
formatNumber(value, options)
const Antl = use('Antl')
Antl.formatNumber(1000)
// ou
Antl.formatNumber(1000, { style: 'percent' }){{ antl.formatNumber(1000) }}
{# ou #}
{{ antl.formatNumber(1000, { style: 'percent' }) }}| Chave | Valor Padrão | Valores Possíveis | Descrição |
|---|---|---|---|
| style | decimal | decimal, currency, percentage | O estilo de formatação a ser usado para formatar o valor. |
| currency | null | A valid ISO 4217 currency code | Se estilo for moeda, esta opção deve passar um código de moeda válido a ser usado para formatar o valor. Lista de referência de código de país |
| currencyDisplay | symbol | symbol, code | Como exibir a moeda. Por exemplo, $ é o símbolo e USD é o código |
| useGrouping | true | true, false | Se deve usar separadores de agrupamento como separadores de milhares/lakhs/crores. |
| minimumIntegerDigits | 1 | 1-21 | O número mínimo de dígitos inteiros a serem usados. |
| minimumFractionDigits | floating | 0-20 | O número mínimo de dígitos de fração a serem usados. O valor padrão é 0 para números simples e dígitos de unidades menores fornecidos pela ISO 4217 para valores de moeda. |
| maximumFractionDigits | floating | 0-20 | O número máximo de dígitos de fração a serem usados. O valor padrão é maior que o valor minimumFractionDigits. |
| minimumSignificantDigits | 1 | 1-21 | O número mínimo de dígitos significativos a serem usados. |
| maximumSignificantDigits | minimumSignificantDigits | 1-21 | O número máximo de dígitos significativos a serem usados. |
formatAmount(value, currency, options)
const Antl = use('Antl')
Antl.formatAmount(1000, 'usd')
// ou
Antl.formatNumber(1000, { currencyDisplay: 'code' }){{ antl.formatAmount(1000, 'usd') }}
{# ou #}
{{ antl.formatAmount(1000, 'usd', { currencyDisplay: 'code' }) }}As opções de formatação são semelhantes a formatNumber
formatDate(value, options)
const Antl = use('Antl')
Antl.formatDate(new Date())
// ou
Antl.formatDate(new Date(), { hour12: false }){{ antl.formatDate(new Date()) }}
{# ou #}
{{ antl.formatDate(new Date(), { hour12: false }) }}| Chave | Valor Padrão | Valores Possíveis | Descrição |
|---|---|---|---|
| hour12 | locale dependent | true, false | Se deve mostrar o tempo no formato 12 horas ou não. |
| weekday | none | narrow, short, long | A representação do dia da semana. |
| era | none | narrow, short, long | A representação da era. |
| year | none | numeric, 2-digit | A representação do ano. |
| month | none | numeric, 2-digit, narrow, short, long | A representação do mês. |
| day | none | numeric, 2-digit | A representação do dia. |
| hour | none | numeric, 2-digit | A representação da hora. |
| minute | none | numeric, 2-digit | A representação do minuto. |
| second | none | numeric, 2-digit | A representação do segundo. |
| timeZoneName | none | short, long | A representação do nome do fuso horário. |
formatRelative(key, value, options)
const Antl = use('Antl')
const threeHoursPrior = new Date().setHours(new Date().getHours() - 3)
Antl.formatRelative(threeHoursPrior)
// 3 horas atrás{{ antl.formatRelative(threeHoursPrior) }}| Chave | Valor Padrão | Valores Possíveis | Descrição |
|---|---|---|---|
| units | best fit | second, minute, hour, day, month, year | A unidade de renderização específica. Por exemplo, 30 dias atrás em vez de 1 mês atrás |
| style | best fit | numeric | O estilo de renderização para o valor. Por exemplo: numeric forçará a saída para 1 day ago em vez de yesterday. |
formatMessage(key, values, [callback|options])
A formatação de uma mensagem exige que você primeiro salve suas strings dentro dos arquivos locales ou na tabela de banco de dados chamada locales e ela deve seguir a Sintaxe de Mensagem ICU.
const Antl = use('Antl')
Antl.formatMessage('messages.total', { total: 1000 })
// ou
Antl.formatMessage('messages.total', { total: 1000 }, (message) => {
message.passFormat('curr').to.('number').withValues({ currency: 'usd' })
})Como as visualizações não permitem adicionar retornos de chamada a uma função, você deve passar uma expressão de string para o método formatMessage.
{{ antl.formatMessage('messages.total', { total: 1000 }) }}
{# ou #}
{{ antl.formatMessage('messages.total', { total: 1000 }, 'curr:number[currency=usd]') }}Localidade e grupos
Ao trabalhar com o provedor Antl, suas mensagens são divididas em segmentos de localidade e grupos. Localidade se refere ao idioma para o qual você definiu a mensagem, e um grupo define a categoria da mensagem. Veja o exemplo a seguir:
----
├── locales
│ ├── en <1>
│ │ ├── messages.json <2>ené o idioma da mensagem.- O arquivo
messages.jsoné o grupo chamado messages para todas as strings definidas dentro deste arquivo.
Ao traduzir/formatar uma mensagem, você pode ser obrigado a passar uma string começando com o grupo. messages.cart.total. Também para mensagens genéricas que são as mesmas para todos os idiomas podem ser definidas ao lado da pasta/grupo fallback.
// resources/locales/fallback/messages.json
{
"greeting": "I am available to all the languages."
}Da mesma forma, você pode definir um grupo ao usar o driver database.
Tabela de localidades do banco de dados
| id | locale | group | item | texto |
|---|---|---|---|---|
| 1 | en | messages | cart.total | O total do seu carrinho é {total, number, curr} |
| 2 | fallback | messages | greeting | Estou disponível para todos os idiomas |
Detectando a localidade do usuário
Até agora, vimos as maneiras de formatar mensagens e valores usando o provedor Antl. Todos os valores serão formatados para a localidade padrão definida no arquivo config/app.js.
// config/locale.js
{
locales: {
driver: 'file',
locale: 'en',
fallbackLocale: 'en'
}
}Você pode alterar o valor da localidade padrão, e todos os valores serão formatados de acordo. Para tornar esse processo dinâmico com base no idioma do usuário, você precisa usar o middleware Antl, que detectará o idioma do usuário e o definirá como o idioma padrão para todas as traduções.
// app/Http/kernel.js
const globalMiddleware = [
// ...
'Adonis/Middleware/DetectLocale'
// ...
]Agora, todos os cabeçalhos de solicitações HTTP Accept-Language ou o parâmetro de string de consulta lang serão usados para detectar o idioma do usuário.
Trocando drivers
O provedor Antl usa o driver padrão definido dentro do arquivo config/app.js. Enquanto você pode alternar os drivers em tempo de execução para usar um driver diferente.
const db = Antl.driver('db')
yield db.load() <1>
db.formatNumber(1000, { format: 'curr' })- O método load deve ser chamado após alternar o driver, pois ele carregará e armazenará em cache todas as strings para um determinado driver.
Adicionando Drivers
Você pode estender o Antl Provider adicionando seus próprios drivers personalizados e registrando-os dentro do arquivo bootstrap/extend.js.
// bootstrap/extend.js
const Ioc = require('adonis-fold').Ioc
Ioc.extend('Adonis/Addons/Antl', 'mongo', (app) => {
return new Mongo()
})// O driver do Mongo
class Mongo {
* load () { <1>
// carregar todos os locais e retornar como um objeto aninhado
}
* set (locale, group, key, value) { <2>
// salvar novo/atualizar valor
}
* remove (locale, group, key) { <3>
// remover valor para um determinado grupo
}
}Ele deve retornar todas as strings de localidade como um objeto aninhado de
languageegroup. Por exemplojson{ "en": { "messages": { "cart.total": "Your cart total is" } } }O método
setdeve salvar o valor para uma determinada chave, grupo e localidade. Se o valor já existir, ele deve atualizá-lo.O método
removedeve excluir o valor.