Flutter - Internazionalizzazione
Al giorno d'oggi, le applicazioni mobili vengono utilizzate da clienti di diversi paesi e, di conseguenza, le applicazioni devono visualizzare il contenuto in diverse lingue. L'abilitazione di un'applicazione per funzionare in più lingue è denominata Internazionalizzazione dell'applicazione.
Affinché un'applicazione funzioni in lingue diverse, deve prima trovare la locale corrente del sistema in cui è in esecuzione l'applicazione e quindi deve mostrare il suo contenuto in quella particolare lingua, e questo processo è chiamato Localizzazione.
Il framework Flutter fornisce tre classi base per la localizzazione e classi di utilità estese derivate dalle classi base per localizzare un'applicazione.
Le classi di base sono le seguenti:
Locale - Locale è una classe utilizzata per identificare la lingua dell'utente. Ad esempio, en-us identifica l'inglese americano e può essere creato come.
Locale en_locale = Locale('en', 'US')
Qui, il primo argomento è il codice della lingua e il secondo è il codice del paese. Un altro esempio di creazione della locale spagnola Argentina (es-ar) è il seguente:
Locale es_locale = Locale('es', 'AR')
Localizzazioni : le localizzazioni sono un widget generico utilizzato per impostare le impostazioni locali e le risorse localizzate del figlio.
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'];
}
}
In questo caso, CustomLocalizations è una nuova classe personalizzata creata appositamente per ottenere determinati contenuti localizzati (titolo e messaggio) per il widget. del metodo utilizza la classe Localizations per restituire la nuova classe CustomLocalizations.
LocalizationsDelegate <T> - LocalizationsDelegate <T> è una classe factory attraverso la quale viene caricato il widget Localizations. Ha tre metodi superabili:
isSupported: accetta una locale e restituisce se la locale specificata è supportata o meno.
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
load: accetta una locale e avvia il caricamento delle risorse per la locale specificata.
Qui, il delegato lavora solo per en ed es locale.
@override
Future<CustomLocalizations> load(Locale locale) {
return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}
shouldReload: specifica se è necessario ricaricare CustomLocalizations quando viene ricostruito il relativo widget Localizations.
Qui, il metodo di caricamento restituisce CustomLocalizations. Le CustomLocalizations restituite possono essere utilizzate per ottenere valori di titolo e messaggio sia in inglese che in spagnolo
@override
bool shouldReload(CustomLocalizationsDelegate old) => false;
Il codice completo di CustomLocalizationDelegate è il seguente:
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;
}
In generale, le applicazioni Flutter si basano su due widget di livello principale, MaterialApp o WidgetsApp. Flutter fornisce una localizzazione pronta per entrambi i widget e sono MaterialLocalizations e WidgetsLocaliations. Inoltre, Flutter fornisce anche delegati per caricare MaterialLocalizations e WidgetsLocaliations e sono rispettivamente GlobalMaterialLocalizations.delegate e GlobalWidgetsLocalizations.delegate.
Creiamo una semplice applicazione abilitata all'internazionalizzazione per testare e comprendere il concetto.
Crea una nuova applicazione flutter, flutter_localization_app.
Flutter supporta l'internazionalizzazione utilizzando l'esclusivo pacchetto flutter, flutter_localizations. L'idea è di separare il contenuto localizzato dall'SDK principale. Apri pubspec.yaml e aggiungi il codice seguente per abilitare il pacchetto di internazionalizzazione -
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
Android Studio mostrerà il seguente avviso che il pubspec.yaml è aggiornato.
Fare clic sull'opzione Ottieni dipendenze. Android Studio otterrà il pacchetto da Internet e lo configurerà correttamente per l'applicazione.
Importa il pacchetto flutter_localizations nel main.dart come segue:
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/foundation.dart' show SynchronousFuture;
In questo caso, lo scopo di SynchronousFuture è caricare le localizzazioni personalizzate in modo sincrono.
Crea una localizzazione personalizzata e il suo delegato corrispondente come specificato di seguito -
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;
}
Qui, CustomLocalizations viene creato per supportare la localizzazione per titolo e messaggio nell'applicazione e CustomLocalizationsDelegate viene utilizzato per caricare CustomLocalizations.
Aggiungi delegati per MaterialApp, WidgetsApp e CustomLocalization utilizzando le proprietà MaterialApp, localizationsDelegates e supportedLocales come specificato di seguito -
localizationsDelegates: [
const CustomLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', ''),
const Locale('es', ''),
],
Utilizzare il metodo CustomLocalizations per ottenere il valore localizzato di titolo e messaggio e utilizzarlo nella posizione appropriata come specificato di seguito -
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, ),
],
),
),
);
}
}
Qui, abbiamo modificato la classe MyHomePage da StatefulWidget a StatelessWidget per motivi di semplicità e abbiamo utilizzato CustomLocalizations per ottenere titolo e messaggio.
Compila ed esegui l'applicazione. L'applicazione mostrerà il suo contenuto in inglese.
Chiudi l'applicazione. Vai aSettings → System → Languages and Input → Languages*.
Fai clic su Aggiungi un'opzione di lingua e seleziona Spagnolo. Questo installerà la lingua spagnola e quindi la elencherà come una delle opzioni.
Seleziona lo spagnolo e spostalo sopra l'inglese. Questo verrà impostato come spagnolo come prima lingua e tutto verrà modificato in testo spagnolo.
Ora riavvia l'applicazione di internazionalizzazione e vedrai il titolo e il messaggio in lingua spagnola.
Possiamo ripristinare la lingua in inglese spostando l'opzione inglese sopra l'opzione spagnola nell'impostazione.
Il risultato dell'applicazione (in spagnolo) è mostrato nella schermata riportata di seguito -
Utilizzo di intl Package
Flutter fornisce un pacchetto intl per semplificare ulteriormente lo sviluppo di applicazioni mobili localizzate. Il pacchetto intl fornisce metodi e strumenti speciali per generare in modo semi-automatico messaggi specifici della lingua.
Creiamo una nuova applicazione localizzata utilizzando il pacchetto intl e comprendiamo il concetto.
Crea una nuova applicazione flutter, flutter_intl_app.
Apri pubspec.yaml e aggiungi i dettagli del pacchetto.
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.15.7
intl_translation: ^0.17.3
Android Studio visualizzerà l'avviso come mostrato di seguito per informare che pubspec.yaml è aggiornato.
Fare clic sull'opzione Ottieni dipendenze. Android Studio otterrà il pacchetto da Internet e lo configurerà correttamente per l'applicazione.
Copia il file main.dart dall'esempio precedente, flutter_internationalization_app.
Importa il pacakge internazionale come mostrato di seguito:
import 'package:intl/intl.dart';
Aggiorna la classe CustomLocalization come mostrato nel codice riportato di seguito -
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;
}
Qui, abbiamo utilizzato tre metodi dal pacchetto intl invece di metodi personalizzati. Altrimenti, i concetti sono gli stessi.
Intl.canonicalizedLocale: utilizzato per ottenere il nome locale corretto.
Intl.defaultLocale: utilizzato per impostare la locale corrente
Intl.message - Usato per definire nuovi messaggi.
importare l10n/messages_all.dartfile. Genereremo questo file a breve
import 'l10n/messages_all.dart';
Ora, crea una cartella, lib / l10n
Apri un prompt dei comandi e vai alla directory principale dell'applicazione (dove pubspec.yaml è disponibile) ed esegui il seguente comando:
flutter packages pub run intl_translation:extract_to_arb --output-
dir=lib/l10n lib/main.dart
Qui, il comando genererà il file intl_message.arb, un modello per creare un messaggio in una lingua diversa. Il contenuto del file è il seguente:
{
"@@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": {}
}
}
Copia intl_message.arb e crea un nuovo file, intl_en.arb.
Copia intl_message.arb e crea un nuovo file, intl_es.arb e cambia il contenuto in lingua spagnola come mostrato di seguito -
{
"@@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": {}
}
}
Ora, esegui il seguente comando per creare il file del messaggio finale, 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
Compila ed esegui l'applicazione. Funzionerà in modo simile all'applicazione precedente, flutter_localization_app.