Flutter - Internacionalização
Hoje em dia, os aplicativos móveis são usados por clientes de diferentes países e, como resultado, os aplicativos são obrigados a exibir o conteúdo em diferentes idiomas. Habilitar um aplicativo para funcionar em vários idiomas é denominado Internacionalizar o aplicativo.
Para que um aplicativo funcione em diferentes idiomas, ele deve primeiro encontrar o local atual do sistema no qual o aplicativo está sendo executado e, em seguida, mostrar seu conteúdo naquele local específico, e esse processo é chamado de localização.
A estrutura Flutter fornece três classes básicas para localização e classes de utilitários abrangentes derivadas de classes básicas para localizar um aplicativo.
As classes básicas são as seguintes -
Locale - Locale é uma classe usada para identificar o idioma do usuário. Por exemplo, en-us identifica o inglês americano e pode ser criado como.
Locale en_locale = Locale('en', 'US')
Aqui, o primeiro argumento é o código do idioma e o segundo argumento é o código do país. Outro exemplo de criação de localidade Argentina espanhol (es-ar) é o seguinte -
Locale es_locale = Locale('es', 'AR')
Localizations - Localizations é um widget genérico usado para definir o Locale e os recursos localizados de seu filho.
class CustomLocalizations {
CustomLocalizations(this.locale);
final Locale locale;
static CustomLocalizations of(BuildContext context) {
return Localizations.of<CustomLocalizations>(context, CustomLocalizations);
}
static Map<String, Map<String, String>> _resources = {
'en': {
'title': 'Demo',
'message': 'Hello World'
},
'es': {
'title': 'Manifestación',
'message': 'Hola Mundo',
},
};
String get title {
return _resources[locale.languageCode]['title'];
}
String get message {
return _resources[locale.languageCode]['message'];
}
}
Aqui, CustomLocalizations é uma nova classe personalizada criada especificamente para obter determinado conteúdo localizado (título e mensagem) para o widget. do método usa a classe Localizations para retornar a nova classe CustomLocalizations.
LocalizationsDelegate <T> - LocalizationsDelegate <T> é uma classe de fábrica por meio da qual o widget Localizations é carregado. Tem três métodos de over-ridable -
isSupported - Aceita uma localidade e retorna se a localidade especificada é compatível ou não.
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
load - Aceita uma localidade e começa a carregar os recursos para a localidade especificada.
Aqui, o delegado trabalha para en e es locale apenas.
@override
Future<CustomLocalizations> load(Locale locale) {
return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}
shouldReload - especifica se o recarregamento de CustomLocalizations é necessário quando seu widget Localizations é reconstruído.
Aqui, o método load retorna CustomLocalizations. As CustomLocalizations retornadas podem ser usadas para obter valores de título e mensagem em inglês e espanhol
@override
bool shouldReload(CustomLocalizationsDelegate old) => false;
O código completo de CustomLocalizationDelegate é o seguinte -
class CustomLocalizationsDelegate extends
LocalizationsDelegate<CustomLocalizations> {
const CustomLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
@override
Future<CustomLocalizations> load(Locale locale) {
return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}
@override bool shouldReload(CustomLocalizationsDelegate old) => false;
}
Em geral, os aplicativos Flutter são baseados em dois widgets de nível raiz, MaterialApp ou WidgetsApp. Flutter fornece localização pronta para ambos os widgets e eles são MaterialLocalizations e WidgetsLocaliations. Além disso, o Flutter também fornece delegados para carregar MaterialLocalizations e WidgetsLocaliations e são GlobalMaterialLocalizations.delegate e GlobalWidgetsLocalizations.delegate, respectivamente.
Vamos criar um aplicativo habilitado para internacionalização simples para testar e entender o conceito.
Crie um novo aplicativo de flutter, flutter_localization_app.
Flutter apóia a internacionalização usando o pacote flutter exclusivo, flutter_localizations. A ideia é separar o conteúdo localizado do SDK principal. Abra o pubspec.yaml e adicione o código abaixo para habilitar o pacote de internacionalização -
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
O Android Studio exibirá o seguinte alerta de que o pubspec.yaml está atualizado.
Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará corretamente para o aplicativo.
Importe o pacote flutter_localizations no main.dart da seguinte forma -
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/foundation.dart' show SynchronousFuture;
Aqui, o objetivo do SynchronousFuture é carregar as localizações personalizadas de forma síncrona.
Crie localizações personalizadas e seu delegado correspondente conforme especificado abaixo -
class CustomLocalizations {
CustomLocalizations(this.locale);
final Locale locale;
static CustomLocalizations of(BuildContext context) {
return Localizations.of<CustomLocalizations>(context, CustomLocalizations);
}
static Map<String, Map<String, String>> _resources = {
'en': {
'title': 'Demo',
'message': 'Hello World'
},
'es': {
'title': 'Manifestación',
'message': 'Hola Mundo',
},
};
String get title {
return _resources[locale.languageCode]['title'];
}
String get message {
return _resources[locale.languageCode]['message'];
}
}
class CustomLocalizationsDelegate extends
LocalizationsDelegate<CustomLocalizations> {
const CustomLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
@override
Future<CustomLocalizations> load(Locale locale) {
return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}
@override bool shouldReload(CustomLocalizationsDelegate old) => false;
}
Aqui, CustomLocalizations é criado para oferecer suporte à localização de título e mensagem no aplicativo e CustomLocalizationsDelegate é usado para carregar CustomLocalizations.
Adicione delegados para MaterialApp, WidgetsApp e CustomLocalization usando as propriedades MaterialApp, localizationsDelegates e supportedLocales conforme especificado abaixo -
localizationsDelegates: [
const CustomLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', ''),
const Locale('es', ''),
],
Use o método CustomLocalizations, de para obter o valor localizado do título e da mensagem e use-o no local apropriado, conforme especificado abaixo -
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(CustomLocalizations .of(context) .title), ),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text( CustomLocalizations .of(context) .message, ),
],
),
),
);
}
}
Aqui, modificamos a classe MyHomePage de StatefulWidget para StatelessWidget por motivos de simplicidade e usamos CustomLocalizations para obter o título e a mensagem.
Compile e execute o aplicativo. O aplicativo exibirá seu conteúdo em inglês.
Feche o aplicativo. Vamos paraSettings → System → Languages and Input → Languages*.
Clique em Adicionar uma opção de idioma e selecione Espanhol. Isso instalará o idioma espanhol e o listará como uma das opções.
Selecione Espanhol e mova-o acima de Inglês. Isso será definido como espanhol como primeiro idioma e tudo será alterado para o texto em espanhol.
Agora reinicie o aplicativo de internacionalização e você verá o título e a mensagem em espanhol.
Podemos reverter o idioma para o inglês movendo a opção Inglês acima da opção Espanhol na configuração.
O resultado da aplicação (em espanhol) é mostrado na imagem abaixo -
Usando pacote intl
O Flutter fornece o pacote internacional para simplificar ainda mais o desenvolvimento de aplicativos móveis localizados. O pacote intl fornece métodos e ferramentas especiais para a geração semi-automática de mensagens específicas de idioma.
Vamos criar um novo aplicativo localizado usando o pacote intl e entender o conceito.
Crie um novo aplicativo de flutter, flutter_intl_app.
Abra pubspec.yaml e adicione os detalhes do pacote.
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.15.7
intl_translation: ^0.17.3
O Android Studio exibirá o alerta, conforme mostrado abaixo, informando que o pubspec.yaml está atualizado.
Clique na opção Obter dependências. O Android Studio obterá o pacote da Internet e o configurará corretamente para o aplicativo.
Copie main.dart do exemplo anterior, flutter_internationalization_app.
Importe o pacote internacional conforme mostrado abaixo -
import 'package:intl/intl.dart';
Atualize a classe CustomLocalization conforme mostrado no código fornecido abaixo -
class CustomLocalizations {
static Future<CustomLocalizations> load(Locale locale) {
final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final String localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((_) {
Intl.defaultLocale = localeName;
return CustomLocalizations();
});
}
static CustomLocalizations of(BuildContext context) {
return Localizations.of<CustomLocalizations>(context, CustomLocalizations);
}
String get title {
return Intl.message(
'Demo',
name: 'title',
desc: 'Title for the Demo application',
);
}
String get message{
return Intl.message(
'Hello World',
name: 'message',
desc: 'Message for the Demo application',
);
}
}
class CustomLocalizationsDelegate extends
LocalizationsDelegate<CustomLocalizations> {
const CustomLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
@override
Future<CustomLocalizations> load(Locale locale) {
return CustomLocalizations.load(locale);
}
@override
bool shouldReload(CustomLocalizationsDelegate old) => false;
}
Aqui, usamos três métodos do pacote intl em vez de métodos personalizados. Caso contrário, os conceitos são os mesmos.
Intl.canonicalizedLocale - Usado para obter o nome de localidade correto.
Intl.defaultLocale - usado para definir a localidade atual
Intl.message - Usado para definir novas mensagens.
importar l10n/messages_all.dartArquivo. Iremos gerar este arquivo em breve
import 'l10n/messages_all.dart';
Agora, crie uma pasta, lib / l10n
Abra um prompt de comando e vá para o diretório raiz do aplicativo (onde pubspec.yaml está disponível) e execute o seguinte comando -
flutter packages pub run intl_translation:extract_to_arb --output-
dir=lib/l10n lib/main.dart
Aqui, o comando irá gerar, arquivo intl_message.arb, um modelo para criar mensagem em localidade diferente. O conteúdo do arquivo é o seguinte -
{
"@@last_modified": "2019-04-19T02:04:09.627551",
"title": "Demo",
"@title": {
"description": "Title for the Demo application",
"type": "text",
"placeholders": {}
},
"message": "Hello World",
"@message": {
"description": "Message for the Demo
application",
"type": "text",
"placeholders": {}
}
}
Copie intl_message.arb e crie um novo arquivo, intl_en.arb.
Copie intl_message.arb e crie um novo arquivo, intl_es.arb e altere o conteúdo para o idioma espanhol como mostrado abaixo -
{
"@@last_modified": "2019-04-19T02:04:09.627551",
"title": "Manifestación",
"@title": {
"description": "Title for the Demo application",
"type": "text",
"placeholders": {}
},
"message": "Hola Mundo",
"@message": {
"description": "Message for the Demo application",
"type": "text",
"placeholders": {}
}
}
Agora, execute o seguinte comando para criar o arquivo de mensagem final, messages_all.dart.
flutter packages pub run intl_translation:generate_from_arb
--output-dir=lib\l10n --no-use-deferred-loading
lib\main.dart lib\l10n\intl_en.arb lib\l10n\intl_es.arb
Compile e execute o aplicativo. Ele funcionará de forma semelhante ao aplicativo acima, flutter_localization_app.