- We need to create one map which contains all the localized values of particular languages.
class AppLocalization {
late final Locale _locale;
AppLocalization(this._locale);
static AppLocalization of(BuildContext context) {
return Localizations.of<AppLocalization>(context, AppLocalization)!;
}
static const _localizedValues = <String, Map<String, String>>{
'en': {
'title': 'Hello World',
},
'es': {
'title': 'Hola Mundo',
},
};
}
- But creating and adding all the values inside this file will create a mess.
- So, we need to create
.json files for all the languages. (ex: en.json, es.json etc).
- These JSON files will contain all the values in their own languages.
- I am creating 4 different json files for
English, Hindi, Spanish, and Chinese languages inside the <root>/assets/lang folder
en.json{
"home_appBar_title": "Flutter Internationalization",
"simple_text":"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
}
es.json
{
"home_appBar_title": "Internacionalización de Flutter",
"simple_text":"Lorem Ipsum es simplemente texto de relleno de la industria de la impresión y la composición tipográfica. Lorem Ipsum ha sido el texto de relleno estándar de la industria desde el año 1500, cuando un impresor desconocido tomó una galera de tipos y la mezcló para hacer un libro de muestras tipográficas. Ha sobrevivido no solo a cinco siglos, sino también al salto a la composición tipográfica electrónica, permaneciendo esencialmente sin cambios. Se popularizó en la década de 1960 con el lanzamiento de hojas de Letraset que contenían pasajes de Lorem Ipsum y, más recientemente, con software de autoedición como Aldus PageMaker que incluía versiones de Lorem Ipsum."
}
hi.json
{
"home_appBar_title": "फ्लटर अंतर्राष्ट्रीयकरण",
"simple_text":"Lorem Ipsum छपाई और अक्षर योजन उद्योग का एक साधारण डमी पाठ है. Lorem Ipsum सन १५०० के बाद से अभी तक इस उद्योग का मानक डमी पाठ मन गया, जब एक अज्ञात मुद्रक ने नमूना लेकर एक नमूना किताब बनाई. यह न केवल पाँच सदियों से जीवित रहा बल्कि इसने इलेक्ट्रॉनिक मीडिया में छलांग लगाने के बाद भी मूलतः अपरिवर्तित रहा. यह 1960 के दशक में Letraset Lorem Ipsum अंश युक्त पत्र के रिलीज के साथ लोकप्रिय हुआ, और हाल ही में Aldus PageMaker Lorem Ipsum के संस्करणों सहित तरह डेस्कटॉप प्रकाशन सॉफ्टवेयर के साथ अधिक प्रचलित हुआ."
}
zh.json
{
"home_appBar_title": "Flutter 国际化",
"simple_text":"Lorem Ipsum 只是印刷和排版行业的虚拟文本。 自 1500 年代以来,Lorem Ipsum 一直是行业标准的虚拟文本,当时一位不知名的印刷商使用了一个类型的厨房并争先恐后地制作了一本类型样本书。 它不仅存活了五个世纪,而且还经历了电子排版的飞跃,基本保持不变。 它在 1960 年代随着包含 Lorem Ipsum 段落的 Letraset 表的发布而流行,最近随着桌面出版软件 Aldus PageMaker 的发布,包括 Lorem Ipsum 的版本。"
}
- After creating all the
json files go to pubspec.yaml load all these JSON file inside assets
assets:
- assets/lang/en.json
- assets/lang/es.json
- assets/lang/hi.json
- assets/lang/zh.json
- Now that we've added all languages in
pubspec.yaml. It's time to create a Map that will give us language-specific values requested by user.
class AppLocalization {
late final Locale _locale;
AppLocalization(this._locale);
static AppLocalization of(BuildContext context) {
return Localizations.of<AppLocalization>(context, AppLocalization)!;
}
late Map<String, String> _localizedValues;
Future loadLanguage() async {
String jsonStringValues = await rootBundle.loadString(
"assets/lang/${_locale.languageCode}.json");
Map<String, dynamic> mappedValues = json.decode(jsonStringValues);
_localizedValues =
mappedValues.map((key, value) => MapEntry(key, value.toString()));
}
}
Text Widget
class SimpleText extends StatelessWidget {
const SimpleText({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
AppLocalization.of(context)
.getTranslatedValue("simple_text")
.toString(),
textAlign: TextAlign.center,
),
);
}
}
- Date and Time picker Widgets
class FlutterPicker extends StatelessWidget {
const FlutterPicker({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
showDatePicker(
context: context,
initialDate: DateTime(2021, 1, 1),
firstDate: DateTime(2021, 1, 1),
lastDate: DateTime(2021, 1, 31),
);
},
child: Text(
"Pick Date",
),
),
SizedBox(
width: 10,
),
ElevatedButton(
onPressed: () {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
},
child: Text(
"Pick Time",
),
),
],
);
}
}
- Language model class
class Language {
final int id;
final String name;
final String flag;
final String languageCode;
Language(this.id, this.name, this.flag, this.languageCode);
static List<Language> languageList() {
return <Language>[
Language(1, "English", "🇺🇸", "en"),
Language(1, "हिंदी", "🇮🇳", "hi"),
Language(1, "española", "🇲🇽", "es"),
Language(1, "中国人", "🇨🇳", "zh"),
];
}
}
- HomePage
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
AppLocalization.of(context)
.getTranslatedValue("home_appBar_title")
.toString(),
),
),
body: SizedBox.expand(
child: Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SimpleText(),
SizedBox(
height: 50,
),
FlutterPicker()
],
),
SizedBox(height: 20),
Wrap(
children: Language.languageList()
.map(
(e) => Padding(
padding: EdgeInsets.only(right: 10),
child: ElevatedButton(
onPressed: () {
},
child: Text("${e.name} ${e.flag}"),
),
),
)
.toList()),
],
),
),
);
}
}
- UI will look something like this -

- Now to change app locale when the user presses a button, Let's create a method called
_changeLanguage().
void _changeLanguage(Language language, context) {
Locale _selectedLocale;
switch (language.languageCode) {
case ENGLISH:
_selectedLocale = Locale(language.languageCode, 'US');
break;
case HINDI:
_selectedLocale = Locale(language.languageCode, 'IN');
break;
case SPANISH:
_selectedLocale = Locale(language.languageCode, 'AR');
break;
case CHINESE:
_selectedLocale = Locale(language.languageCode, 'CN');
break;
default:
_selectedLocale = Locale(language.languageCode, 'US');
}
}
- Call this on Language Button press
Wrap(
children: Language.languageList()
.map(
(e) => Padding(
padding: EdgeInsets.only(right: 10),
child: ElevatedButton(
onPressed: () {
_changeLanguage(e, context);
},
child: Text("${e.name} ${e.flag}"),
),
),
) .toList(),
),
- But still, this will not do anything. If we need to change locale locally through the app we need some kind of
notifer that tells Flutter to change its locale instantly whenever the user changes its language.
- For that, we can use
ChangeNotifierProvier provided by Provider package.
- Let's create a file called
locale_notifier.dart
class LocaleNotifier extends ChangeNotifier {
Locale _locale = Locale("en");
Locale get locale => _locale;
void setLocale(Locale locale) async {
_locale = locale;
notifyListeners();
}
}
- Now add the below code inside
_changeLocale() function
void _changeLanguage(Language language, context) {
final appLocaleProvider =
Provider.of<LocaleNotifier>(context, listen: false);
appLocaleProvider.setLocale(_selectedLocale);
}
- Wrap MaterialApp inside
ChangeNotifierProvider. And then provide the LocaleNotifier to its create property.
- This
ChangeNotifierProvider will notify the app when locale changes and will update accordingly.
ChangeNotifierProvider(
create: (context) => LocaleNotifier(),
builder: (context, child) {
final appLocaleProvider = Provider.of<LocaleNotifier>(context);
return MaterialApp(
locale: appLocaleProvider.locale,
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
AppLocalization.delegate
],
supportedLocales: [
Locale('en', 'US'),
Locale('es', 'AR'),
Locale('hi', 'IN'),
Locale('zh', 'CN'),
],
localeResolutionCallback: (deviceLocale, supportedLocales) {
for (var locale in supportedLocales) {
if (locale.languageCode == deviceLocale!.languageCode &&
locale.countryCode == deviceLocale.countryCode) {
return deviceLocale;
}
}
return supportedLocales.first;
},
home: HomePage(),
);
});

- AND THAT'S IT YOU MADE IT
