Flutter Localization
How to create multiple language app with Flutter
Flutter Localization
How to create multiple language app with Flutter

Photo by Liam Desic on Unsplash
Pengenalan
Fitur multiple language atau pengaturan bahasa pada aplikasi merupakan fitur yang sederhana. Di native sendiri seperti di Android (saya bahasnya Android karena saya basic di Android) untuk membuat fitur multiple language proses pembuatannya cukup gampang. Kita hanya perlu menyediakan aset dalam bentuk file strings.xml untuk semua bahasa yang ingin kita buat. Berikut contoh asetnya di projek native Android.

Aset bahasa English dan Indonesia
Lalu, kita cuma perlu tambahkan sedikit bumbu-bumbu magic coding logika untuk membuat app kita bisa berubah bahasanya sesuai dengan pengaturan bahasanya.
Bagaimana Dengan Flutter
Di Flutter, pada awal-awal peluncuran versi stabilnya saya coba cari-cari di internet ternyata pembuatan fitur bahasa ini ternyata cukup susah untuk menemukan tulisan tentang hal tersebut. Setelah saya berusaha mencari-cari caranya ternyata tidak ada hasilnya sama sekali. Dengan berberat hati akhirnya saya merelakan rasa keingintahuan saya waktu itu. Lalu, seiring berjalannya waktu dari akhir tahun 2018 dimana, itu waktu pertama kalinya saya mencoba Flutter lalu, sampai pada hari tulisan ini dipublikasikan dan rasa penasaran saya itu masih ada. Dan akhirnya saya berhasil juga menemukan caranya untuk mengubah bahasa pada app di Flutter. Berikut ialah contoh projek yang saya implementasikan pengaturan bahasa di Flutter.
[embed]Contoh projek yang saya implementasikan fitur multiple language
Mulai Pembuatan Contoh Projek
Contoh 1
Di Flutter untuk membuat fitur pengaturan bahasa kita bisa pakai plugin berikut.
Silakan kita buat projek baru di Flutter. Untuk contoh nama projeknya bebas tapi kalau mau ikuti punya saya juga boleh. Berikut contoh nama projek punya saya.

Buat projek baru
Lalu, kita tambahkan plugin diatas tadi kedalam projek kita. Caranya, kita buka file pubspec.yaml. Lalu, buat flutter_localizations didalam dependencies dan tambahkan intl_translation: <latest_version> . Berikut kode lengkapnya.
dependencies:
flutter:
sdk: flutter
flutter_localizations:
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
intl_translation: ^0.17.7
Lalu, kita unduh paketnya dengan perintah flutter packages get .
Buat Class MyLocalization
Class MyLocalization berfungsi sebagai tempat kita mendeklarasikan setiap kata-kata yang mau kita buat bahasanya. Silakan buat class tersebut didalam package lib/locale. Dan nama file-nya my_localization.dart.
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class MyLocalization {
static Future<MyLocalization> 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 MyLocalization();
});
}
static MyLocalization of (BuildContext context) {
return Localizations.of<MyLocalization>(context, MyLocalization);
}
String get helloWorld {
return Intl.message(
'Hello World',
name: 'helloWorld',
desc: 'Kata Hello World', /* Optional */
);
}
}
Pada kode diatas, seharusnya kita akan mendapatkan error pada baris kode berikut.

Error initializeMessages
Error tersebut untuk saat ini kita abaikan saja karena nantinya error tersebut akan hilang setelah kita selesai melewati langkah-langkah selanjutnya.
Jadi, pada kode diatas bisa kita lihat bahwa di fungsi getter helloWorld merupakan salah satu contoh String yang akan kita coba buat dalam 2 bahasa yaitu bahasa Inggris dan Indonesia. Dan property desc itu sifatnya opsional jadi boleh kita isi dengan keterangan atau empty string.
Buat Class MyLocalizationDelegate
Class MyLocalizationDelegate merupakan class yang kita turunkan dari class LocalizationDelegate dimana, class ini berfungsi untuk menterjemahkan kumpulan list String yang sudah kita buat tadi di dalam class MyLocalization. Sekarang silakan kita buat class MyLocalizationDelegate didalam package yang sama dengan class MyLocalization. Dan beri nama file-nya my_localization_delegate.dart.
import 'package:flutter/material.dart';
import 'package:flutter_language/lib/locale/my_localization.dart';
class MyLocalizationDelegate extends LocalizationsDelegate<MyLocalization> {
final Locale locale;
const MyLocalizationDelegate(this.locale);
@override
bool isSupported(Locale locale) {
return ['en', 'id'].contains(locale.languageCode);
}
@override
Future<MyLocalization> load(Locale locale) {
return MyLocalization.load(locale);
}
@override
bool shouldReload(LocalizationsDelegate<MyLocalization> old) {
return false;
}
}
Pada kode diatas, kita ada mendeklarasikan bahasa apa saja yang akan didukung oleh app kita. Contoh diatas kita buat app kita akan mendukung dalam 2 bahasa yaitu bahasa Inggris dan Indonesia.
Buat File .arb
Sebelum kita membuat file .arb-nya kita perlu membuat satu package baru dengan nama lib/l10n dimana nantinya semua kumpulan String yang sudah diterjemahkan akan diletakkan didalam package tersebut. Untuk membuat file .arb silakan jalankan perintah berikut.
flutter pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/locale/my_localization.dart
Jalankan perintah diatas dengan kondisi kita sudah berada didalam direktori root projek kita.

Perintah untuk membuat file .arb
Adapun format dari perintah diatas adalah seperti berikut.
flutter pub run intl_translation:extract_to_arb --output-dir=<direktori_file_arb_nya> <file_localization_yang_sudah_kita_buat>
Jika berhasil seharusnya di dalam package lib/l10n tadi akan terbentuk sebuah file dengan nama intl_messages.arb.

File intl_messages.arb
Pada gambar diatas kita lihat file intl_messages.arb sudah terbentuk dan file my_localization.dart masih ada error. Untuk error tersebut kita abaikan saja dulu ya karena nantinya error tersebut akan hilang setelah kita melewati beberapa langkah lagi.
Buat Aset Bahasa Inggris dan Indonesia
Untuk membuat aset bahasa Inggris dan Indonesia kita perlu membuka file intl_messages.arb dan didalamnya bisa kita lihat kira-kira isinya seperti berikut.
{
"@@last_modified": "2019-11-17T16:07:23.398925",
"helloWorld": "Hello World",
"@helloWorld": {
"description": Word Hello World",
"type": "text",
"placeholders": {}
}
}
Untuk membuat aset bahasa Inggris dan Indonesianya kita cuma perlu menyalin isi dari file intl_messages.arb dan masukkan kedalam file baru dengan nama intl_en.arb (untuk bahasa Inggris) dan intl_id.arb (untuk bahasa Indonesia).
Catatan: File intl_en.arb dan intl_id.arb kita buat sendiri ya.
Jika sudah kita salin isi dari file intl_messages.arb kedalam file intl_en.arb dan intl_id.arb maka, hasilnya akan menjadi seperti berikut.

Salin isi file intl_messages.arb
Langkah selanjutnya adalah kita perlu menterjemahkan String yang berada di dalam file intl_en.arb kedalam bahasa Inggris dan intl_id.arb kedalam bahasa Indonesia. Dikarenakan bahasa default pada app kita sudah kita buat dalam bahasa Inggris jadi yang perlu kita terjemahkan String -nya hanyalah file intl_id.arb saja. Berikut ialah hasilnya.

Hasil terjemahan yang kita buat
Ubah File arb Menjadi File dart
Jadi, untuk meng-konversi file intl_messages.arb, intl_en.arb, dan intl_id.arb kedalam file dart kita perlu menjalankan perintah berikut.
flutter pub run intl_translation:generate_from_arb \--output-dir=lib/l10n --no-use-deferred-loading \lib/l10n/intl_messages.arb lib/l10n/intl_en.arb lib/l10n/intl_id.arb lib/locale/my_localization.dart

Perintah generator untuk konversi file arb ke file dart
Adapun format dari perintah diatas adalah sebagai berikut.
flutter pub run intl_translation:generate_from_arb \--output-dir=<lokasi_direktori_file_arb> --no-use-deferred-loading <semua_file_arb_yang_kita_buat> <file_localization_yang_sudah_kita_buat>
Jika berhasil seharusnya didalam package lib/l10n akan terbentuk file messages_all.dart, messages_en.dart, messages_id.dart, dan messages_messages.dart.

Hasil konversi file arb ke file dart
Perbaikan Error Di File my_localization.dart
Selanjutnya kita buka lagi file my_localization.dart dan perbaiki dengan cara melakukan import.

Perbaiki error di file my_localization.dart
Hello World App
Sekarang kita perlu meng-implementasikan fungsi localization yang sudah kita buat tadi kedalam app kita. Caranya silakan kita buka file main.dart dan ubah isinya menjadi seperti berikut.
import 'package:flutter/material.dart';
import 'package:flutter_language/locale/my_localization.dart';
import 'package:flutter_language/locale/my_localization_delegate.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() => runApp(App());
class App extends StatelessWidget {
MyLocalizationDelegate _myLocalizationDelegate = MyLocalizationDelegate(Locale('en', 'US'));
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
_myLocalizationDelegate,
],
supportedLocales: [
Locale('en', 'US'),
Locale('id', 'ID'),
],
home: MyApp(),
);
}
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Localization'),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RaisedButton(
child: Text('English'),
onPressed: () {
setState(() {
MyLocalization.load(Locale('en', 'US'));
});
},
),
Text(MyLocalization.of(context).helloWorld),
RaisedButton(
child: Text('Indonesia'),
onPressed: () {
setState(() {
MyLocalization.load(Locale('id', 'ID'));
});
},
),
],
),
),
),
);
}
}
Dan berikut ialah output-nya.
[embed]Output contoh 1
Contoh 2
Pada contoh 1 kita sudah berhasil membuat fitur multiple language yang sederhana. Sekarang kita buat lagi untuk contoh 2 dimana, pada contoh 2-nya kita akan buat 3 screen dalam bentuk Bottom Navigation Bar. Untuk aset bahasanya kita update ya. Jadi, kita perlu tambahkan aset list String nya didalam file my_localization.dart seperti berikut.
String get helloWorld {
return Intl.message(
'Hello World',
name: 'helloWorld',
desc: 'Word Hello World', /* Optional */
);
}
String get homeScreen {
return Intl.message(
'Home Screen',
name: 'homeScreen',
desc: '',
);
}
String get accountScreen {
return Intl.message(
'Account Screen',
name: 'accountScreen',
desc: '',
);
}
String get settingScreen {
return Intl.message(
'Setting Screen',
name: 'settingScreen',
desc: '',
);
}
String get home {
return Intl.message(
'Home',
name: 'home',
desc: '',
);
}
String get account {
return Intl.message(
'Account',
name: 'account',
desc: '',
);
}
String get setting {
return Intl.message(
'Setting',
name: 'setting',
desc: '',
);
}
Selanjutnya kita jalankan perintah
flutter pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/locale/my_localization.dart
Lalu, buka file intl_messages.arb dan salin isinya kedalam file intl_en.arb dan intl_id.arb. Lalu, kita buka file intl_id.arb dan kita terjemahkan secara manual list String -nya kedalam bahasa Indonesia. Sehingga hasilnya seperti berikut.

Update list String
Lalu, jalankan perintah berikut untuk mengubah file arb menjadi dart.
flutter pub run intl_translation:generate_from_arb \--output-dir=lib/l10n --no-use-deferred-loading \lib/l10n/intl_messages.arb lib/l10n/intl_en.arb lib/l10n/intl_id.arb lib/locale/my_localization.dart
Buat Home Screen
Sekarang kita buat file home_screen.dart dan isikan dengan kode berikut.
import 'package:flutter/material.dart';
import 'package:flutter_language/locale/my_localization.dart';
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text(MyLocalization.of(context).homeScreen),
),
);
}
}
Buat Account Screen
Buat file account_screen.dart dan isikan dengan kode berikut.
import 'package:flutter/material.dart';
import 'package:flutter_language/locale/my_localization.dart';
class AccountScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text(MyLocalization.of(context).accountScreen),
),
);
}
}
Buat Setting Screen
Selanjutnya kita juga perlu membuat file setting_screen.dart dan isi dengan kode berikut.
import 'package:flutter/material.dart';
import 'package:flutter_language/locale/my_localization.dart';
class SettingScreen extends StatefulWidget {
@override
_SettingScreenState createState() => _SettingScreenState();
}
class _SettingScreenState extends State<SettingScreen> {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RaisedButton(
child: Text('English'),
onPressed: () {
setState(() {
MyLocalization.load(Locale('en', 'US'));
});
},
),
Text(MyLocalization.of(context).settingScreen),
RaisedButton(
child: Text('Indonesia'),
onPressed: () {
setState(() {
MyLocalization.load(Locale('id', 'ID'));
});
},
),
],
),
),
);
}
}
Ubah File main.dart
Selanjutya, kita buka file main.dart dan ubah kodenya menjadi seperti berikut.
import 'package:flutter/material.dart';
import 'package:flutter_language/locale/my_localization_delegate.dart';
import 'package:flutter_language/ui/account/account_screen.dart';
import 'package:flutter_language/ui/home/home_screen.dart';
import 'package:flutter_language/ui/setting/setting_screen.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() => runApp(App());
class App extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
MyLocalizationDelegate(Locale('en', 'US')),
],
supportedLocales: [
Locale('en', 'US'),
Locale('id', 'ID'),
],
home: MyApp(),
);
}
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int indexSelected = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Localization'),
),
bottomNavigationBar: BottomNavigationBar(
onTap: (indexSelected) {
setState(() {
this.indexSelected = indexSelected;
});
},
items: [
BottomNavigationBarItem(
title: Text('Home'),
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
title: Text('Account'),
icon: Icon(Icons.account_balance),
),
BottomNavigationBarItem(
title: Text('Setting'),
icon: Icon(Icons.settings),
),
],
),
body: _buildWidgetBody(),
);
}
Widget _buildWidgetBody() {
switch (indexSelected) {
case 0:
return HomeScreen();
case 1:
return AccountScreen();
case 2:
return SettingScreen();
default:
return Container();
}
}
}
Dan sekarang coba kita test apakah fitur multiple language-nya berhasil.
[embed]Output contoh 2 tidak berhasil
Ada yang aneh ya 🤔 . Mengapa label pada Bottom Navigation Bar-nya berubah ketika kita berpindah menu. Seharusnya label di Bottom Navigation Bar-nya akan ikut berubah ketika kita ubah bahasanya. Untuk kasus seperti ini kita punya 2 solusinya yaitu sebagai berikut.
- Kita bisa melakukan restart app-nya dengan cara memanggil ulang atau navigator ke file main.dart ketika perubahan bahasa dilakukan. Untuk beberapa sebagian app dipasaran saya lihat masih ada yang menggunakan teknik seperti ini.
- Kita bisa melakukan perubahan bahasanya tanpa perlu melakukan restart app. Tekniknya kita bisa pakai Provider atau BLoC.
Solusi
Untuk solusinya kita pakai Provider saja ya. Silakan buat file baru dengan nama provider_localization.dart dan isikan dengan kode berikut.
import 'package:flutter/material.dart';
class ProviderLocalization extends ChangeNotifier {
Locale _locale = Locale('en', 'US');
Locale get language => _locale;
void setLanguage(Locale locale) {
_locale = locale;
notifyListeners();
}
}
Selanjutnya, kita buka file main.dart dan kita cuma perlu membungkus widget MaterialApp dengan ChangeNotifierProvider dan Consumer . Berikut ialah perubahannya pada file main.dart.
import 'package:flutter/material.dart';
import 'package:flutter_language/locale/my_localization.dart';
import 'package:flutter_language/locale/my_localization_delegate.dart';
import 'package:flutter_language/provider_localization.dart';
import 'package:flutter_language/ui/account/account_screen.dart';
import 'package:flutter_language/ui/home/home_screen.dart';
import 'package:flutter_language/ui/setting/setting_screen.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:provider/provider.dart';
void main() => runApp(App());
class App extends StatelessWidget {
Widget build(BuildContext context) {
return ChangeNotifierProvider(
builder: (context) => ProviderLocalization(),
child: Consumer<ProviderLocalization>(
builder: (context, localization, child) {
return MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
MyLocalizationDelegate(localization.language),
],
supportedLocales: [
Locale('en', 'US'),
Locale('id', 'ID'),
],
home: MyApp(),
);
},
),
);
}
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int indexSelected = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Localization'),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: indexSelected,
onTap: (indexSelected) {
setState(() {
this.indexSelected = indexSelected;
});
},
items: [
BottomNavigationBarItem(
title: Text(MyLocalization.of(context).home),
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
title: Text(MyLocalization.of(context).account),
icon: Icon(Icons.account_circle),
),
BottomNavigationBarItem(
title: Text(MyLocalization.of(context).setting),
icon: Icon(Icons.settings),
),
],
),
body: _buildWidgetBody(),
);
}
Widget _buildWidgetBody() {
switch (indexSelected) {
case 0:
return HomeScreen();
case 1:
return AccountScreen();
case 2:
return SettingScreen();
default:
return Container();
}
}
}
Lalu, kita juga perlu mengubah file setting_screen.dart menjadi seperti berikut.
import 'package:flutter/material.dart';
import 'package:flutter_language/locale/my_localization.dart';
import 'package:flutter_language/provider_localization.dart';
import 'package:provider/provider.dart';
class SettingScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final providerLocalization = Provider.of<ProviderLocalization>(context);
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
RaisedButton(
child: Text('English'),
onPressed: () {
MyLocalization.load(Locale('en', 'US'));
providerLocalization.setLanguage(Locale('en', 'US'));
},
),
Text(MyLocalization.of(context).settingScreen),
RaisedButton(
child: Text('Indonesia'),
onPressed: () {
MyLocalization.load(Locale('id', 'ID'));
providerLocalization.setLanguage(Locale('id', 'ID'));
},
),
],
),
),
);
}
}
Sekarang coba kita test lagi.
[embed]Output contoh 2 berhasil
Dan solusinya berhasil. Sebenarnya solusi yang kita lakukan pada contoh kedua tadi adalah kita cuma me-listen perubahan bahasa yang dilakukan oleh widget SettingScreen dan si consumer-nya itu kita letakkan didalam widget MaterialApp sehingga ketika ada perubahan data bahasa maka, MaterialApp akan langsung mendeteksi perubahan bahasa tersebut.
Kesimpulan
Jadi, dari tulisan ini saya ambil kesimpulan bahwa Flutter sudah memiliki plugin localization yang bisa kita pakai untuk mengubah bahasa sesuai dengan localization yang kita inginkan. Untuk projeknya bisa dilihat di Github ya.
메타데이터
- post_id
- bb22547ca653
- slug
- flutter-localization-bb22547ca653
- url
- https://medium.com/nusanet/flutter-localization-bb22547ca653
- canonical_url
- https://medium.com/nusanet/flutter-localization-bb22547ca653
- author_url
- https://medium.com/@coderjava
- status
- ok
- fetched_at
- 2026-08-06 09:14:48