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);

      ที่นี่ผู้รับมอบสิทธิ์ทำงานสำหรับภาษา en และ es เท่านั้น

    • load - ยอมรับโลแคลและเริ่มโหลดทรัพยากรสำหรับโลแคลที่ระบุ

@override 
Future<CustomLocalizations> load(Locale locale) { 
   return SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale)); 
}

      ที่นี่วิธีการโหลดจะส่งคืน CustomLocalizations CustomLocalizations ที่ส่งคืนสามารถใช้เพื่อรับค่าของชื่อเรื่องและข้อความทั้งในภาษาอังกฤษและภาษาสเปน

    • shouldReload - ระบุว่าจำเป็นต้องทำการรีโหลด CustomLocalizations หรือไม่เมื่อมีการสร้างวิดเจ็ต Localizations

@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