Belajar Flutter - Internationalization & Accessibility
Episode 17 of 23

Belajar Flutter - Internationalization & Accessibility

Episode ini membuka aplikasi ke dunia yang lebih luas: internationalization dengan flutter_localizations, dukungan RTL dan locale-aware formatting, accessibility best practices lewat semantics dan focus order, serta inclusive UX dan accessibility testing.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Aplikasi yang hebat tidak membatasi penggunanya pada satu bahasa atau satu cara berinteraksi. Episode 17 membangun fondasi untuk pengguna global dan pengguna dengan kebutuhan berbeda: internationalization, dukungan teks kanan-ke-kiri, formatting yang sadar locale, dan accessibility untuk screen reader dan keyboard.

Internationalization dengan flutter_localizations

Mengaktifkan Localization

Tambahkan dukungan localization dari SDK:

Menambahkan flutter_localizations
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: ^0.19.0

Tambahkan flutter_localizations dan intl ke blok dependencies. Lalu daftarkan delegates dan locale di MaterialApp:

MaterialApp dengan dukungan locale
MaterialApp(
  localizationsDelegates: GlobalMaterialLocalizations.delegates,
  supportedLocales: const [
    Locale('id'),
    Locale('en'),
  ],
  locale: const Locale('id'),
)

supportedLocales mendeklarasikan bahasa yang didukung. GlobalMaterialLocalizations.delegates menyediakan terjemahan bawaan untuk widget Material — seperti label tanggal dan tombol default.

File ARB untuk Terjemahan

Pesan aplikasi dikelola di file .arb:

Kunci terjemahan di app_id.arb
{
  "@@locale": "id",
  "appTitle": "Aplikasi Saya",
  "greeting": "Selamat datang, {name}!"
}

File .arb berformat {"@@locale": "id", ...} dan menyimpan semua string dalam satu kunci. Flutter tool kemudian membangkitkan class bertipe-safe dari file ini, sehingga kesalahan terjemahan terdeteksi saat compile, bukan runtime.

RTL dan Locale-Aware Formatting

Dukungan RTL Otomatis

Flutter menangani layout kanan-ke-kiri secara otomatis untuk locale Arab, Ibrani, dan sejenisnya. Widget Row dan Column membalik arah sesuai Directionality yang disuntikkan oleh locale aktif. Untuk menguji, ubah locale ke bahasa RTL:

Force locale untuk pengujian
MaterialApp(
  locale: const Locale('ar'),
  supportedLocales: const [Locale('ar')],
)

MaterialApp(locale: Locale('ar')) memaksa aplikasi memakai arah RTL. Uji setiap layar dengan locale RTL — margin, ikon panah, dan posisi elemen sering kali perlu penyesuaian manual meski layout inti sudah otomatis.

Formatting yang Sadar Locale

Angka, tanggal, dan mata uang tidak boleh di-format manual. Pakai intl:

Format tanggal sesuai locale
import 'package:intl/intl.dart';
 
final formatter = DateFormat.yMMMMd(Localizations.localeOf(context).toString());
print(formatter.format(DateTime.now()));

DateFormat.yMMMMd(locale) memformat tanggal sesuai bahasa dan kebiasaan lokal. Aturan: simpan data mentah (timestamp, angka) dan format di lapisan presentasi — jangan pernah menyimpan string hasil format ke storage.

Accessibility Best Practices

Semantics untuk Screen Reader

Widget visual sering tidak terbaca oleh screen reader tanpa bantuan. Gunakan Semantics untuk memberi label:

Semantics dengan label
Semantics(
  label: 'Tombol untuk menambah jumlah',
  button: true,
  child: FloatingActionButton(
    onPressed: _tambah,
    child: const Icon(Icons.add),
  ),
)

Semantics(label: '...') memberi teks yang dibacakan screen reader. Tombol ikon tanpa teks membutuhkan label — jika tidak, pengguna screen reader hanya mendengar "tombol" tanpa makna.

Focus Order dan Keyboard

Untuk pengguna keyboard dan TV, urutan fokus penting:

Mengatur urutan fokus
FocusTraversalGroup(
  policy: OrderedTraversalPolicy(),
  child: Column(
    children: [
      TextField(decoration: const InputDecoration(labelText: 'Email')),
      TextField(decoration: const InputDecoration(labelText: 'Password')),
      ElevatedButton(onPressed: login, child: const Text('Masuk')),
    ],
  ),
)

OrderedTraversalPolicy memaksa urutan fokus mengikuti urutan visual child. Pastikan semua elemen interaktif bisa dijangkau keyboard dan order-nya masuk akal — dari email, password, ke tombol masuk.

Kontras dan Ukuran Teks

Kontras warna yang rendah menyulitkan pembacaan. Gunakan warna dari ColorScheme yang sudah dirancang kontrasnya, dan uji dengan MediaQuery.textScalerOf(context) untuk memastikan layout tidak pecah saat ukuran teks diperbesar.

Inclusive UX dan Accessibility Testing

Testing dengan Semantics

Flutter menyediakan test untuk semantics:

Widget test untuk semantics
testWidgets('label tombol tersedia untuk screen reader', (tester) async {
  await tester.pumpWidget(const MaterialApp(home: MyButton()));
 
  expect(
    find.bySemanticsLabel('Tombol untuk menambah jumlah'),
    findsOneWidget,
  );
});

find.bySemanticsLabel mencari widget berdasarkan label semantics. Test seperti ini memastikan aksesibilitas tidak rusak oleh perubahan tak sengaja.

Memeriksa dengan Tool

  • Aktifkan TalkBack (Android) dan VoiceOver (iOS) untuk uji manual.
  • Gunakan tab Accessibility di Flutter DevTools untuk menemukan masalah kontras dan semantics.
  • Uji dengan ukuran teks maksimum dan orientasi landscape.

Jadikan aksesibilitas bagian dari definisi selesai, bukan fitur tambahan di akhir.

Penutup

Inti yang harus dibawa pulang:

  • Tambahkan flutter_localizations dan intl untuk dukungan bahasa.
  • Kelola string di file .arb agar terjemahan bertipe-safe.
  • Flutter menangani RTL otomatis; tetap uji setiap layar dengan locale RTL.
  • Format tanggal dan angka dengan intl, simpan data mentah.
  • Semantics memberi label untuk screen reader; atur focus order untuk keyboard.
  • Uji aksesibilitas dengan find.bySemanticsLabel dan tools bawaan.

Di episode 18 selanjutnya kita membahas advanced rendering dan architecture — custom render objects dan widgets, adaptasi spesifik platform dan aplikasi responsif, micro frontends dan plugin-driven architectures, serta hybrid app patterns dengan web dan desktop. Kalian masuk ke area lanjutan Flutter.

Belajar Flutter - Internationalization & Accessibility | Belajar Flutter