Skip to content

Repository files navigation

Flutter Localization

In this project, I tried to explain in detail how to do Localizations in Flutter.

Folder Structure

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

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

l10n.yaml

#* 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.json

Extension on BuildContext for easily usage

import'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);
}

Simple Text

Configuration

"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"

Usage

classSimpleTextWidgetextendsStatelessWidget {
constSimpleTextWidget({super.key});
@overrideWidgetbuild(BuildContext context) {
final l10n = context.l10n;
returnCustomText(
title: l10n.simpleTextTitle,
content:Text(l10n.simpleTextContent),
);
}
}

Calendar Date Picker

Configuration

"calendarDatePickerTitle": "Calendar Date Picker",
"calendarDatePickerButton": "Pick Date",
"calendarDatePickerNoSelected": "No date selected",

Usage

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),
);
},
);
},
),
],
),
);
}
}

Basic Placeholder Text

Configuration

 "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"
}
}
}

Usage

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',
),
),
);
}
}

Plural Text

Configuration

 "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"
}
}
}

Usage

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'
],
),
);
}
}

Select Text

Configuration

 "pronounTitle": "Select Gender Text",
"pronounContent": "{gender, select, male{he} female{she} other{they}}",
"@pronounContent": {
"description": "A gendered message",
"placeholders": {
"gender": {
"type": "String"
}
}
}

Usage

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'
],
),
);
}
}

Number And Currencies Text

Configuration

 "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"
}
}
}

Usage

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')),
],
),
);
}
}

Contact Me

LinkedInMedium

enesakbal00@gmail.com

created by ea.

About

Flutter Localization Example

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages