# ทำ l10n แบบไม่ยากนัก?

#Dev#Flutter

คือต้องบอกตรงๆเลยว่าผมพยายามทำ Localize มานานมาก (แบบทำแอปให้รองรับหลายภาษา) แต่วิธีแบบ Official นั้นวุ่นวายมาก ต้อง Generate สร้างนู่นสร้างนี่
ตอนนี้ก็เจอ Library ตัวนี้ที่ใช้ง่ายกว่า? (คิดซะว่าเป็นทางเลีอกแล้วกันครับ)

โดยตัวที่ผมจะใช้นั้นมีชื่อว่า easy_localization (opens new window)

ป.ล. ใครมีของดีของเด็ดใช้ง่ายก็บอกกันได้นะครับ

Header

# สร้างโปรเจค

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

เมื่อรันแอปขึ้นมาก็จะเจอกับแอปในรูปแบบนี้ครับ

Title
หน้าตาแอปเมื่อเปิดมาครั้งแรก (ภาษาจะเป็นไปตามภาษาเครื่อง)

# เขียนส่วนตั้งค่าเปลี่ยนภาษา

เนื่องด้วย 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 ดู

Title
เย่ เปลี่ยนภาษาได้แล้ว

Note

แม้จะปิดแอปเปิดใหม่ ภาษาที่เราเปลี่ยนก็จะยังคงอยู่
เพราะ Library นี้มีการบันทึกค่าภาษาลงใน Shared Preferences

เหมือนจะยาวนะ แต่ก็ไม่ยาวหรอกถ้าเทียบกับ Official 😂

ดาวน์โหลด Source Code ที่นี่ (opens new window)


อัปเดตเมื่อ: 1 ปีที่แล้ว