Flutter - การทำให้เป็นสากล
ปัจจุบันลูกค้าจากประเทศต่างๆใช้แอปพลิเคชันมือถือดังนั้นแอปพลิเคชันจึงจำเป็นต้องแสดงเนื้อหาในภาษาต่างๆ การเปิดใช้งานแอปพลิเคชันเพื่อทำงานในหลายภาษาเรียกว่า Internationalizing the application
เพื่อให้แอปพลิเคชันทำงานในภาษาอื่นก่อนอื่นควรค้นหาตำแหน่งที่ตั้งปัจจุบันของระบบที่แอปพลิเคชันกำลังทำงานอยู่จากนั้นจึงต้องแสดงเนื้อหาในภาษานั้น ๆ และกระบวนการนี้เรียกว่า Localization
เฟรมเวิร์ก Flutter มีคลาสพื้นฐานสามคลาสสำหรับการแปลเป็นภาษาท้องถิ่นและคลาสยูทิลิตี้ที่ครอบคลุมซึ่งได้มาจากคลาสพื้นฐานเพื่อแปลแอปพลิเคชัน
คลาสพื้นฐานมีดังนี้ -
Locale - Locale คือคลาสที่ใช้ในการระบุภาษาของผู้ใช้ ตัวอย่างเช่น en-us ระบุภาษาอังกฤษแบบอเมริกันและสามารถสร้างเป็น
Locale en_locale = Locale('en', 'US')
ที่นี่อาร์กิวเมนต์แรกคือรหัสภาษาและอาร์กิวเมนต์ที่สองคือรหัสประเทศ อีกตัวอย่างหนึ่งของการสร้างภาษาสเปนในอาร์เจนตินา (es-ar)มีดังนี้ -
Locale es_locale = Locale('es', 'AR')
การแปลเป็นภาษาท้องถิ่น - การแปลเป็นวิดเจ็ตทั่วไปที่ใช้ในการตั้งค่าสถานที่และทรัพยากรที่แปลเป็นภาษาท้องถิ่นของลูก
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'];
}
}
ที่นี่ CustomLocalizations เป็นคลาสแบบกำหนดเองใหม่ที่สร้างขึ้นโดยเฉพาะเพื่อรับเนื้อหาที่แปลเป็นภาษาท้องถิ่น (ชื่อเรื่องและข้อความ) สำหรับวิดเจ็ต วิธีการใช้คลาส Localizations เพื่อส่งคืนคลาส CustomLocalizations ใหม่
LocalizationsDelegate <T> - LocalizationsDelegate <T> เป็นคลาสโรงงานที่โหลดวิดเจ็ต Localizations มีสามวิธีที่สามารถกำจัดได้มากเกินไป -
isSupported - ยอมรับโลแคลและส่งคืนว่ารองรับโลแคลที่ระบุหรือไม่
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
load - ยอมรับโลแคลและเริ่มโหลดทรัพยากรสำหรับโลแคลที่ระบุ
ที่นี่ผู้รับมอบสิทธิ์ทำงานสำหรับภาษา en และ es เท่านั้น
@override
Future<CustomLocalizations> load(Locale locale) {
return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}
shouldReload - ระบุว่าจำเป็นต้องทำการรีโหลด CustomLocalizations หรือไม่เมื่อมีการสร้างวิดเจ็ต Localizations
ที่นี่วิธีการโหลดจะส่งคืน CustomLocalizations CustomLocalizations ที่ส่งคืนสามารถใช้เพื่อรับค่าของชื่อเรื่องและข้อความทั้งในภาษาอังกฤษและภาษาสเปน
@override
bool shouldReload(CustomLocalizationsDelegate old) => false;
รหัสที่สมบูรณ์ของ CustomLocalizationDelegate มีดังนี้ -
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;
}
โดยทั่วไปแอปพลิเคชัน Flutter จะขึ้นอยู่กับวิดเจ็ตระดับรูทสองตัวคือ MaterialApp หรือ WidgetsApp Flutter จัดเตรียมการแปลพร้อมสำหรับวิดเจ็ตทั้งสองและเป็น MaterialLocalizations และ WidgetsLocaliation นอกจากนี้ Flutter ยังให้ผู้รับมอบสิทธิ์ในการโหลด MaterialLocalizations และ WidgetsLocaliation และเป็น GlobalMaterialLocalizations.delegate และ GlobalWidgetsLocalizations.delegate ตามลำดับ
ให้เราสร้างแอปพลิเคชันที่เปิดใช้งานการทำให้เป็นสากลอย่างง่ายเพื่อทดสอบและทำความเข้าใจแนวคิด
สร้างแอปพลิเคชัน flutter ใหม่ flutter_localization_app
Flutter รองรับความเป็นสากลโดยใช้แพ็คเกจ Flutter พิเศษ flutter_localizations แนวคิดคือการแยกเนื้อหาที่แปลเป็นภาษาท้องถิ่นออกจาก SDK หลัก เปิด pubspec.yaml และเพิ่มโค้ดด้านล่างเพื่อเปิดใช้งานแพ็คเกจสากล -
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
Android studio จะแสดงการแจ้งเตือนต่อไปนี้ว่ามีการอัปเดต pubspec.yaml
คลิกตัวเลือกรับการอ้างอิง Android studio จะได้รับแพ็คเกจจากอินเทอร์เน็ตและกำหนดค่าให้เหมาะสมกับแอปพลิเคชัน
นำเข้าแพ็คเกจ flutter_localizations ใน main.dart ดังนี้ -
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/foundation.dart' show SynchronousFuture;
จุดประสงค์ของ SynchronousFuture คือการโหลดการแปลแบบกำหนดเองแบบซิงโครนัส
สร้างการแปลที่กำหนดเองและตัวแทนที่เกี่ยวข้องตามที่ระบุด้านล่าง -
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;
}
ที่นี่ CustomLocalizations ถูกสร้างขึ้นเพื่อรองรับการแปลสำหรับหัวเรื่องและข้อความในแอปพลิเคชันและ CustomLocalizationsDelegate ใช้เพื่อโหลด CustomLocalizations
เพิ่มผู้รับมอบสิทธิ์สำหรับ MaterialApp, WidgetsApp และ CustomLocalization โดยใช้คุณสมบัติ MaterialApp, localizationsDelegates และ supportedLocales ตามที่ระบุด้านล่าง -
localizationsDelegates: [
const CustomLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', ''),
const Locale('es', ''),
],
ใช้เมธอด CustomLocalizations เพื่อรับค่าที่แปลเป็นภาษาท้องถิ่นของชื่อเรื่องและข้อความและใช้ในตำแหน่งที่เหมาะสมตามที่ระบุด้านล่าง -
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, ),
],
),
),
);
}
}
ที่นี่เราได้แก้ไขคลาส MyHomePage จาก StatefulWidget เป็น StatelessWidget ด้วยเหตุผลด้านความเรียบง่ายและใช้ CustomLocalizations เพื่อรับชื่อและข้อความ
รวบรวมและเรียกใช้แอปพลิเคชัน แอปพลิเคชันจะแสดงเนื้อหาเป็นภาษาอังกฤษ
ปิดแอปพลิเคชัน ไปที่Settings → System → Languages and Input → Languages*.
คลิกเพิ่มตัวเลือกภาษาแล้วเลือกภาษาสเปน เพื่อติดตั้งภาษาสเปนจากนั้นแสดงรายการเป็นหนึ่งในตัวเลือก
เลือกภาษาสเปนและย้ายไปไว้เหนือภาษาอังกฤษ สิ่งนี้จะตั้งค่าเป็นภาษาสเปนเป็นภาษาแรกและทุกอย่างจะเปลี่ยนเป็นข้อความภาษาสเปน
ตอนนี้เปิดแอปพลิเคชันการทำให้เป็นสากลอีกครั้งและคุณจะเห็นชื่อและข้อความเป็นภาษาสเปน
เราสามารถเปลี่ยนภาษากลับเป็นภาษาอังกฤษได้โดยเลื่อนตัวเลือกภาษาอังกฤษเหนือตัวเลือกภาษาสเปนในการตั้งค่า
ผลลัพธ์ของแอปพลิเคชัน (เป็นภาษาสเปน) แสดงอยู่ในภาพหน้าจอด้านล่าง -
การใช้แพ็คเกจ intl
Flutter มีแพ็คเกจ intl เพื่อลดความซับซ้อนในการพัฒนาแอปพลิเคชันมือถือที่แปลเป็นภาษาท้องถิ่น แพ็คเกจ intl มีวิธีการและเครื่องมือพิเศษในการสร้างข้อความเฉพาะภาษาแบบกึ่งอัตโนมัติ
ให้เราสร้างแอปพลิเคชันที่แปลเป็นภาษาท้องถิ่นใหม่โดยใช้แพ็คเกจ intl และทำความเข้าใจกับแนวคิด
สร้างแอปพลิเคชัน Flutter ใหม่ flutter_intl_app
เปิด pubspec.yaml และเพิ่มรายละเอียดแพ็คเกจ
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: ^0.15.7
intl_translation: ^0.17.3
Android studio จะแสดงการแจ้งเตือนดังที่แสดงด้านล่างเพื่อแจ้งว่ามีการอัปเดต pubspec.yaml
คลิกตัวเลือกรับการอ้างอิง Android studio จะได้รับแพ็คเกจจากอินเทอร์เน็ตและกำหนดค่าให้เหมาะสมกับแอปพลิเคชัน
คัดลอก main.dart จากตัวอย่างก่อนหน้า flutter_internationalization_app
นำเข้า intl pacakge ตามที่แสดงด้านล่าง -
import 'package:intl/intl.dart';
อัปเดตคลาส CustomLocalization ดังแสดงในโค้ดด้านล่าง -
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;
}
ที่นี่เราได้ใช้สามวิธีจากแพ็คเกจ intl แทนวิธีกำหนดเอง มิฉะนั้นแนวคิดจะเหมือนกัน
Intl.canonicalizedLocale - ใช้เพื่อรับชื่อภาษาที่ถูกต้อง
Intl.defaultLocale - ใช้เพื่อตั้งค่าภาษาปัจจุบัน
Intl.message - ใช้เพื่อกำหนดข้อความใหม่
นำเข้า l10n/messages_all.dartไฟล์. เราจะสร้างไฟล์นี้ในไม่ช้า
import 'l10n/messages_all.dart';
ตอนนี้สร้างโฟลเดอร์ lib / l10n
เปิดพรอมต์คำสั่งและไปที่ไดเร็กทอรีรูทของแอ็พพลิเคชัน (ซึ่งมี pubspec.yaml) และรันคำสั่งต่อไปนี้ -
flutter packages pub run intl_translation:extract_to_arb --output-
dir=lib/l10n lib/main.dart
ที่นี่คำสั่งจะสร้างไฟล์ intl_message.arb ซึ่งเป็นเทมเพลตสำหรับสร้างข้อความในภาษาอื่น เนื้อหาของไฟล์มีดังนี้ -
{
"@@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": {}
}
}
คัดลอก intl_message.arb และสร้างไฟล์ใหม่ intl_en.arb
คัดลอก intl_message.arb และสร้างไฟล์ใหม่ intl_es.arb และเปลี่ยนเนื้อหาเป็นภาษาสเปนตามที่แสดงด้านล่าง -
{
"@@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": {}
}
}
ตอนนี้เรียกใช้คำสั่งต่อไปนี้เพื่อสร้างไฟล์ข้อความสุดท้าย 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
รวบรวมและเรียกใช้แอปพลิเคชัน มันจะทำงานคล้ายกับแอปพลิเคชันด้านบน flutter_localization_app