Flutter - internacjonalizacja
W dzisiejszych czasach aplikacje mobilne są używane przez klientów z różnych krajów, w związku z czym aplikacje są wymagane do wyświetlania treści w różnych językach. Umożliwienie aplikacji pracy w wielu językach nazywa się internacjonalizacją aplikacji.
Aby aplikacja działała w różnych językach, powinna najpierw znaleźć aktualne ustawienie regionalne systemu, w którym działa aplikacja, a następnie wyświetlić jej zawartość w tym konkretnym języku, a proces ten nazywa się Lokalizacja.
Framework Flutter udostępnia trzy klasy bazowe do lokalizacji i rozbudowane klasy narzędziowe pochodzące z klas bazowych do lokalizacji aplikacji.
Podstawowe klasy są następujące -
Locale - Locale to klasa używana do identyfikacji języka użytkownika. Na przykład en-us identyfikuje amerykański angielski i można go utworzyć jako.
Locale en_locale = Locale('en', 'US')
Tutaj pierwszy argument to kod języka, a drugi to kod kraju. Kolejny przykład tworzenia ustawień regionalnych dla Argentyny (es-ar) jest następujący -
Locale es_locale = Locale('es', 'AR')
Lokalizacje - lokalizacje to ogólny widget używany do ustawiania ustawień regionalnych i zlokalizowanych zasobów jego elementów podrzędnych.
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'];
}
}
Tutaj CustomLocalizations to nowa klasa niestandardowa utworzona specjalnie w celu uzyskania określonej zlokalizowanej zawartości (tytułu i komunikatu) dla widżetu. of używa klasy Localizations, aby zwrócić nową klasę CustomLocalizations.
LocalizationsDelegate <T> - LocalizationsDelegate <T> to klasa fabryczna, za pośrednictwem której ładowany jest widget Localizations. Ma trzy metody do pokonania -
isSupported - akceptuje ustawienie regionalne i zwraca, czy określone ustawienie regionalne jest obsługiwane, czy nie.
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
load - akceptuje ustawienia regionalne i rozpoczyna ładowanie zasobów dla określonych ustawień regionalnych.
W tym przypadku delegat działa tylko w językach en i es.
@override
Future<CustomLocalizations> load(Locale locale) {
return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}
shouldReload - określa, czy ponowne wczytanie CustomLocalizations jest konieczne, gdy jego widget Localizations jest przebudowywany.
Tutaj metoda load zwraca CustomLocalizations. Zwróconych CustomLocalizations można użyć do uzyskania wartości tytułu i komunikatu w języku angielskim i hiszpańskim
@override
bool shouldReload(CustomLocalizationsDelegate old) => false;
Pełny kod CustomLocalizationDelegate jest następujący -
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;
}
Ogólnie rzecz biorąc, aplikacje Flutter są oparte na dwóch widżetach poziomu głównego, MaterialApp lub WidgetsApp. Flutter zapewnia gotową lokalizację dla obu widżetów i są to MaterialLocalizations i WidgetsLocaliations. Ponadto Flutter zapewnia również delegatów do ładowania MaterialLocalizations i WidgetsLocaliations i są to odpowiednio GlobalMaterialLocalizations.delegate i GlobalWidgetsLocalizations.delegate.
Stwórzmy prostą aplikację z możliwością internacjonalizacji, aby przetestować i zrozumieć koncepcję.
Utwórz nową aplikację flutter, flutter_localization_app.
Flutter wspiera internacjonalizację przy użyciu ekskluzywnego pakietu flutter, flutter_localizations. Chodzi o to, aby oddzielić zlokalizowaną zawartość od głównego zestawu SDK. Otwórz pubspec.yaml i dodaj poniższy kod, aby włączyć pakiet internacjonalizacji -
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
Studio Android wyświetli następujący alert informujący o zaktualizowaniu pliku pubspec.yaml.
Kliknij opcję Pobierz zależności. Studio Android pobierze pakiet z Internetu i odpowiednio skonfiguruje go dla aplikacji.
Zaimportuj pakiet flutter_localizations w main.dart w następujący sposób -
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/foundation.dart' show SynchronousFuture;
Tutaj celem SynchronousFuture jest synchroniczne ładowanie niestandardowych lokalizacji.
Utwórz niestandardowe lokalizacje i odpowiadającego im delegata, jak określono poniżej -
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;
}
Tutaj CustomLocalizations jest tworzony w celu obsługi lokalizacji tytułu i komunikatu w aplikacji, a CustomLocalizationsDelegate jest używany do ładowania CustomLocalizations.
Dodaj delegatów dla MaterialApp, WidgetsApp i CustomLocalization przy użyciu właściwości MaterialApp, lokalizacjiDelegates i supportedLocales, jak określono poniżej -
localizationsDelegates: [
const CustomLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', ''),
const Locale('es', ''),
],
Użyj metody CustomLocalizations of, aby uzyskać zlokalizowaną wartość tytułu i komunikatu i użyj go w odpowiednim miejscu, jak określono poniżej -
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, ),
],
),
),
);
}
}
Tutaj zmodyfikowaliśmy klasę MyHomePage ze StatefulWidget do StatelessWidget ze względu na prostotę i użyliśmy CustomLocalizations, aby uzyskać tytuł i komunikat.
Skompiluj i uruchom aplikację. Aplikacja wyświetli zawartość w języku angielskim.
Zamknij aplikację. Iść doSettings → System → Languages and Input → Languages*.
Kliknij Dodaj opcję języka i wybierz hiszpański. Spowoduje to zainstalowanie języka hiszpańskiego, a następnie wyświetli go jako jedną z opcji.
Wybierz hiszpański i przenieś go nad angielski. Spowoduje to ustawienie hiszpańskiego jako pierwszego języka i wszystko zostanie zmienione na hiszpański.
Teraz ponownie uruchom aplikację do internacjonalizacji, a zobaczysz tytuł i komunikat w języku hiszpańskim.
Możemy przywrócić język angielski, przesuwając opcję angielski nad opcję hiszpańską w ustawieniach.
Wynik aplikacji (po hiszpańsku) pokazano na zrzucie ekranu podanym poniżej -
Korzystanie z pakietu intl
Flutter dostarcza pakiet intl, aby jeszcze bardziej uprościć tworzenie zlokalizowanych aplikacji mobilnych. Pakiet intl zapewnia specjalne metody i narzędzia do półautomatycznego generowania komunikatów specyficznych dla języka.
Stwórzmy nową zlokalizowaną aplikację przy użyciu pakietu intl i zrozummy koncepcję.
Utwórz nową aplikację flutter, flutter_intl_app.
Otwórz pubspec.yaml i dodaj szczegóły pakietu.
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.15.7
intl_translation: ^0.17.3
Studio Android wyświetli alert, jak pokazano poniżej, informując, że plik pubspec.yaml został zaktualizowany.
Kliknij opcję Pobierz zależności. Studio Android pobierze pakiet z Internetu i odpowiednio skonfiguruje go dla aplikacji.
Skopiuj plik main.dart z poprzedniej próbki, flutter_internationalization_app.
Zaimportuj pakiet intl, jak pokazano poniżej -
import 'package:intl/intl.dart';
Zaktualizuj klasę CustomLocalization, jak pokazano w kodzie podanym poniżej -
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;
}
Tutaj użyliśmy trzech metod z pakietu intl zamiast metod niestandardowych. W przeciwnym razie koncepcje są takie same.
Intl.canonicalizedLocale - służy do uzyskania poprawnej nazwy ustawień regionalnych.
Intl.defaultLocale - Służy do ustawiania bieżących ustawień regionalnych
Intl.message - służy do definiowania nowych wiadomości.
import l10n/messages_all.dartplik. Wkrótce wygenerujemy ten plik
import 'l10n/messages_all.dart';
Teraz utwórz folder lib / l10n
Otwórz wiersz polecenia i przejdź do katalogu głównego aplikacji (gdzie dostępny jest pubspec.yaml) i uruchom następujące polecenie -
flutter packages pub run intl_translation:extract_to_arb --output-
dir=lib/l10n lib/main.dart
Tutaj polecenie wygeneruje plik intl_message.arb, szablon do tworzenia wiadomości w różnych lokalizacjach. Zawartość pliku jest następująca -
{
"@@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": {}
}
}
Skopiuj intl_message.arb i utwórz nowy plik, intl_en.arb.
Skopiuj intl_message.arb i utwórz nowy plik, intl_es.arb i zmień zawartość na język hiszpański, jak pokazano poniżej -
{
"@@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": {}
}
}
Teraz uruchom następujące polecenie, aby utworzyć ostateczny plik komunikatów, 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
Skompiluj i uruchom aplikację. Będzie działać podobnie do powyższej aplikacji flutter_localization_app.