DEV Community

Cover image for Criando aplicação multi-idioma no Flutter
Adryanne Kelly
Adryanne Kelly

Posted on

Criando aplicação multi-idioma no Flutter

Neste artigo, vou guiá-lo passo a passo sobre como implementar um seletor de idioma moderno e funcional em sua aplicação Flutter. Vamos explorar como criar um toggle de idioma de forma intuitiva e fácil de usar, garantindo que seus usuários possam alternar entre diferentes idiomas de forma suave e sem complicações. Vamos começar?

 

Tópicos

 

Introdução

Se você está desenvolvendo uma aplicação que visa um público global, ou simplesmente deseja oferecer suporte a múltiplos idiomas, um seletor de idioma é essencial.
A alternância entre idiomas é importante pois oferece uma experiencia melhor para o usuário, permitindo que ele escolha um idioma de sua preferência de maneira rápida e fácil.
Neste artigo, você vai aprender de maneira rápida como fazer sua aplicação ter suporte a diferentes idiomas.
Lembrando que neste artigo faremos a alternância entre 2 idiomas, mas a partir disso você pode fazer com quantos idiomas desejar. Então, mão na massa!

 

Passo a passo

Passo 1: Criando nosso projeto Flutter

Para criar nosso projeto Flutter, vamos simplesmente rodar o seguinte comando

flutter create internationalization_example
Enter fullscreen mode Exit fullscreen mode

Aqui batizamos o nome do nosso projeto como "internationalization_example". Você pode colocar o nome que preferir.

 

Passo 2: Adicionando flutter_localizations, intl e provider

Agora, vamos adicionar os packages que precisamos para o nosso toggle de idiomas. Para isso, dentro do nosso projeto flutter vamos rodar os seguintes comandos:

  • Adicionando flutter_localizations: Este pacote será para adicionar suporte a outros idiomas já que por padrão o Flutter suporta somente o Inglês.
flutter pub add flutter_localization
Enter fullscreen mode Exit fullscreen mode
  • Adicionando o intl: Este pacote oferece recursos de internacionalização e localização, incluindo tradução de mensagens, plurais e gêneros, formatação e análise de data/número e texto bidirecional.
flutter pub add intl:any
Enter fullscreen mode Exit fullscreen mode
  • Adicionando o provider: Utilizaremos este para injeção de dependência que vamos precisar mais pra frente.
flutter pub add provider
Enter fullscreen mode Exit fullscreen mode

⚠️ Agora uma pequena alteração:
No nosso arquivo pubspec.yaml, precisaremos alterar a forma de declaração do nosso flutter_localization como mostrado abaixo e após isso dar um ctrl + s para reinstalar as nossas dependências:

dependencies:
    flutter:
        sdk: flutter
+   flutter_localizations:
+       sdk: flutter
    # The following adds the Cupertino Icons font to your application.
    # Use with the CupertinoIcons class for iOS style icons.
    cupertino_icons: ^1.0.6
-   flutter_localization: ^0.2.0
    intl: any
    provider: ^6.1.2
Enter fullscreen mode Exit fullscreen mode

 

Passo 3: Gerando arquivos de tradução

Dentro da pasta lib vamos criar uma pasta chamada l10n e dentro criar um arquivo chamado app_en.arb para os textos em inglês (en é a sigla da linguagem desejada, você pode colocar a sigla da linguagem que quiser) e um chamado app_pt.arb para textos em português.

Vamos escrever nossas traduções da seguinte forma:

// app_en.arb
{
    "helloWorld": "Hello World!",
    "counterMsg": "You have pushed the button this many times:"
}
Enter fullscreen mode Exit fullscreen mode
// app_pt.arb
{
    "helloWorld": "Olá mundo",
    "counterMsg": "Você apertou o botão essa quantidade de vezes:"
}
Enter fullscreen mode Exit fullscreen mode

Lembrando que as chaves das traduções devem ser exatamente iguais nos dois arquivos.

Você deverá fazer isso para todos os textos que deseja traduzir na sua aplicação. "Ah mas eu tenho um montão de textos nela!". Então... boa sorte.  👍

Curiosidade: A sigla l10n é assim porque na palavra localization tem 10 letras entre a letra L e a letra N.

Criados os nossos arquivos, para ativar a nossa geração dos arquivos de tradução, vamos no nosso arquivo pubspec.yaml novamente e habilitar a flag generate como no exemplo abaixo:

flutter:
    # The following line ensures that the Material Icons font is
    # included with your application, so that you can use the icons in
    # the material Icons class.
    uses-material-design: true
    generate: true
Enter fullscreen mode Exit fullscreen mode

Agora, para gerar nossos arquivos, rodamos o seguinte comando:

flutter gen-l10n
Enter fullscreen mode Exit fullscreen mode

Estes arquivos gerados ficarão localizados em dart_tool/flutter_gen/gen_l10n.

Não mexa nesses arquivos. Toda alteração nas traduções deve ser feita somente nos arquivos .arb

 

Passo 4: Configurando as linguagens na nossa aplicação

Agora configuraremos nosso MyApp, afinal, é a partir dele que a mágica acontece.

O MyApp é onde fica o nosso MaterialApp que nada mais é que a raiz de um aplicativo Flutter, que fornece uma estrutura base para navegação, estilização e internacionalização.

Dito isso, vamos adicionar as nossas configurações de internacionalização:

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:internationalization_flutter_example/app/my_home_page.dart';


class MyApp extends StatelessWidget {
    const MyApp({super.key});

    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
                colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
                useMaterial3: true,
            ),
            // Delegações de internacionalização globais 
            localizationsDelegates: const [
                AppLocalizations.delegate,
                GlobalMaterialLocalizations.delegate,
                GlobalWidgetsLocalizations.delegate,
                GlobalCupertinoLocalizations.delegate,
            ],
            // linguagens que nossa aplicação irá suportar
            supportedLocales: const [
                Locale('en'),
                Locale('pt'),
            ],
            // idioma atual da nossa aplicação
            locale: const Locale('pt'),
            home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

 

Passo 5: Adicionando traduções na nossa aplicação

Para adicionar as traduções nas páginas da nossa aplicação, vamos substituir os textos presentes na aplicação pelas chaves correspondentes do arquivo gerado com o comando flutter gen-l10n como no exemplo abaixo:

import 'package:flutter_gen/gen_l10n/app_localizations.dart';
...

appBar: AppBar(
    // adicionando texto da chave helloWorld
    title: Text(AppLocalizations.of(context)!.helloWorld),
),
Enter fullscreen mode Exit fullscreen mode

Nota: a cada mudança nos arquivos .arb é necessário rodar novamente o comando flutter gen-l10n para que as mudanças persistam nos arquivos de tradução gerados.

 

Passo 6: Fazendo toggle de idiomas

Agora, por fim, vamos fazer nosso toggle de idiomas!! Para isso vamos criar uma controller que vai estender de ChangeNotifier (vamos usar o ChangeNotifier para que a nossa tela fique escutando qualquer alteração na nossa classe)

Nesta classe vamos criar uma variável booleana (vou chamá-la de isEnglish) que recebe por padrão true

Criada a variável, criaremos agora uma função void que toda vez que for chamada o valor da variável mudará para sua negação (isso significa que se ela for true se tornará false e vice-versa) e logo após notificamos essa alteração usando notifyListeners();.

Nossa controller ficará da seguinte forma:

import 'package:flutter/material.dart';

class LanguageController extends ChangeNotifier {
    bool isEnglish = true;

  void toggleLanguage() {
    isEnglish = !isEnglish;
    notifyListeners();
  }
}
Enter fullscreen mode Exit fullscreen mode

Agora voltando ao nosso MyApp, vamos injetar o nosso controller que é a nossa dependência:


class MyApp extends StatelessWidget {
    const MyApp({super.key});

    @override
    Widget build(BuildContext context) {
        // adicionamos o ChangeNotifierProvider para fornecer o LanguageController
        return ChangeNotifierProvider(
            // criamos uma instância de LanguageController
            create: (context) => LanguageController(),
            builder: (context, child) {
                // acessamos o LanguageController por meio do Provider
                final languageController = Provider.of<LanguageController>(context);
                return MaterialApp(
                    title: 'Flutter Demo',
                    theme: ThemeData(
                        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
                        useMaterial3: true,
                    ),
                    localizationsDelegates: const [
                        AppLocalizations.delegate,
                        GlobalMaterialLocalizations.delegate,
                        GlobalWidgetsLocalizations.delegate,
                        GlobalCupertinoLocalizations.delegate,
                    ],
                    supportedLocales: const [
                        Locale('en'),
                        Locale('pt'),
                    ],
                    // acessamos o atributo isEnglish do LanguageController para definir o idioma
                    // se false, o idioma será português (pt), caso contrário, será inglês (en)
                    locale: languageController.isEnglish ? const Locale('en') : const Locale('pt'),
                    home: const MyHomePage(title: 'Flutter Demo Home Page'),
                );
            },
        );
    }
}

Enter fullscreen mode Exit fullscreen mode

 O ChangeNotifierProvider é uma classe do pacote provider no Flutter, que é usado para fornecer uma instância de um ChangeNotifier aos widgets descendentes na árvore de widgets. Sendo assim, o método create é chamado para criar uma instância de LanguageController para que possamos acessar os dados ou regras de negócio presentes nele.

Agora, na nossa tela, vamos adicionar o nosso botão para mudar o idioma da nossa aplicação:

class MyHomePage extends StatefulWidget {
    const MyHomePage({super.key, required this.title});
    final String title;

    @override
    State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
    @override
    Widget build(BuildContext context) {
        // acessamos o LanguageController por meio do Provider
        final languageController = Provider.of<LanguageController>(context);

        return Scaffold(
            appBar: AppBar(
                backgroundColor: Theme.of(context).colorScheme.inversePrimary,
                title: Text(AppLocalizations.of(context)!.helloWorld),
            ),
            body: Center(
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                        Text(
                            AppLocalizations.of(context)!.counterMsg,
                        ),
                        Text(
                            '2',
                            style: Theme.of(context).textTheme.headlineMedium,
                        ),
                    ],
                ),
            ),
            floatingActionButton: FloatingActionButton(
                // chamando nossa função do LanguageController
                onPressed: languageController.toggleLanguage,
                tooltip: 'Toggle Language',
                child: const Icon(Icons.language),
            ),
        );
    }
}

Enter fullscreen mode Exit fullscreen mode

Ao fim disso, nosso toggle de idiomas já está funcionando, basta clicar no botão flutuante e o idioma da nossa aplicação mudará assim como demonstrado abaixo:

E pronto, agora você pode alternar entre os idiomas que quiser na sua aplicação!

Conclusão

Implementar uma alternância entre idiomas é uma excelente maneira de tornar sua aplicação acessível a usuários de diversos países. Com estes seis passos, você pode implementar essa funcionalidade de forma fácil e eficiente. Abaixo, disponibilizo o repositório de exemplo e links úteis para auxiliá-lo. Em caso de dúvidas, sinta-se a vontade para entrar em contato. Obrigado por ler até aqui. Espero que tenha gostado e até a próxima!

Referências

Meus agradecimentos a @clintonrocha98, @cherryramatis e @redrodrigoc vocês são demais 💜

Top comments (5)

Collapse
 
alinesousaa profile image
Aline Sousa

A melhor e digo mais!

Collapse
 
adryannekelly profile image
Adryanne Kelly

Obrigadaaa ^^

Collapse
 
phenriquesousa profile image
Pedro Henrique

MUITO interessante, obrigado por compartilhar 💜

Collapse
 
adryannekelly profile image
Adryanne Kelly

Muito obrigada, que bom que gostou ^^

Collapse
 
mateuxaff profile image
Mateus Ferreira Rodrigues

💜💜💜💜💜