Integre facilmente vários idiomas no aplicativo Flutter

Tempo de leitura: 5 minutes

O suporte a vários idiomas em seu aplicativo é muito importante para abranger o mercado global. Muitos tutoriais estão disponíveis para o Flutter Localization & Integrate multi-language support in Flutter, mas eu fiz um tutorial muito fácil para adicionar vários idiomas no aplicativo Flutter. Esse tutorial também é útil para iniciantes aprenderem sobre a localização do Flutter.

 

Por que multilíngue?

Adicionar suporte multilíngue ao aplicativo é fundamental para a acessibilidade global, a experiência aprimorada do usuário, a expansão do mercado, a sensibilidade cultural, a competitividade e a adaptabilidade às preferências do usuário. Isso garante um público mais amplo, maior satisfação e uma vantagem estratégica em um cenário diversificado e competitivo.

 

Começando com o Multi-Language

Primeiro, você precisa criar um novo projeto Flutter seguindo estas etapas:

  1. Abra o terminal ou o prompt de comando.
  2. Digite o seguinte comando:
flutter create multi_language_app

Adicionar dependência

Por padrão, o Flutter fornece apenas localizações em inglês dos EUA. Portanto, é necessário adicionar flutter_localizations como uma dependência ao seu arquivo pubspec.yaml. A partir de dezembro de 2023, esse pacote oferece suporte a 115 idiomas e variantes de idioma.

Abra o arquivo pubspec.yaml e faça as seguintes alterações:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  shared_preferences: ^2.2.2

 

Adicionar os idiomas

Primeiro, crie a pasta language na pasta lib. Em seguida, crie o arquivo language.dart na pasta language. Depois disso, crie uma classe abstrata que contenha todas as cadeias de caracteres localizadas. Precisamos definir todos os textos localizados em arquivos de cadeia de caracteres de idiomas diferentes, como mostrado abaixo:

import 'package:flutter/material.dart';

abstract class Languages {
  static Languages? of(BuildContext context) {
    return Localizations.of<Languages>(context, Languages);
  }

  String get appName;

  String get welcomeText;

  String get appDescription;

  String get selectLanguage;
}

Depois disso, você pode criar outras classes de idiomas de acordo com suas necessidades, estender a classe Languages e substituir todas as cadeias de caracteres. Aqui eu adicionei os três idiomas: inglês, português e francês.

Aqui está o meu arquivo language_en.dart:

import 'languages.dart';

class LanguageEn extends Languages {
  @override
  String get appName => "Demo App";

  @override
  String get welcomeText => "Welcome";

  @override
  String get selectLanguage => "Select your language";

  @override
  String get appDescription => "This application helps you to easily implement the multi language to your flutter application.";
}

Aqui está o meu arquivo language_br.dart:

import 'languages.dart';

class LanguageBr extends Languages {
  @override
  String get appName => "Aplicativo de demonstração";

  @override
  String get welcomeText => "Ei você";

  @override
  String get selectLanguage => "Escolha seu idioma";

  @override
  String get appDescription =>
      "Este aplicativo ajuda você a implementar facilmente vários idiomas para seu aplicativo Flutter.";
}

Aqui está o meu arquivo language_fr.dart:

import 'languages.dart';

class LanguageFr extends Languages {
  @override
  String get appName => "Application de démonstration";

  @override
  String get welcomeText => "Bienvenue";

  @override
  String get selectLanguage => "Choisissez votre langue";

  @override
  String get appDescription =>
      "Cette application vous aide à implémenter facilement le multilinguisme dans votre application Flutter.";
}

 

 

Criar LocalizationsDelegate :

O LocalizationDelegate no Flutter é necessário para o suporte a vários idiomas, pois ele gerencia a lógica de localização, permitindo que o aplicativo alterne dinamicamente entre diferentes idiomas.

O AppLocalizationsDelegate é o arquivo-chave para a localização. Crie uma classe e estenda LocalizationsDelegate e forneça nossa classe Languages criada em um parâmetro genérico. Depois disso, você precisa substituir três métodos, que são isSupported, load e shouldReload. Portanto, agora crie a pasta de localizationna pasta lib. Em seguida, crie o arquivo delegation.dart na pasta de localização, que é o seguinte:

import 'package:flutter/material.dart';
import 'package:multi_language_app/language/languages.dart';
import 'package:multi_language_app/language/language_en.dart';
import 'package:multi_language_app/language/language_fr.dart';
import 'package:multi_language_app/language/language_br.dart';

class AppLocalizationsDelegate extends LocalizationsDelegate<Languages> {
  const AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) =>
      ['en', 'pt', 'fr'].contains(locale.languageCode);

  @override
  Future<Languages> load(Locale locale) => _load(locale);

  static Future<Languages> _load(Locale locale) async {
    switch (locale.languageCode) {
      case 'en':
        return LanguageEn();
      case 'pt':
        return LanguageBr();
      case 'fr':
        return LanguageFr();
      default:
        return LanguageEn();
    }
  }

  @override
  bool shouldReload(LocalizationsDelegate<Languages> old) => false;
}

Configurar o arquivo main.dart

É necessário criar a classe MyApp com o StatefulWidget, pois sempre que o idioma é alterado, todo o aplicativo é reconstruído e refletido com o novo idioma. Portanto, primeiro precisamos definir algumas propriedades no MaterialApp Widget.

Precisamos adicionar o widget MaterialApp supportedLocales e localizationsDelegates dentro da classe MyApp(), como abaixo:

supportedLocales: const [
  Locale('en', 'US'),
  Locale('pt', 'BR'),
  Locale('fr', 'FR')
],
localizationsDelegates: const [
  AppLocalizationsDelegate(),
  GlobalMaterialLocalizations.delegate,
  GlobalWidgetsLocalizations.delegate,
  GlobalCupertinoLocalizations.delegate,
],

Aqui está o código-fonte completo do arquivo main.dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:multi_language_app/localization/delegation.dart';
import 'package:multi_language_app/screen/home_screen.dart';

import 'localization/constant.dart';

void main() {
  runApp(const MyApp());
}

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

  static void setLocale(BuildContext context, Locale newLocale) {
    var state = context.findAncestorStateOfType<_MyAppState>();
    state!.setLocale(newLocale);
  }

  @override
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Locale? _locale;

  void setLocale(Locale locale) {
    setState(() {
      _locale = locale;
    });
  }

  @override
  void didChangeDependencies() async {
    getLocale().then((locale) {
      setState(() {
        _locale = locale;
      });
    });
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, child) {
        return MediaQuery(
          data: MediaQuery.of(context)
              .copyWith(textScaler: const TextScaler.linear(1.0)),
          child: child!,
        );
      },
      title: 'Multi Language',
      debugShowCheckedModeBanner: false,
      locale: _locale,
      home: const Home(),
      supportedLocales: const [
        Locale('en', 'US'),
        Locale('pt', 'BR'),
        Locale('fr', 'FR')
      ],
      localizationsDelegates: const [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      localeResolutionCallback: (locale, supportedLocales) {
        for (var supportedLocale in supportedLocales) {
          if (supportedLocale.languageCode == locale?.languageCode &&
              supportedLocale.countryCode == locale?.countryCode) {
            return supportedLocale;
          }
        }
        return supportedLocales.first;
      },
    );
  }
}

Além disso, você pode usar o SharedPreference para armazenar a localidade do idioma e obter a localidade que usamos na classe principal. Eu o defini no arquivo constant.dart.

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../main.dart';

const String prefSelectedLanguageCode = "language";
const String prefSelectedCountry = "country";

Future<Locale> setLocale(String languageCode, String country) async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  await prefs.setString(prefSelectedLanguageCode, languageCode);
  await prefs.setString(prefSelectedCountry, country);

  return _locale(languageCode, country);
}

Future<Locale> getLocale() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String languageCode = prefs.getString(prefSelectedLanguageCode) ?? "en";
  String country = prefs.getString(prefSelectedCountry) ?? "US";
  return _locale(languageCode, country);
}

Locale _locale(String languageCode, String country) {
  return languageCode.isNotEmpty
      ? Locale(languageCode, country)
      : const Locale('en', 'US');
}

void changeLanguage(
    BuildContext context, String selectedLanguageCode, String country) async {
  var locale = await setLocale(selectedLanguageCode, country);
  // ignore: use_build_context_synchronously
  MyApp.setLocale(context, locale);
}

Ao executar o aplicativo, devemos obter a saída da tela como a captura de tela abaixo.

Está versão adicionei o package country_flags no seu pubspec.yaml

Ele permite mostrar o icon do Country.

Segue o Codigo da mudança no home_screen.dart

import 'package:country_flags/country_flags.dart';
import 'package:flutter/material.dart';
import 'package:multi_language_app/language/languages.dart';
import 'package:multi_language_app/localization/constant.dart';
import 'package:multi_language_app/model/language_model.dart';

class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<StatefulWidget> createState() => HomeState();
}

class HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          // leading: const Icon(
          //   Icons.language,
          //   color: Colors.white,
          // ),
          title: Text(
            Languages.of(context)!.appName,
          ),
          centerTitle: true,
        ),
        body: Container(
          margin: const EdgeInsets.all(30),
          child: Center(
            child: Column(
              children: <Widget>[
                const SizedBox(
                  height: 80,
                ),
                Text(
                  Languages.of(context)!.welcomeText,
                  style: const TextStyle(
                      fontSize: 30,
                      fontWeight: FontWeight.bold,
                      color: Colors.black),
                ),
                const SizedBox(
                  height: 30,
                ),
                Text(
                  Languages.of(context)!.appDescription,
                  style: const TextStyle(fontSize: 20, color: Colors.grey),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(
                  height: 70,
                ),
                _createLanguageDropDown()
              ],
            ),
          ),
        ),
      );

  _createLanguageDropDown() {
    return DropdownButton<LanguageModel>(
      iconSize: 50,
      hint: Text(Languages.of(context)!.selectLanguage),
      onChanged: (LanguageModel? language) {
        changeLanguage(context, language!.languageCode, language.country);
      },
      items: LanguageModel.languageList()
          .map<DropdownMenuItem<LanguageModel>>(
            (e) => DropdownMenuItem<LanguageModel>(
              value: e,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  CountryFlag.fromCountryCode(
                    e.country.toString(),
                    height: 30,
                    width: 40,
                  ),
                  //Text(
                  //  e.country,
                  //  style: const TextStyle(fontSize: 30),
                  //s),
                  Text(e.languageName)
                ],
              ),
            ),
          )
          .toList(),
    );
  }
}

Código completo no meu Github (Git)

Conclusão

Neste artigo, aprendemos sobre o suporte a vários idiomas no Flutter, explorando como criar um aplicativo verdadeiramente globalizado que atenda a um público diversificado. Desde o tratamento da localização e da internacionalização até a implementação de mecanismos de troca de idiomas.