In this project, I tried to explain in detail how to do Localizations in Flutter.
lib
├── l10n
│ ├── arb
│ │ ├── app_de.arb
│ │ ├── app_en.arb
│ │ └── app_tr.arb
│ │ │ ├── l10n.dart
│ └── locale_provider.dart
│ ├── views
│ └── home_view.dart
│ ├── widgets
│ ├── _custom_text_widget.dart
│ ├── basic_placeholder_text_widget.dart
│ ├── calendar_date_picker_widget.dart
│ ├── numbers_and_currencies_widget.dart
│ ├── plural_text_widget.dart
│ ├── select_text_widget.dart
│ └── simple_text_widget.dart
│ └── main.dart
dependencies:
flutter:
sdk: flutterflutter_localizations: # for localizationsdk: flutterintl: ^0.18.0 # for localizationprovider: ^6.1.1 # for change localedev_dependencies:
flutter_test:
sdk: flutterflutter_lints: ^3.0.1flutter:
uses-material-design: truegenerate: true # for generating l10n files#* This YAML file contains configuration settings for localization in the application.#* - `arb-dir`: Specifies the directory where the ARB (Application Resource Bundle) files are located.#* - `template-arb-file`: Specifies the name of the template ARB file.#* - `output-localization-file`: Specifies the name of the output file that will contain the generated localizations.#* - `nullable-getter`: Specifies whether the generated getter methods should be nullable or not.#* - `untranslated-messages-file`: Specifies the name of the file that will contain the untranslated messages.arb-dir: lib/l10n/arbtemplate-arb-file: app_de.arboutput-localization-file: app_localizations.dartnullable-getter: falseuntranslated-messages-file: untranslated_messages.jsonimport'package:flutter/material.dart';
import'package:flutter_gen/gen_l10n/app_localizations.dart';
export'package:flutter_gen/gen_l10n/app_localizations.dart';
extensionAppLocalizationsXonBuildContext {
AppLocalizationsget l10n =>AppLocalizations.of(this);
}"simpleTextTitle": "Simple Text",
"simpleTextContent": "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"
classSimpleTextWidgetextendsStatelessWidget {
constSimpleTextWidget({super.key});
@overrideWidgetbuild(BuildContext context) {
final l10n = context.l10n;
returnCustomText(
title: l10n.simpleTextTitle,
content:Text(l10n.simpleTextContent),
);
}
}"calendarDatePickerTitle": "Calendar Date Picker",
"calendarDatePickerButton": "Pick Date",
"calendarDatePickerNoSelected": "No date selected",
classCalendarDatePickerWidgetextendsStatefulWidget {
constCalendarDatePickerWidget({super.key});
@overrideState<CalendarDatePickerWidget> createState() =>_CalendarDatePickerWidgetState();
}
class_CalendarDatePickerWidgetStateextendsState<CalendarDatePickerWidget> {
//* A value notifier to listen to the selected datelatefinalValueNotifier<DateTime?> selectedDate;
@overridevoidinitState() {
selectedDate =ValueNotifier<DateTime?>(null);
super.initState();
}
@overridevoiddispose() {
selectedDate.dispose();
super.dispose();
}
@overrideWidgetbuild(BuildContext context) {
final l10n = context.l10n;
returnCustomText(
title: l10n.calendarDatePickerTitle,
content:Row(
children: [
//* CalendarDatePickerTextButton(
onPressed: () async {
selectedDate.value =awaitshowDatePicker(
context: context,
currentDate:DateTime.now(),
firstDate:DateTime(1900),
lastDate:DateTime(2100),
initialDatePickerMode:DatePickerMode.day,
) ??DateTime.now();
},
child:Text(l10n.calendarDatePickerButton),
),
constSpacer(),
//* Selected DateValueListenableBuilder<DateTime?>(
valueListenable: selectedDate,
builder: (_, selectedDate, __) {
returnBuilder(
builder: (context) {
if (selectedDate !=null) {
final locale =Localizations.localeOf(context);
returnText(
DateFormat.yMMMEd(locale.languageCode).format(selectedDate),
style:constTextStyle(fontSize:14),
);
}
returnText(
l10n.calendarDatePickerNoSelected,
style:constTextStyle(fontSize:14),
);
},
);
},
),
],
),
);
}
}
"basicPlaceholderTitle": "Basic Placeholder Text",
"basicPlaceholderContent": "Hello, my name is {name}. I am {age} years old with {experience} years of experience with Flutter. Born on {birthDate} in {birthPlace}",
"@basicPlaceholderContent": {
"description": "A message with name, age, experience, birthDate and birthPlace parameters",
"placeholders": {
"name": {
"type": "String",
"example": "Enes"
},
"age": {
"type": "int",
"example": "23"
},
"experience": {
"type": "double",
"example": "2.5"
},
"birthDate": {
"type": "DateTime",
"format": "yMMMEd"
},
"birthPlace": {
"type": "String",
"example": "Istanbul, Türkiye"
}
}
}
classBasicPlaceholderTextWidgetextendsStatelessWidget {
constBasicPlaceholderTextWidget({super.key});
@overrideWidgetbuild(BuildContext context) {
final l10n = context.l10n;
//* Text with parametersreturnCustomText(
title: l10n.basicPlaceholderTitle,
content:Text(
l10n.basicPlaceholderContent(
'Enes',
22,
2.5,
DateTime(2001, 07, 29),
'Istanbul, Türkiye',
),
),
);
}
}
"nKangaroosTitle": "Plural Text",
"nKangaroosContent": "{count, plural, =0{no kangaroos} =1{1 kangaroo} other{{count} kangaroos}}",
"@nKangaroosContent": {
"description": "A plural message for kangaroos",
"placeholders": {
"count": {
"type": "num",
"format": "compact"
}
}
}
classTextWithPluralWidgetextendsStatelessWidget {
constTextWithPluralWidget({super.key});
@overrideWidgetbuild(BuildContext context) {
final l10n = context.l10n;
//* Text with pluralreturnCustomText(
title: l10n.nKangaroosTitle,
content:Row(
mainAxisAlignment:MainAxisAlignment.spaceEvenly,
children: [
Text(l10n.nKangaroosContent(0)), //* Returns '0 kangaroos'Text(l10n.nKangaroosContent(1)), //* Returns '1 kangaroo'Text(l10n.nKangaroosContent(12)), //* Returns '12 kangaroos'
],
),
);
}
} "pronounTitle": "Select Gender Text",
"pronounContent": "{gender, select, male{he} female{she} other{they}}",
"@pronounContent": {
"description": "A gendered message",
"placeholders": {
"gender": {
"type": "String"
}
}
}
classTextWithSelectWidgetextendsStatelessWidget {
constTextWithSelectWidget({super.key});
@overrideWidgetbuild(BuildContext context) {
final l10n = context.l10n;
//* Text with SelectreturnCustomText(
title: l10n.pronounTitle,
content:Row(
mainAxisAlignment:MainAxisAlignment.spaceEvenly,
children: [
Text(l10n.pronounContent('male')), //* Returns 'he'Text(l10n.pronounContent('female')), //* Returns 'she'Text(l10n.pronounContent('other')), //* Returns 'they'Text(l10n.pronounContent('wrong key')), //* Returns 'they'
],
),
);
}
} "numberAndCurrenciesTitle": "Number and Currencies",
"simpleCurrencyContent": "The price of the product is {currency1}",
"@simpleCurrencyContent": {
"description": "A message with a formatted int|double parameter",
"placeholders": {
"currency1": {
"type": "double",
"format": "simpleCurrency",
"optionalParameters": {
"decimalDigits": 2
}
}
}
},
"compactLongContent": "The population of {country} is {compactLong}",
"@compactLongContent": {
"description": "A message with a formatted double parameter",
"placeholders": {
"compactLong": {
"type": "double",
"format": "compactLong"
},
"country": {
"type": "String",
"example": "Turkey"
}
}
},
"percentContent": "{country} accounts for approximately {percent} of the world's population",
"@percentContent": {
"description": "A message with a formatted double parameter",
"placeholders": {
"percent": {
"type": "double",
"format": "decimalPercentPattern"
},
"country": {
"type": "String",
"example": "Turkey"
}
}
}
classNumberAndCurrenciesWidgetextendsStatelessWidget {
constNumberAndCurrenciesWidget({super.key});
@overrideWidgetbuild(BuildContext context) {
final l10n = context.l10n;
returnCustomText(
title: l10n.numberAndCurrenciesTitle,
content:Column(
crossAxisAlignment:CrossAxisAlignment.start,
children: [
Text(l10n.simpleCurrencyContent(25)),
Text(l10n.compactLongContent(274000000, 'Indonesia')),
Text(l10n.percentContent(0.03, 'Indonesia')),
],
),
);
}
}
created by ea.





