Flutter — Traduções: passo a passo

Alessandro Biessek
Flutter — Comunidade BR
5 min readJun 20, 2019

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 lines
dev_dependencies:
intl_translation: ^0.17.1 # adicionar

O pacote flutter_localizationsdeclara 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 intlfornece 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 tipo InheritedWidget 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 pacote intl carregue a string correta sempre que precisar.
  • initializeMessages — Esta função é gerada pela ferramenta de tradução intl. 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 AppLocalizationsDelegatefornece 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étudo load precisa returnar um objeto que contenha uma coleção de recursos traduzidos relacionados(tipicamente com um método por recurso). No nosso caso, retonamos AppLocalizations.load.
  • isSupported, deve retornar true 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 o load.

Resumindo, a classeAppLocalizations é o objeto exposto pelo delegate e contém as traduções nos seus gett’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 argumentooutput-dir precisa existir previamente.
Nota 2: O último argumento é o arquivo que contém os get’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 arquivointl_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 ferramenta intl gera os arquivos Dart equivalentes. A classeAppLocalizations usa então a funçãoinitializeMessages() (definida no arquivo messages_all.dart) para carregar as strings traduzidas e Intl.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 listalocalizationsDelegates 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

--

--