Internacionalização e localização
A internacionalização e a localização visam ajudar você a criar aplicativos da web para várias regiões e idiomas. O suporte para i18n (abreviação de internacionalização) é fornecido pelo pacote @adonisjs/i18n
.
Localização é o processo de traduzir o texto do seu aplicativo para vários idiomas. Você deve escrever uma cópia para cada idioma e referenciá-los em modelos do Edge, mensagens de erro de validação ou usando a API
i18n
diretamente.Internacionalização é o processo de formatar valores como data, hora, números de acordo com uma região ou país específico.
Instalação
Instale e configure o pacote usando o seguinte comando:
node ace add @adonisjs/i18n
Veja as etapas executadas pelo comando add
Instala o pacote
@adonisjs/i18n
usando o gerenciador de pacotes detectado.Registra o seguinte provedor de serviços dentro do arquivo
adonisrc.ts
.ts{ providers: [ // ...other providers () => import('@adonisjs/i18n/i18n_provider') ] }
Cria o arquivo
config/i18n.ts
.Cria
detect_user_locale_middleware
dentro do diretóriomiddleware
.Registra o seguinte middleware dentro do arquivo
start/kernel.ts
.tsrouter.use([ () => import('#middleware/detect_user_locale_middleware') ])
Configuração
A configuração do pacote i18n é armazenada no arquivo config/i18n.ts
.
Veja também: Config stub
import app from '@adonisjs/core/services/app'
import { defineConfig, formatters, loaders } from '@adonisjs/i18n'
const i18nConfig = defineConfig({
defaultLocale: 'en',
formatter: formatters.icu(),
loaders: [
loaders.fs({
location: app.languageFilesPath()
})
],
})
export default i18nConfig
formatter
Define o formato a ser usado para armazenar traduções. O AdonisJS suporta o formato de mensagem ICU.
O formato de mensagem ICU é um padrão amplamente aceito e suportado por muitos serviços de tradução como Crowdin e Lokalise.
Além disso, você pode adicionar formatadores de mensagem personalizados.
defaultLocale
O local padrão para o aplicativo. Traduções e formatação de valores retornarão a esta localidade quando seu aplicativo não suportar o idioma do usuário.
fallbackLocales
Um par de chave-valor que define uma coleção de localidades e suas localidades de fallback. Por exemplo, se seu aplicativo suportar espanhol, você pode defini-lo como um fallback para o idioma Catalin.
export default defineConfig({
formatter: formatters.icu(),
defaultLocale: 'en',
fallbackLocales: {
ca: 'es' // mostrar conteúdo em espanhol quando um usuário fala catalão
}
})
supportedLocales
Uma matriz de localidades suportadas por seu aplicativo.
export default defineConfig({
formatter: formatters.icu(),
defaultLocale: 'en',
supportedLocales: ['en', 'fr', 'it']
})
Se você não definir este valor, inferiremos supportedLocales
das traduções. Por exemplo, se você tiver definido traduções para inglês, francês e espanhol, o valor de supportedLocales
será ['en', 'es', 'fr']
loaders
Uma coleção de carregadores para usar no carregamento de traduções. Por padrão, suportamos apenas o carregador do sistema de arquivos. No entanto, você pode adicionar carregadores personalizados.
Armazenando traduções
As traduções são armazenadas dentro do diretório resources/lang
, e você deve criar um subdiretório para cada idioma conforme o formato IETF language tag . Por exemplo:
resources
├── lang
│ ├── en
│ └── fr
Você pode definir traduções para uma região específica criando subdiretórios com o código da região. No exemplo a seguir, definimos traduções diferentes para Inglês (Global), Inglês (Estados Unidos) e Inglês (Reino Unido).
O AdonisJS retornará automaticamente para Inglês (Global) quando você tiver uma tradução ausente em um conjunto de traduções específicas da região.
Veja também: Código de idioma ISO
resources
├── lang
│ ├── en
│ ├── en-us
│ ├── en-uk
Formato de arquivos
As traduções devem ser armazenadas dentro de arquivos .json
ou .yaml
. Sinta-se à vontade para criar uma estrutura de diretório aninhada para melhor organização.
resources
├── lang
│ ├── en
│ │ └── messages.json
│ └── fr
│ └── messages.json
As traduções devem ser formatadas de acordo com a sintaxe de mensagem ICU.
// resources/lang/en/messages.json
{
"greeting": "Hello world"
}
// resources/lang/fr/messages.json
{
"greeting": "Bonjour le monde"
}
Resolvendo traduções
import i18nManager from '@adonisjs/i18n/services/main'
// Instância I18n para inglês
const en = i18nManager.locale('en')
// Instância I18n para francês
const fr = i18nManager.locale('fr')
Depois de ter uma instância da classe I18n
, você pode usar o método .t
para formatar uma tradução.
const i18n = i18nManager.locale('en')
i18n.t('messages.greeting') // Hello world
const i18n = i18nManager.locale('fr')
i18n.t('messages.greeting') // Bonjour le monde
Localidade de fallback
Cada instância tem um idioma de fallback pré-configurado com base na coleção config.fallbackLocales. O idioma de fallback é usado quando uma tradução está faltando para o idioma principal.
export default defineConfig({
fallbackLocales: {
'de-CH': 'de',
'fr-CH': 'fr'
}
})
const i18n = i18nManager.locale('de-CH')
i18n.fallbackLocale // de (usando coleção de fallback)
const i18n = i18nManager.locale('fr-CH')
i18n.fallbackLocale // fr (usando coleção de fallback)
const i18n = i18nManager.locale('en')
i18n.fallbackLocale // en (usando localidade padrão)
Traduções ausentes
Se uma tradução estiver ausente nos locais principal e de fallback, o método .t
retornará uma string de erro formatada da seguinte forma.
const i18n = i18nManager.locale('en')
i18n.t('messages.hero_title')
// translation missing: en, messages.hero_title
Você pode substituir esta mensagem por uma mensagem diferente ou uma string vazia definindo um valor de fallback como o segundo parâmetro.
const fallbackValue = ''
i18n.t('messages.hero_title', fallbackValue)
// saída: ''
Você também pode calcular um valor de fallback globalmente por meio do arquivo de configuração. O método fallback
recebe o caminho da tradução como o primeiro parâmetro e o código de localidade como o segundo parâmetro. Certifique-se de sempre retornar um valor de string.
import { defineConfig } from '@adonisjs/i18n'
export default defineConfig({
fallback: (identifier, locale) => {
return ''
},
})
Detectando a localidade do usuário durante uma solicitação HTTP
Durante a configuração inicial, criamos um arquivo detect_user_locale_middleware.ts
dentro do diretório ./app/middleware
. O middleware executa as seguintes ações.
Compartilhe a mesma instância com modelos Edge como uma propriedade global
i18n
.Validador de solicitação e forneça mensagens de validação usando arquivos de tradução.
Se esse middleware estiver ativo, você pode traduzir mensagens dentro de seus controladores e modelos Edge da seguinte forma.
import { HttpContext } from '@adonisjs/core/http'
export default class PostsController {
async store({ i18n, session }: HttpContext) {
session.flash('success', {
message: i18n.t('post.created')
})
}
}
<h1> {{ t('messages.heroTitle') }} </h1>
Alterando o código de detecção do idioma do usuário
Como o detect_user_locale_middleware
faz parte da base de código do seu aplicativo, você pode modificar o método getRequestLocale
e usar lógica personalizada para encontrar o idioma do usuário.
Traduzindo mensagens de validação
O detect_user_locale_middleware
se conecta ao Request validator e fornece mensagens de validação usando os arquivos de tradução.
export default class DetectUserLocaleMiddleware {
static {
RequestValidator.messagesProvider = (ctx) => {
return ctx.i18n.createMessagesProvider()
}
}
}
As traduções devem ser armazenadas dentro do arquivo validator.json
sob a chave shared
. As mensagens de validação podem ser definidas para a regra de validação ou a combinação field + rule
.
// resources/lang/en/validator.json
{
"shared": {
"fields": {
"first_name": "first name"
},
"messages": {
"required": "Enter {field}",
"username.required": "Choose a username for your account",
"email": "The email must be valid"
}
}
}
// resources/lang/fr/validator.json
{
"shared": {
"fields": {
"first_name": "Prénom"
},
"messages": {
"required": "Remplisser le champ {field}",
"username.required": "Choissisez un nom d'utilisateur pour votre compte",
"email": "L'email doit être valide"
}
}
}
Usando traduções com VineJS diretamente
Durante uma solicitação HTTP, o detect_user_locale_middleware
se conecta ao validador de solicitação e registra um provedor de mensagens personalizadas para procurar erros de validação em arquivos de tradução.
No entanto, se você usar o VineJS fora de uma solicitação HTTP, em comandos Ace ou trabalhos de fila, deverá registrar explicitamente um provedor de mensagens personalizadas ao chamar o método validator.validate
.
import { createJobValidator } from '#validators/jobs'
import i18nManager from '@adonisjs/i18n/services/main'
/**
* Obtenha uma instância i18n para uma localidade específica
*/
const i18n = i18nManager.locale('fr')
await createJobValidator.validate(data, {
/**
* Registre um provedor de mensagens para usar traduções
*/
messagesProvider: i18n.createMessagesProvider()
})
Formato de mensagem ICU
Interpolação
A sintaxe de mensagens ICU usa uma única chave para referenciar valores dinâmicos. Por exemplo:
NOTA
A sintaxe de mensagens ICU não suporta conjuntos de dados aninhados e, portanto, você só pode acessar propriedades de um objeto plano durante a interpolação.
{
"greeting": "Hello { username }"
}
{{ t('messages.greeting', { username: 'Virk' }) }}
Você também pode escrever HTML dentro das mensagens. No entanto, use três chaves dentro dos modelos Edge para renderizar HTML sem escapar dele.
{
"greeting": "<p> Hello { username } </p>"
}
{{{ t('messages.greeting', { username: 'Virk' }) }}}
Formato numérico
Você pode formatar valores numéricos dentro das mensagens de tradução usando a sintaxe {key, type, format}
. No exemplo a seguir:
- O
amount
é o valor de tempo de execução. - O
number
é o tipo de formatação. - Esqueleto numérico
{
"bagel_price": "The price of this bagel is {amount, number, ::currency/USD}"
}
{{ t('bagel_price', { amount: 2.49 }) }}
The price of this bagel is $2.49
A seguir estão exemplos de uso do formato number
com diferentes estilos de formatação e esqueletos numéricos.
Length of the pole: {price, number, ::measure-unit/length-meter}
Account balance: {price, number, ::currency/USD compact-long}
Formato de data/hora
Você pode formatar as instâncias Date ou as instâncias luxon DateTime usando a sintaxe {key, type, format}
. No exemplo a seguir:
expectedDate
é o valor de tempo de execução.date
é o tipo de formatação.- E
medium
é o formato de data.
{
"shipment_update": "Your package will arrive on {expectedDate, date, medium}"
}
{{ t('shipment_update', { expectedDate: luxonDateTime }) }}
Your package will arrive on Oct 16, 2023
Você pode usar o formato time
para formatar o valor como uma hora.
{
"appointment": "You have an appointment today at {appointmentAt, time, ::h:m a}"
}
You have an appointment today at 2:48 PM
O ICU fornece uma ampla gama de padrões para personalizar o formato de data e hora. No entanto, nem todos eles estão disponíveis via API Intl do ECMA402. Portanto, oferecemos suporte apenas aos seguintes padrões.
Símbolo | Descrição |
---|---|
G | Designador de era |
y | ano |
M | mês no ano |
L | mês autônomo no ano |
d | dia no mês |
E | dia da semana |
e | dia local da semana e..eee não é suportado |
c | dia local autônomo da semana c..ccc não é suportado |
a | Marcador AM/PM |
h | Hora [1-12] |
H | Hora [0-23] |
K | Hora [0-11] |
k | Hora [1-24] |
m | Minuto |
s | Segundo |
z | Fuso horário |
Regras plurais
A sintaxe da mensagem ICU tem suporte de primeira classe para definir as regras plurais dentro de suas mensagens. Por exemplo:
NOTA
No exemplo a seguir, usamos YAML em vez de JSON, pois escrever texto multilinha em YAML é mais fácil.
cart_summary:
"You have {itemsCount, plural,
=0 {no items}
one {1 item}
other {# items}
} in your cart"
{{ t('messages.cart_summary', { itemsCount: 1 }) }}
You have 1 item in your cart
O #
é um token especial a ser usado como um espaço reservado para o valor numérico. Ele será formatado como {key, number}
.
{{ t('messages.cart_summary', { itemsCount: 1000 }) }}
{{-- Output --}}
{{-- You have 1,000 items in your cart --}}
A regra plural usa a sintaxe {key, plural, matches}
. O matches
é um valor literal correspondido a uma das seguintes categorias plurais.
Categoria | Descrição |
---|---|
zero | Esta categoria é usada para idiomas com gramática especializada especificamente para número zero de itens. (Exemplos são árabe e letão) |
one | Esta categoria é usada para idiomas com gramática explicitamente especializada para um item. Muitos idiomas, mas não todos, usam esta categoria plural. (Muitos idiomas asiáticos populares, como chinês e japonês, não usam esta categoria.) |
two | Esta categoria é usada para idiomas com gramática explicitamente especializada para dois itens. (Exemplos são árabe e galês.) |
few | Esta categoria é usada para idiomas com gramática explicitamente especializada para um pequeno número de itens. Para alguns idiomas, isso é usado para 2-4 itens, para alguns 3-10 itens, e outros idiomas têm regras ainda mais complexas. |
many | Esta categoria é usada para idiomas com gramática especializada para um número mais significativo de itens. (Exemplos são árabe, polonês e russo.) |
other | Esta categoria é usada se o valor não corresponder a uma das outras categorias plurais. Observe que isso é usado para "plural" para idiomas (como inglês) que têm uma dicotomia simples "singular" versus "plural". |
=value | Isso é usado para corresponder a um valor específico, independentemente das categorias plurais do local atual. |
O conteúdo da tabela é referenciado em formatjs.io
Selecionar
O formato select
permite que você escolha a saída comparando um valor com uma das muitas opções. Escrever texto específico de gênero é um excelente exemplo do formato select
.
// Yaml
auto_reply:
"{gender, select,
male {He}
female {She}
other {They}
} will respond shortly."
{{ t('messages.auto_reply', { gender: 'female' }) }}
She will respond shortly.
Selecionar ordinal
O formato select ordinal
permite que você escolha a saída com base nas regras de pluralização ordinal. O formato é semelhante ao formato select
. No entanto, o valor é mapeado para uma categoria plural ordinal.
anniversary_greeting:
"It's my {years, selectordinal,
one {#st}
two {#nd}
few {#rd}
other {#th}
} anniversary"
{{ t('messages.anniversary_greeting', { years: 2 }) }}
It's my 2nd anniversary
O formato ordinal de seleção usa a sintaxe {key, selectordinal, matches}
. A correspondência é um valor literal e corresponde a uma das seguintes categorias plurais.
Categoria | Descrição |
---|---|
zero | Esta categoria é usada para idiomas com gramática especializada especificamente para zero número de itens. (Exemplos são árabe e letão.) |
one | Esta categoria é usada para idiomas com gramática explicitamente especializada para um item. Muitos idiomas, mas não todos, usam esta categoria plural. (Muitos idiomas asiáticos populares, como chinês e japonês, não usam esta categoria.) |
two | Esta categoria é usada para idiomas com gramática explicitamente especializada para dois itens. (Exemplos são árabe e galês.) |
few | Esta categoria é usada para idiomas com gramática explicitamente especializada para um pequeno número de itens. Para alguns idiomas, isso é usado para 2-4 itens, para alguns 3-10 itens, e outros idiomas têm regras ainda mais complexas. |
many | Esta categoria é usada para idiomas com gramática especializada para um número maior de itens. (Exemplos são árabe, polonês e russo.) |
other | Esta categoria é usada se o valor não corresponder a uma das outras categorias plurais. Observe que isso é usado para "plural" para idiomas (como inglês) que têm uma dicotomia simples "singular" versus "plural". |
=value | Isso é usado para corresponder a um valor específico, independentemente das categorias plurais do local atual. |
O conteúdo da tabela é referenciado em formatjs.io
Formatando valores
Os métodos abaixo usam a API Intl do Node.js, mas têm melhor desempenho. Veja benchmarks
formatNumber
Formate um valor numérico usando a classe Intl.NumberFormat
. Você pode passar os seguintes argumentos.
- O valor a ser formatado.
- Um objeto
options
opcional.
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatNumber(123456.789, {
maximumSignificantDigits: 3
})
formatCurrency
Formate um valor numérico como uma moeda usando a classe Intl.NumberFormat
. O método formatCurrency
define implicitamente a opção style = currency
.
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatCurrency(200, {
currency: 'USD'
})
formatDate
Formate uma data ou um objeto luxon date-time usando a classe Intl.DateTimeFormat
. Você pode passar os seguintes argumentos.
- O valor a ser formatado. Pode ser um objeto Date ou um objeto luxon DateTime.
- Um objeto opcional
options
.
import i18nManager from '@adonisjs/i18n/services/main'
import { DateTime } from 'luxon'
i18nManager
.locale('en')
.formatDate(new Date(), {
dateStyle: 'long'
})
// Formato luxon data hora instância
i18nManager
.locale('en')
.formatDate(DateTime.local(), {
dateStyle: 'long'
})
formatTime
Formate um valor de data para uma string de tempo usando a classe Intl.DateTimeFormat
. O método formatTime
define implicitamente a opção timeStyle = medium
.
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatTime(new Date())
formatRelativeTime
O método formatRelativeTime
usa a classe Intl.RelativeTimeFormat
para formatar um valor para uma string de representação de tempo relativa. O método aceita os seguintes argumentos.
- O valor a ser formatado. unidades oficialmente suportadas, também suportamos uma unidade
auto
adicional. opções objeto.
import { DateTime } from 'luxon'
import i18nManager from '@adonisjs/i18n/services/main'
const luxonDate = DateTime.local().plus({ hours: 2 })
i18nManager
.locale('en')
.formatRelativeTime(luxonDate, 'hours')
Defina o valor da unidade como auto
para exibir a diferença na melhor unidade correspondente.
const luxonDate = DateTime.local().plus({ hours: 2 })
I18n
.locale('en')
.formatRelativeTime(luxonDate, 'auto')
// In 2 hours 👈
const luxonDate = DateTime.local().plus({ hours: 200 })
I18n
.locale('en')
.formatRelativeTime(luxonDate, 'auto')
// In 8 days 👈
formatPlural
Encontre a categoria plural para um número usando a classe Intl.PluralRules
. Você pode passar os seguintes argumentos.
- O valor numérico para o qual encontrar a categoria plural.
- Um objeto options opcional.
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager.i18nManager('en').formatPlural(0)
// other
i18nManager.i18nManager('en').formatPlural(1)
// one
i18nManager.i18nManager('en').formatPlural(2)
// other
formatList
Formate um array de strings para uma frase usando a classe Intl.ListFormat
. Você pode passar os seguintes argumentos.
- O valor a ser formatado.
- Um objeto options opcional.
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatList(['Me', 'myself', 'I'], { type: 'conjunction' })
// Me, myself and I
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatList(['5 hours', '3 minutes'], { type: 'unit' })
// 5 hours, 3 minutes
formatDisplayNames
Formate os códigos currency
, language
, region
e calendar
para seus nomes de exibição usando a classe Intl.DisplayNames
. Você pode passar os seguintes argumentos.
- O código a ser formatado. O valor de
code
varia dependendo dotype
de formatação. - Options objeto.
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatDisplayNames('INR', { type: 'currency' })
// Indian Rupee
import i18nManager from '@adonisjs/i18n/services/main'
i18nManager
.locale('en')
.formatDisplayNames('en-US', { type: 'language' })
// American English
Configurando a extensão i18n Ally VSCode
A extensão i18n Ally para VSCode fornece um excelente fluxo de trabalho para armazenar, inspecionar e referenciar traduções com seu editor de código.
Para fazer a extensão funcionar perfeitamente com o AdonisJS, você deve criar os seguintes arquivos dentro do diretório .vscode
da raiz do seu projeto.
mkdir .vscode
touch .vscode/i18n-ally-custom-framework.yml
touch .vscode/settings.json
Copie/cole o seguinte conteúdo dentro do arquivo settings.json
.
// .vscode/settings.json
{
"i18n-ally.localesPaths": [
"resources/lang"
],
"i18n-ally.keystyle": "nested",
"i18n-ally.namespace": true,
"i18n-ally.editor.preferEditor": true,
"i18n-ally.refactor.templates": [
{
"templates": [
"{{ t('{key}'{args}) }}"
],
"include": [
"**/*.edge",
],
},
]
}
Copie/cole o seguinte conteúdo dentro do arquivo .vscode/i18n-ally-custom-framework.yml
.
// .vscode/i18n-ally-custom-framework.yml
languageIds:
- edge
usageMatchRegex:
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
sortKeys: true
Ouvindo o evento de traduções ausentes
Você pode ouvir o evento i18n:missing:translation
para ser notificado sobre as traduções ausentes no seu aplicativo.
import emitter from '@adonisjs/core/services/emitter'
emitter.on('i18n:missing:translation', function (event) {
console.log(event.identifier)
console.log(event.hasFallback)
console.log(event.locale)
})
Forçar o recarregamento de traduções
O pacote @adonisjs/i18n
lê os arquivos de tradução ao inicializar o aplicativo e os armazena na memória para acesso rápido.
No entanto, se você modificar os arquivos de tradução enquanto seu aplicativo estiver em execução, poderá usar o método reloadTranslations
para atualizar o cache na memória.
import i18nManager from '@adonisjs/i18n/services/main'
await i18nManager.reloadTranslations()
Criando um carregador de tradução personalizado
Um carregador de traduções é responsável por carregar traduções de um armazenamento persistente. Nós enviamos com um carregador de sistema de arquivos e fornecemos uma API para registrar carregadores personalizados.
Um carregador deve implementar a interface TranslationsLoaderContract e definir o método load
que retorna um objeto com par chave-valor. A chave é o código de localidade e o valor é um objeto simples com uma lista de traduções.
import type {
LoaderFactory,
TranslationsLoaderContract,
} from '@adonisjs/i18n/types'
/**
* Tipo para a configuração
*/
export type DbLoaderConfig = {
connection: string
tableName: string
}
/**
* Implementação do carregador
*/
export class DbLoader implements TranslationsLoaderContract {
constructor(public config: DbLoaderConfig) {
}
async load() {
return {
en: {
'messages.greeting': 'Hello world',
},
fr: {
'messages.greeting': 'Bonjour le monde',
}
}
}
}
/**
* Função de fábrica para referenciar o carregador
* dentro do arquivo de configuração.
*/
export function dbLoader(config: DbLoaderConfig): LoaderFactory {
return () => {
return new DbLoader(config)
}
}
No exemplo de código acima, exportamos os seguintes valores.
DbLoaderConfig
: tipo TypeScript para a configuração que você deseja aceitar.DbLoader
: a implementação dos carregadores como uma classe. Ele deve aderir à interfaceTranslationsLoaderContract
.dbLoader
: finalmente, uma função de fábrica para referenciar o carregador dentro do arquivo de configuração.
Usando o carregador
Depois que o carregador for criado, você pode referenciá-lo dentro do arquivo de configuração usando a função de fábrica dbLoader
.
import { defineConfig } from '@adonisjs/i18n'
import { dbLoader } from 'my-custom-package'
const i18nConfig = defineConfig({
loaders: [
dbLoader({
connection: 'pg',
tableName: 'translations'
})
]
})
Criando um formatador de tradução personalizado
Os formatadores de tradução são responsáveis por formatar as traduções de acordo com um formato específico. Nós enviamos com uma implementação para a sintaxe de mensagem ICU e fornecemos APIs adicionais para registrar formatadores personalizados.
Um formatador deve implementar a interface TranslationsFormatterContract e definir o método format
para formatar uma mensagem de tradução.
import type {
FormatterFactory,
TranslationsLoaderContract,
} from '@adonisjs/i18n/types'
/**
* Implementação do formatador
*/
export class FluentFormatter implements TranslationsFormatterContract {
format(
message: string,
locale: string,
data?: Record<string, any>
): string {
// retorna valor formatado
}
}
/**
* Função de fábrica para referenciar o formatador
* dentro do arquivo de configuração.
*/
export function fluentFormatter(): FormatterFactory {
return () => {
return new FluentFormatter()
}
}
Usando o formatador
Depois que o formatador for criado, você pode referenciá-lo dentro do arquivo de configuração usando a função de fábrica fluentFormatter
.
import { defineConfig } from '@adonisjs/i18n'
import { fluentFormatter } from 'my-custom-package'
const i18nConfig = defineConfig({
formatter: fluentFormatter()
})