Are you looking for localize your mobile apps such as supporting German, French, Japanese or Chinese? From marketing perspective, it’s crucial for the Flutter apps to support multiple languages to reach a broader audience. In Flutter, it is really easy to achieve the goal by utilizing the comprehensive framework for internationalization (i18n). It allow you to easily add multi-language support. In this detailed tutorial, we’ll explore how to make your Flutter app localize step by step.
This tutorial will cover the following:
- Set up localization and language files in Flutter framework;
- Switch between languages in your app;
- Use the flutter_localizations package and the intl library for internationalization;
Let’s get started.
Setting Up the Flutter Localizations Package
The very first step is to setup the environment. Flutter framework supports internationalization through the flutter_localizations
package. Many common widgets, for example, the MaterialApps, Appbar, Placeholder will all be supported. To get started, you need to include the localization package in your Flutter app.
Add flutter_localizations
and intl
Packages
First, open your pubspec.yaml
file and add the following dependencies:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
intl: latest_version
Run flutter pub get
in the terminal to install the corresponding packages.
Enable Localization Support
In your main.dart
, configure your app to use the flutter_localizations package. You’ll need to modify the “MaterialApp widget” to support multiple locales and provide localized resources.
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// Add localization delegates and supported locales
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
Locale('en', ''), // English
Locale('es', ''), // Spanish
Locale('fr', ''), // French
],
home: LanguageSwitcher(),
);
}
}
For a quick explanation, the localizationsDelegates specifies the localization support for different Flutter components like Material and Cupertino widgets. Also, in the lists of “supportedLocales”, you can add the languages your app should be supported. In this example, we’re supporting English, Spanish, and French.
Creating Localization Files
Once your environment is ready, we can move forward to the next step. You need to create language files for the supported languages. The purpose of the files are to store the translations for different languages. Basically, we need to take care of the localization file and the language files in JSON file format.
Organize the Localization Files
First you need to create a new directory called l10n
(short for “localization”) in the root of your project.
Inside the l10n
folder, create separate JSON files for each language, for example, en.json, es.json and fr.json
/l10n
- en.json (for English)
- es.json (for Spanish)
- fr.json (for French)
Add Translations Strings to the JSON Files
Now you are ready to add some key-value pairs representing the translations in each file. For example, let me add a greeting messages like below. Remember you need to add in each language file. Sure you can use Google Translate or DeepL to assist you for the task.
en.json (English):
{
"title": "Hello",
"message": "Welcome to Flutter Internationalization"
}
es.json (Spanish):
{
"title": "Hola",
"message": "Bienvenido a la internacionalización de Flutter"
}
fr.json (French):
{
"title": "Bonjour",
"message": "Bienvenue dans l'internationalisation de Flutter"
}
Load and Use the Localization Files
We need to load the JSON files dynamically based on the user’s selected language. To do this, we’ll create a class to load and fetch the appropriate translations for the app.
1. Create a AppLocalizations
Class
In the lib
folder, create a new file called app_localizations.dart
and define a class to handle loading the localization files:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class AppLocalizations {
final Locale locale;
AppLocalizations(this.locale);
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
late Map<String, String> _localizedStrings;
Future<bool> load() async {
String jsonString =
await rootBundle.loadString('l10n/${locale.languageCode}.json');
Map<String, dynamic> jsonMap = json.decode(jsonString);
_localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});
return true;
}
String translate(String key) {
return _localizedStrings[key] ?? key;
}
}
In this class:
- load(): Loads the appropriate JSON file based on the user’s locale.
- translate(): Retrieves the translation for a given key.
2. Create a LocalizationsDelegate
Next, we’ll create a LocalizationsDelegate to tell Flutter how to load the language resources dynamically. Add the following code in the same app_localizations.dart
file:
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) {
return ['en', 'es', 'fr'].contains(locale.languageCode);
}
@override
Future<AppLocalizations> load(Locale locale) async {
AppLocalizations localizations = AppLocalizations(locale);
await localizations.load();
return localizations;
}
@override
bool shouldReload(LocalizationsDelegate<AppLocalizations> old) => false;
}
This delegate tells Flutter which locales are supported and how to load the correct localization data.
Step 4: Updating MaterialApp
for Localization
Now, update the MaterialApp in your main.dart
to use the custom AppLocalizations
class and delegate.
import 'app_localizations.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
Locale('en', ''), // English
Locale('es', ''), // Spanish
Locale('fr', ''), // French
],
home: LanguageSwitcher(),
);
}
}
Step 5: Switching Between Languages
Finally, let’s create a simple interface to switch between different languages in your app.
class LanguageSwitcher extends StatefulWidget {
@override
_LanguageSwitcherState createState() => _LanguageSwitcherState();
}
class _LanguageSwitcherState extends State<LanguageSwitcher> {
Locale _currentLocale = Locale('en', '');
void _changeLanguage(Locale locale) {
setState(() {
_currentLocale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _currentLocale,
localizationsDelegates: [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
Locale('en', ''),
Locale('es', ''),
Locale('fr', ''),
],
home: Scaffold(
appBar: AppBar(title: Text(AppLocalizations.of(context)!.translate('title'))),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(AppLocalizations.of(context)!.translate('message')),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => _changeLanguage(Locale('es', '')),
child: Text('Switch to Spanish'),
),
ElevatedButton(
onPressed: () => _changeLanguage(Locale('fr', '')),
child: Text('Switch to French'),
),
ElevatedButton(
onPressed: () => _changeLanguage(Locale('en', '')),
child: Text('Switch to English'),
),
],
),
),
),
);
}
}
In this example:
- The user can switch between English, Spanish, and French by tapping a button.
- The app uses the selected locale to load the appropriate translations from the JSON files.
Conclusion: Supporting Multiple Languages in Your Flutter App
By following these steps, you’ve learned how to implement internationalization (i18n) in your Flutter app using the flutter_localizations
package and the intl library. Now, your app can dynamically switch between different languages and provide a localized experience to users around the world.
In the next tutorial, we’ll explore advanced topics such as formatting dates, numbers, and currencies for different locales. Keep building, and happy coding!