การใช้ Localization (l10n) ใน Flutter
จากบทความที่แล้ว เราได้เรียนรู้เกี่ยวกับการทำ Internationalization (i18n) เพื่อรองรับหลายภาษาในแอป Flutter ของเรา แต่การรองรับภาษาอย่างเดียวอาจไม่เพียงพอที่จะทำให้แอปพลิเคชันของเราเข้าถึงผู้ใช้ในแต่ละท้องถิ่นได้อย่างแท้จริง เพราะแต่ละท้องถิ่นอาจมีรูปแบบการแสดงผลข้อมูลที่แตกต่างกัน เช่น รูปแบบวันที่, รูปแบบตัวเลข, สกุลเงิน และอื่นๆ อีกมากมาย นี่คือที่มาของ Localization (l10n) ที่เราจะมาเจาะลึกกันในบทความนี้
Localization (l10n) คือกระบวนการปรับแต่งแอปพลิเคชันให้เข้ากับวัฒนธรรมและประเพณีของท้องถิ่นนั้นๆ นอกเหนือจากแค่การแปลภาษาแล้ว ยังรวมถึงการปรับรูปแบบการแสดงผลข้อมูลให้สอดคล้องกับความคาดหวังของผู้ใช้ในแต่ละท้องถิ่นอีกด้วย
NumberFormat
NumberFormat เป็น class ที่อยู่ใน package intl ซึ่งเป็น package เดียวกับที่เราใช้สำหรับการทำ i18n ในบทความที่แล้ว NumberFormat ช่วยให้เราสามารถจัดรูปแบบตัวเลขให้สอดคล้องกับ locale ที่กำหนดได้
เหตุผลเชิงออกแบบ: ทำไมเราต้องใช้ NumberFormat แทนที่จะใช้ .toString() หรือวิธีการอื่นๆ? เหตุผลหลักคือ NumberFormat จะจัดการเรื่องรูปแบบตัวเลขตาม locale ที่กำหนดให้โดยอัตโนมัติ เช่น การใช้ comma (,) หรือ period (.) เป็นตัวคั่นหลักพัน, การใช้สัญลักษณ์สกุลเงินที่ถูกต้อง และอื่นๆ การใช้ .toString() อาจทำให้เกิดความไม่สอดคล้องกับความคาดหวังของผู้ใช้ในบาง locale
ตัวอย่างการใช้งาน:
import 'package:intl/intl.dart';
void main() {
// กำหนด locale เป็นภาษาไทย (ประเทศไทย)
final locale = 'th_TH';
// ตัวเลขที่ต้องการจัดรูปแบบ
final number = 1234567.89;
// สร้าง NumberFormat สำหรับ locale ที่กำหนด
final numberFormat = NumberFormat.decimalPattern(locale);
// จัดรูปแบบตัวเลข
final formattedNumber = numberFormat.format(number);
// แสดงผลลัพธ์
print('Formatted Number (th_TH): $formattedNumber'); // Output: Formatted Number (th_TH): 1,234,567.89
// สร้าง NumberFormat สำหรับสกุลเงินบาท (THB)
final currencyFormat = NumberFormat.currency(locale: locale, symbol: '฿');
// จัดรูปแบบตัวเลขเป็นสกุลเงิน
final formattedCurrency = currencyFormat.format(number);
// แสดงผลลัพธ์
print('Formatted Currency (th_TH): $formattedCurrency'); // Output: Formatted Currency (th_TH): ฿1,234,567.89
// สร้าง NumberFormat สำหรับเปอร์เซ็นต์
final percentFormat = NumberFormat.percentPattern(locale);
// จัดรูปแบบตัวเลขเป็นเปอร์เซ็นต์
final formattedPercent = percentFormat.format(0.75);
// แสดงผลลัพธ์
print('Formatted Percent (th_TH): $formattedPercent'); // Output: Formatted Percent (th_TH): 75%
}
จากตัวอย่าง จะเห็นได้ว่า NumberFormat มีรูปแบบการจัดรูปแบบตัวเลขให้เลือกหลากหลาย เช่น decimalPattern, currency, และ percentPattern แต่ละรูปแบบจะมีการปรับแต่งให้สอดคล้องกับ locale ที่กำหนด
แนวปฏิบัติที่ดี:
- กำหนด locale ให้ถูกต้อง: ตรวจสอบให้แน่ใจว่า locale ที่กำหนดนั้นถูกต้องและสอดคล้องกับภาษาและประเทศที่ต้องการรองรับ
- เลือกรูปแบบการจัดรูปแบบที่เหมาะสม: เลือกรูปแบบการจัดรูปแบบที่เหมาะสมกับประเภทของข้อมูล (เช่น ตัวเลข, สกุลเงิน, เปอร์เซ็นต์)
- หลีกเลี่ยงการ hardcode รูปแบบ: หลีกเลี่ยงการ hardcode รูปแบบการจัดรูปแบบตัวเลขด้วยตัวเอง เพราะอาจทำให้เกิดความไม่สอดคล้องกับ locale ที่แตกต่างกัน
DateFormat
DateFormat เป็น class ที่อยู่ใน package intl เช่นเดียวกัน และใช้สำหรับจัดรูปแบบวันที่และเวลาให้สอดคล้องกับ locale ที่กำหนด
เหตุผลเชิงออกแบบ: เช่นเดียวกับ NumberFormat การใช้ DateFormat ช่วยให้เราสามารถแสดงวันที่และเวลาในรูปแบบที่ผู้ใช้ในแต่ละ locale คุ้นเคย เช่น รูปแบบปี/เดือน/วัน หรือ เดือน/วัน/ปี, การใช้ชื่อเดือนแบบเต็มหรือแบบย่อ, และอื่นๆ การใช้ .toString() บน object DateTime อาจทำให้เกิดความไม่สอดคล้องกับความคาดหวังของผู้ใช้
ตัวอย่างการใช้งาน:
import 'package:intl/intl.dart';
void main() {
// กำหนด locale เป็นภาษาไทย (ประเทศไทย)
final locale = 'th_TH';
// วันที่และเวลาที่ต้องการจัดรูปแบบ
final dateTime = DateTime.now();
// สร้าง DateFormat สำหรับ locale ที่กำหนด
final dateFormat = DateFormat('dd/MM/yyyy', locale);
// จัดรูปแบบวันที่
final formattedDate = dateFormat.format(dateTime);
// แสดงผลลัพธ์
print('Formatted Date (th_TH): $formattedDate'); // Output: Formatted Date (th_TH): (ขึ้นอยู่กับวันที่ปัจจุบัน) เช่น 27/10/2023
// สร้าง DateFormat สำหรับรูปแบบวันที่และเวลาแบบเต็ม
final fullDateFormat = DateFormat.yMMMMEEEEd(locale);
// จัดรูปแบบวันที่และเวลา
final formattedFullDate = fullDateFormat.format(dateTime);
// แสดงผลลัพธ์
print('Formatted Full Date (th_TH): $formattedFullDate'); // Output: Formatted Full Date (th_TH): (ขึ้นอยู่กับวันที่ปัจจุบัน) เช่น วันศุกร์ที่ 27 ตุลาคม 2023
// สร้าง DateFormat สำหรับเวลา
final timeFormat = DateFormat.Hm(locale);
// จัดรูปแบบเวลา
final formattedTime = timeFormat.format(dateTime);
// แสดงผลลัพธ์
print('Formatted Time (th_TH): $formattedTime'); // Output: Formatted Time (th_TH): (ขึ้นอยู่กับเวลาปัจจุบัน) เช่น 15:30
}
จากตัวอย่าง จะเห็นได้ว่า DateFormat มีรูปแบบการจัดรูปแบบวันที่และเวลาให้เลือกหลากหลาย และเราสามารถกำหนดรูปแบบเองได้โดยใช้ pattern ที่กำหนด (เช่น dd/MM/yyyy) หรือใช้รูปแบบสำเร็จรูป เช่น yMMMMEEEEd (ปี เดือน (แบบเต็ม) วันในสัปดาห์ (แบบเต็ม) วันที่)
แนวปฏิบัติที่ดี:
- กำหนด locale ให้ถูกต้อง: ตรวจสอบให้แน่ใจว่า locale ที่กำหนดนั้นถูกต้องและสอดคล้องกับภาษาและประเทศที่ต้องการรองรับ
- เลือกรูปแบบการจัดรูปแบบที่เหมาะสม: เลือกรูปแบบการจัดรูปแบบที่เหมาะสมกับความต้องการในการแสดงผลวันที่และเวลา
- ศึกษา pattern ของ DateFormat: ทำความเข้าใจ pattern ที่ใช้ในการกำหนดรูปแบบวันที่และเวลา เพื่อให้สามารถสร้างรูปแบบที่ต้องการได้อย่างถูกต้อง
- พิจารณา timezone: หากแอปพลิเคชันของคุณเกี่ยวข้องกับเวลาในหลาย timezone ให้พิจารณาการใช้
TimeZoneclass เพื่อจัดการเรื่อง timezone อย่างถูกต้อง
Trade-offs
การใช้ NumberFormat และ DateFormat มีข้อดีคือช่วยให้เราสามารถปรับรูปแบบการแสดงผลข้อมูลให้สอดคล้องกับ locale ที่กำหนดได้อย่างง่ายดาย แต่ก็มีข้อเสียคืออาจทำให้โค้ดของเราซับซ้อนขึ้นเล็กน้อย และอาจต้องใช้เวลาในการเรียนรู้ pattern ของ DateFormat
นอกจากนี้ การใช้ NumberFormat และ DateFormat อาจส่งผลกระทบต่อ performance ของแอปพลิเคชันเล็กน้อย เนื่องจากต้องมีการสร้าง object และทำการคำนวณเพื่อจัดรูปแบบข้อมูล แต่โดยทั่วไปแล้ว ผลกระทบนี้จะไม่มากนัก และสามารถลดลงได้โดยการ cache object NumberFormat และ DateFormat ที่สร้างขึ้นแล้ว
สรุป
Localization (l10n) เป็นส่วนสำคัญในการสร้างแอปพลิเคชันที่เข้าถึงผู้ใช้ทั่วโลกได้อย่างแท้จริง การใช้ NumberFormat และ DateFormat ช่วยให้เราสามารถปรับรูปแบบการแสดงผลตัวเลข วันที่ และเวลาให้สอดคล้องกับ locale ที่กำหนดได้อย่างง่ายดาย ทำให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีขึ้นและรู้สึกเป็นกันเองกับแอปพลิเคชันของเรามากขึ้น
ในบทความถัดไป เราจะมาเรียนรู้เกี่ยวกับการ Optimize Performance ของแอป Flutter กัน ซึ่งเป็นอีกหนึ่งหัวข้อที่สำคัญในการสร้างแอปพลิเคชันที่มีคุณภาพ