Com a crescente de setores com demanda por soluções digitais em todo o mundo, atender públicos de diversas localidades é cada vez mais necessário. Na busca por atingir maior alcance uma das praticas mais populares é a Internacionalização. A internacionalização, segundo o dicionário, ação de se tornar ou de tornar algo internacional, também conhecida i18n, é um processo que vem ganhado força no desenvolvimento de soluções. Mirando estar preparada para o máximo de usuários, plataformas de todos os tipos tem buscado incluir APIs com sensibilidade linguística de forma que atendam não só uma grande quantidade de línguas, mas também suas variações entre localidades.
Para entender melhor a Internacionalização, é importante entender a Localização. Localização, também conhecido como l10n, refere-se ao processo de adaptação de um produto de forma que este esteja em conformidade com linguagem, cultura e outros requerimentos de um específico mercado alvo(um local). Alguns erroneamente entendem o processo como a simples tradução, mas na realidade o processo inclui formatação de números, datas e horários, moedas, disposição de teclado, formas de organização, orientação da escrita, entre outros. Com isso em mente, pensemos a Localização aplicado de forma global e teremos a Internacionalização.
Atualmente, a Internacionalização já alcançou um grande mercado. Plataformas que incluem suporte para o i18n incluem: dispositivos móveis Android e iOS; frontend frameworks como React, Angular, Vue; e no backend linguagens como Python, Java, PHP, Ruby, Go e frameworks baseados nessas linguagens; até mesmo a linguagem multiplataforma Flutter. Além disso, bibliotecas independentes tem se proposto a disponibilizar opções para a implementação do processo.
Como amostra, vamos observar a API nativa do npm(gerenciador de pacotes node) para aplicações Javascript:
O objeto Intl
Em Javascript, a internacionalização pode ser aplicada a partir do objeto Intl
que guarda construtores para as diversas funcionalidades da implementação. (Se ainda não sabe o que seriam contrutores, te convido a ler meu artigo Contextos em Javascript. Os construtores dentro de Int
recebem dois argumentos: o local e as opções.
Local: uma string que corresponde a uma tag de linguagem BCP 47 ou uma lista dessas tags. Caso esse argumento não seja passado, o local padrão usado é o do runtime.
Opções: um objeto opcional com propriedades que variam de acordo com o construtor em uso.
Intl.Collator
O construtor Int.Collator
torna possível a comparação de strings com sensibilidade linguística. Um ótimo caso de uso é a organização de listas a partir de comparações linguísticas.
const characters = ['a', '手に', '大人', 'b', '金魚', 'きんぎょ']
function compare(language, characters){
return characters.sort(new Intl.Collator(language).compare)
}
console.log(compare('pt', characters))
console.log(compare('zh', characters))
console.log(compare('ja', characters))
// Saída Esperada
// [ 'a', 'b', 'きんぎょ', '大人', '手に', '金魚' ]
// [ '大人', '金魚', '手に', 'a', 'b', 'きんぎょ' ]
// [ 'a', 'b', 'きんぎょ', '金魚', '手に', '大人' ]
Intl.DateTimeFormat
O construtor Int.DateTimeFormat
torna possível a formatação de datas com sensibilidade linguística. Abaixo podemos observar as variações de configuração que vão desde escrita por extenso, quanto timezones e mais.
const date = new Date(Date.UTC(1994, 08, 14, 15, 45, 13));
function format(language, options){
return new Intl.DateTimeFormat(language, options).format(date)
}
console.log(format('en-US'));
console.log(format('ar', { dateStyle: 'full' }));
console.log(format('pt', { dateStyle: 'full', timeStyle: 'long', timeZone: 'America/Bahia' })
);
// Saída esperada:
// "9/14/1994"
// "الأربعاء، 14 سبتمبر 1994"
// "quarta-feira, 14 de setembro de 1994 às 12:45:13 BRT"
Intl.ListFormat
O construtor Int.ListFormat
torna possível a formatação de listas com sensibilidade linguística. No caso em específico abaixo vemos as diferenças entre línguas que não usam conjunções da mesma forma.
const fruits = ['Banana', 'Grape', 'Lime'];
function format(language, options){
return new Intl.ListFormat(language, options).format(fruits)
}
console.log(format('en', { style: 'long', type: 'conjunction' }));
console.log(format('tr', { type: 'conjunction' }));
console.log(format('ar-SU', { type: 'conjunction' }));
// Saída esperada:
// "Banana, Grape, and Lime"
// "Banana, Grape ve Lime"
// "Banana وGrape وLime"
Intl.NumberFormat
O construtor Int.NumberFormat
torna possível a formatação de números com sensibilidade linguística. Com este construtor, fica fácil formatar dinheiro em variados estilos e línguas .
const number = 123456.789;
console.log(new Intl.NumberFormat("ar-EG").format(number));
console.log(new Intl.NumberFormat("ja-JP", { style: 'currency', currency: 'JPY'}).format(number));
// Saída esperada:
// "¥123,457"
// "١٢٣٤٥٦٫٧٨٩"
Intl.PluralRules
O construtor Int.PluralRules
torna possível a formatação de plural e regras de linguagens relacionadas a plurais. Cada lugar tem suas próprias formas de regras sendo algo extremamente variável e relativo à localidade.
const arCardinalRules = new Intl.PluralRules("ar-EG");
console.log(arCardinalRules.select(0)); // "zero"
console.log(arCardinalRules.select(1)); // "one"
console.log(arCardinalRules.select(2)); // "two"
console.log(arCardinalRules.select(6)); // "few"
console.log(arCardinalRules.select(18)); // "many"
Intl.RelativeTimeFormat
O construtor Intl.RelativeTimeFormat
torna possível a formatação de tempo com sensibilidade linguística. Aqui conseguimos variações linguístivas baseadas no conceito de tempo relativo bem facilmente.
function createFormatter(language, options){
return new Intl.RelativeTimeFormat(language, options);
}
const ptFormatter = createFormatter('pt', { style: 'long' });
const enFormatter = createFormatter('en', { style: 'long' });
const esFormatter = createFormatter('es', { numeric: 'auto' });
console.log(ptFormatter.format(3, 'quarter'));
console.log(enFormatter.format(-1, 'day'));
console.log(esFormatter.format(2, 'day'));
// Saída Esperada
// "em 3 trimestres"
// "1 day ago"
// "pasado mañana"
Intl.Segmenter
O construtor Intl.Segmenter
torna possível a segmentação de textos, de forma que é capaz extrair itens significativos como palavras e sentenças.
const segmenterPt = new Intl.Segmenter('pt', { granularity: 'sentence' });
const string = 'Olha lá. Que homem alto!';
const iterator1 = segmenterFr.segment(string1)[Symbol.iterator]();
console.log(iterator1.next().value.segment);
console.log(iterator1.next().value.segment);
// Saída Esperada
// "Olha lá. "
// "Que homem alto!"
O processo de Internacionalização, como podemos ver, envolve um trabalho cuidadoso de adaptação aos locais alvos. Por fim, basta saber a forma de implementação na linguagem de programação alvo. Isso é tudo, pessoal!