# ทำ l10n แบบไม่ยากนัก?
#Dev#Flutterคือต้องบอกตรงๆเลยว่าผมพยายามทำ Localize มานานมาก (แบบทำแอปให้รองรับหลายภาษา) แต่วิธีแบบ Official นั้นวุ่นวายมาก ต้อง Generate สร้างนู่นสร้างนี่
ตอนนี้ก็เจอ Library ตัวนี้ที่ใช้ง่ายกว่า? (คิดซะว่าเป็นทางเลีอกแล้วกันครับ)
โดยตัวที่ผมจะใช้นั้นมีชื่อว่า easy_localization (opens new window)
ป.ล. ใครมีของดีของเด็ดใช้ง่ายก็บอกกันได้นะครับ
# สร้างโปรเจค
flutter create multi_locale
และเมื่อเราเปิดดูไฟล์ lib/main.dart
เราก็จะเห็น (ก็โค้ดเริ่มต้นนั่นล่ะ ข้ามๆไปได้)
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
# เริ่ม Setup กันเลยครับ
ค่อยๆทำไปครับไม่เยอะ
# เพิ่ม Dependencies
โดยเราจะต้องเพิ่ม dependencies ที่ไฟล์ pubspec.yaml
ดังนี้
...
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
easy_localization: ^1.3.1 # หรือจะใช้ Version ไหนก็ตามแต่สะดวกครับ
...
ต่อไปเราจะทำการเพิ่ม assets หรือไฟล์คำแปลของเรา ให้ตัว Flutter รู้ว่าจะทำการใช้ไฟล์ไหนบ้าง โดยการเลื่อนไปข้างล่างของไฟล์ pubspec.yaml
...
flutter:
...
assets:
- assets/lang/en-US.json
- assets/lang/th-TH.json
...
จากนั้นก็รัน
flutter pub get
# เพิ่มไฟล์ภาษาต่างๆ
จากนั้นให้ทำการเพิ่มไฟล์ภาษาครับ เช่น assets/lang/en-US.json
{
"app": {
"title": "Multi locale clicker",
"description": "You have pushed the button this many times"
},
"counter": {
"zero": "{} times",
"one": "{} time",
"other": "{} times"
}
}
และ assets/lang/th-TH.json
{
"app": {
"title": "Multi locale clicker",
"description": "คลิกสิคลิกหลายๆที"
},
"counter": {
"zero": "{} ครั้ง",
"one": "{} ครั้ง",
"other": "{} ครั้ง"
}
}
Note
counter ตั้งใจทำไว้เพื่อรองรับ Plural ในภาษาอังกฤษ โดยจะต้องกำหนดไว้ชั้นนอกสุด และเขียนในรูปแบบด้านบนเท่านั้น (เพราะ Library เขียนมาแบบนี้)
# มาใส่ easy_localization ลงในแอปของเรา
หลายขั้นตอนค่อยๆทำไปครับ โดยเราจะทำการแก้ไฟล์ lib/main.dart
กัน
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:easy_localization/easy_localization.dart';
void main() => runApp(EasyLocalization(child: MyApp()));
class MyApp extends StatelessWidget {
...
สังเกตว่ามีการเพิ่ม Widget EasyLocalization คลุม MyApp ไปครับ
โดยเจ้า EasyLocalization จะทำให้เราสามารถรู้ได้ว่าตอนนี้ Locale เป็นภาษาอะไร หรือสามารถเปลี่ยน Locale ผ่านเจ้าตัวนี้ก็ได้เช่นกันครับ โดยจะมีฟังก์ชันชื่อ changeLocale อยู่
ทีนี้ก็ทำการเพิ่ม Localization ให้กับ MaterialApp (หรือ CupertinoApp)
...
return MaterialApp(
title: 'Flutter Demo',
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
//app-specific localization
EasylocaLizationDelegate(
locale: data.locale,
path: 'assets/lang',
),
],
supportedLocales: [Locale('en', 'US'), Locale('th', 'TH')],
locale: data.savedLocale,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
...
ก็เป็นอันเรียบร้อย ทีนี้มาเริ่มแปลภาษากันครับ โดยการใช้คำสั่ง AppLocalizations.of(context).tr('...')
...
return MaterialApp(
...
home: Builder(
builder: (context) => MyHomePage(
title: AppLocalizations.of(context).tr('app.title'),
),
),
);
...
Note
เพราะ AppLocalizations ถูกสร้างที่ Widget MaterialApp ถ้าอยากจะเรียกใช้ AppLocalizations ที่ MaterialApp ผมต้องซ้อนผ่าน Widget Builder ก่อน
แปลในส่วนของหน้าหลักกันต่อ
...
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
AppLocalizations.of(context).tr('app.description') + ':',
),
Text(
AppLocalizations.of(context).plural('counter', _counter),
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
...
เมื่อรันแอปขึ้นมาก็จะเจอกับแอปในรูปแบบนี้ครับ
# เขียนส่วนตั้งค่าเปลี่ยนภาษา
เนื่องด้วย Library ตัวนี้เขียนไว้ให้จำภาษาแรกไว้ (คือเปลี่ยนภาษาเครื่องเป็นภาษาอื่นก็จะไม่มีการเปลี่ยนตาม) ถ้าเราต้องการเปลี่ยนภาษาเราอาจจะต้องเขียนส่วนของการตั้งค่าเพิ่มเอง
...
var data = EasyLocalizationProvider.of(context).data;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
FlatButton(
child: Text(
'Toggle lang',
style: TextStyle(color: Colors.white),
),
onPressed: () => setState(() {
if (data.savedLocale.languageCode == 'en') {
data.changeLocale(Locale('th', 'TH'));
} else {
data.changeLocale(Locale('en', 'US'));
}
}),
)
],
),
...
ทีนี้ลองกดปุ่ม Toggle lang ดู
Note
แม้จะปิดแอปเปิดใหม่ ภาษาที่เราเปลี่ยนก็จะยังคงอยู่
เพราะ Library นี้มีการบันทึกค่าภาษาลงใน Shared Preferences
เหมือนจะยาวนะ แต่ก็ไม่ยาวหรอกถ้าเทียบกับ Official 😂
ดาวน์โหลด Source Code ที่นี่ (opens new window)