Flutter — Traduções: passo a passo
Se você está lendo isso, provavelmente já conhece os benefícios de criar um aplicativo internacionalizado, como expandir seu público, ux, etc. Então, vamos diretor para o tutorial.
Introdução
Traduções no Flutter, assim como todo o resto, são baseadas em Widgets. Neste tutorial, vamos usar o pacote flutter_localizations
que faz parte do SDK do Flutter e trabalha juntamente com o pacote intl
do Dart.
Essa é a forma “padrão” de tradução com Flutter. Já existem algumas alternativas disponíveis pela comunidade.
1. Adicionar dependências
Iniciamos adicionando as dependências dos pacotes mencionados acima no arquivopubspec.yaml
: (Pode adicionar em um projeto existente ou criar um novo)
dependencies:
flutter:
sdk: flutter
flutter_localizations: # adicionar
sdk: flutter # adicionar
# other linesdev_dependencies:
intl_translation: ^0.17.1 # adicionar
O pacote flutter_localizations
declara a necessidade do pacote de traduções do Flutter, que possui widgets relacionados a tradução e também as traduções de widgets existentes para diversas linguagens. O pacote intl
fornece ferramentas para manipulação dos arquivos .arb
de tradução.
2. A classe de tradução do app
A forma mais comum de gerenciar a tradução do app é criando uma classe que possui toda a implementação relacionada a traduções e pode ser usada em todo o app, AppLocalizations
por exemplo:
Note que muito dessa classe vai ser igual em todos os apps que você trabalhar, o que muda geralmente são as mensagens.
Vamos ver os detalhes da classe AppLocalizations
:
load
— Esta função carrega as mensagens da língua desejada (Locale
) passado por parâmetro..of
— Esta função é muito conhecida no mundo Flutter, uma prática padrão de widgets do tipoInheritedWidget
para facilitar o acesso a qualquer String de qualquer parte do app.get
’s — Os “getters” são funções com cada uma das strings traduzidas disponíveis para app. Perceba a chamada ao métodoIntl.message
em cada “getter”, isso fará com que o pacoteintl
carregue a string correta sempre que precisar.initializeMessages
— Esta função é gerada pela ferramenta de traduçãointl
. Note o import"l10n/messages_all.dart"
, este arquivo contém os métodos que carregam as mensagens traduzidas efetivamente.
A classe AppLocalizations
é geralmente acompanhada da classe AppLocalizationsDelegate
. Esta sim é a verdadeira classe de traduções do nosso app, AppLocalizations
é usada para encapsular as traduções e AppLocalizationsDelegate
fornece estas traduções ao nosso app. Ela pode ser dividida em três partes principais:
load
, pela documentação em tradução livre: O métudoload
precisa returnar um objeto que contenha uma coleção de recursos traduzidos relacionados(tipicamente com um método por recurso). No nosso caso, retonamosAppLocalizations.load
.isSupported
, deve retornartrue
se o app suporta a língua/Locale
.shouldReload
, basicamente, se este método retornartrue
, todos os widgets do app são reconstruídos após oload
.
Resumindo, a classe
AppLocalizations
é o objeto exposto pelo delegate e contém as traduções nos seusget
t’ers.
3. Arquivo .arb
O último passo é criar as traduções propriamente ditas. As traduções são criadas em arquivos do tipo Application Resource Bundle, de extensão.arb
. Este formato é suportado pelo Google Translators Toolkit. Cada arquivo .arb
contém um JSON que mapeia cada ID ao seu valor traduzido.
De início, nós usamos a ferramenta intl
para gerar um arquivo .arb
de exemplo.
flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/localizations.dart
Nota 1: O argumento
output-dir
precisa existir previamente.
Nota 2: O último argumento é o arquivo que contém osget
’s comas chamadas aoIntl.message.
Este comando gera um arquivo chamado intl_messages.arb
na pasta lib/i10n
e este arquivo é um template, a partir dele podemos criar outros com um simples ctrl+c e ctrl+v e renomeá-los para melhor identificação:
intl_en.arb:
{
"@@last_modified": "2018-05-25T11:50:40.743319",
"title": "Hello world App",
"@title": {
"description": "The application title",
"type": "text",
"placeholders": {}
},
"hello": "Hello",
"@hello": {
"type": "text",
"placeholders": {}
}
}
intl_pt.arb:
{
"@@last_modified": "2018-05-25T11:50:40.743319",
"title": "App Olá Mundo",
"@title": {
"description": "The application title",
"type": "text",
"placeholders": {}
},
"hello": "Olá",
"@hello": {
"type": "text",
"placeholders": {}
}
}
intl_es.arb:
{
"@@last_modified": "2018-05-25T11:50:40.743319",
"title": "App Hola Mundo",
"@title": {
"description": "The application title",
"type": "text",
"placeholders": {}
},
"hello": "Hola",
"@hello": {
"type": "text",
"placeholders": {}
}
}
Como pode ver, copiamos o arquivo
intl_messages.arb
e traduzimos de acordo com cada língua.
Com os arquivos de traduções prontos, devemos restaurá-los para o mundo Dart, linkando com oinitializeMessages
do primeiro passo. Isso é feito com o seguinte comando:
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n \
--no-use-deferred-loading lib/localization.dart lib/l10n/intl_*.arb
A partir dos arquivos
.arb
, a ferramentaintl
gera os arquivos Dart equivalentes. A classeAppLocalizations
usa então a funçãoinitializeMessages()
(definida no arquivomessages_all.dart
) para carregar as strings traduzidas eIntl.message()
para usá-las efetivamente. — (flutter.io,tradução livre)
Finalizando
Sem widgets até agora? Pois é, chegou a hora de usá-los , precisamos dizer ao nosso app que ele deve usar nossa classe AppLocalizationsDelegate
como sua classe de traduções.
Isso é feito com as propriedadeslocalizationsDelegates
esupportedLocales
. Você deve repetir os supportedLocales
definidos no seu delegate e configurar a listalocalizationDelegates
com a classe AppLocalizationsDelegate
além das classes GlobalDelegates
do pacote flutter_localizations
.
Os elementos da lista
localizationsDelegates
são factories que produzem coleções de valores traduzidos.GlobalMaterialLocalizations.delegate
fornece strings traduzidas e outros valores para widgets do padrão Material Design.GlobalWidgetsLocalizations.delegate
define outros valores relacionados a internacionalização como direcionalidade de texto, ltr ou rtl. — flutter.io , tradução livre
Conclusão
Isso é tudo no nosso tutorial de tradução, confira o código completo em: https://github.com/biessek/flutter_localization_example.
Pessoalmente, o método de traduções padrão é um pouco complicado e até mesmo chato pra que conhece o estilo do Android ou do iOS . Mas exitem outras formas e tem tudo para melhorar ainda mais no futuro, confira: https://flutter.dev/docs/development/accessibility-and-localization/internationalization.
Confira também o plugin para vs-code Flutter Intl que ajuda nesse processo automatizando grande parte do trabalho.
Espero que esse tutorial ajude vocês,
me segue lá no twitter se quiser trocar uma ideia sobre Flutter: https://twitter.com/abiessek