As the world becomes more connected, mobile app developers need to ensure that their apps can cater to a global audience. One crucial aspect of this is providing support for multiple languages. In this article, we'll guide you through the process of enabling multi-language support in a Flutter app, allowing you to increase the accessibility of your app to a wider range of users. Let's dive in and learn how to make your app more inclusive!
Configuration
1. Folder and File Setup
Begin by creating the necessary folder and file structure for your Flutter project. The structure should be similar to the following:
2. Pubspec.yaml Configuration
Make sure to add flutter_localizations and intl dependencies to your pubspec.yaml file for Flutter's built-in localization support, and intl helps with internationalization.
Add the language assets file to pubspec.yaml as well:
Create Language Files
Add language-specific JSON files to the assets/locales folder. A few examples include:
en.json
es.json
There will be key-value pairs in these JSON files, where the key is a unique identifier and the value is the translated string.
App Localization Logic
The app_localization.dart file handles app localizations, loading the correct language file based on the user's locale and providing a method for string translation.
//Location: i18n/app_locatization.dart
// Importing necessary libraries
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// Class for handling app localizations
class AppLocalizations {
// The locale for which the app is localized
final Locale locale;
// Map to hold the localized strings
Map<String, String> _localizedStrings = {};
// Constructor
AppLocalizations(this.locale);
// Method to get the current instance of AppLocalizations
static AppLocalizations of(BuildContext context) {
// Try to get the localization for the current context, if not available, default to English
return Localizations.of<AppLocalizations>(context, AppLocalizations) ?? AppLocalizations(Locale('en'));
}
// Method to load the localized strings
Future<bool> load() async {
// Load the localization file from the assets
String jsonString = await rootBundle.loadString('assets/locales/${locale.languageCode}.json');
// Decode the JSON
Map<String, dynamic> jsonMap = json.decode(jsonString);
// Convert the dynamic values to String and store them in the _localizedStrings map
_localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});
// Return true when loading is done
return true;
}
// Method to get a localized string
String translate(String key) {
// Return the localized string if it exists, otherwise return a default message
return _localizedStrings[key] ?? 'Key not found';
}
}
The class initializes with the given locale, loads the associated language file, and delivers translated strings via a method (translate).
App Localization Delegate
The app_localization_delegate.dart file defines the localization delegate that Flutter uses to manage and load localized strings.
//Location: i18n/app_localization_delegate.dart
// Importing necessary libraries
import 'package:flutter/material.dart';
import 'package:flutter_localization_demo/i18n/app_localization.dart';
// Class for handling localization delegate
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
// Constructor
const AppLocalizationsDelegate();
// Method to check if a locale is supported
@override
bool isSupported(Locale locale) {
// Currently only English and Spanish are supported
return ['en', 'es'].contains(locale.languageCode);
}
// Method to load the localized strings for a locale
@override
Future<AppLocalizations> load(Locale locale) {
// Create an instance of AppLocalizations for the given locale
AppLocalizations localizations = AppLocalizations(locale);
// Load the localized strings and return the AppLocalizations instance
return localizations.load().then((bool _) {
return localizations;
});
}
// Method to decide if the delegate should be reloaded
@override
bool shouldReload(AppLocalizationsDelegate old) => false;
}
It checks if a given locale is supported, loads the localized strings, and ensures that the delegate does not need to be reloaded.
Integration in main.dart
In the main.dart file, initialize the delegates and supported languages to set up localization for the entire app.
// Importing necessary libraries
import 'package:flutter/material.dart';
import 'package:flutter_localization_demo/i18n/AppLocalizationsDelegate.dart';
import 'package:flutter_localization_demo/i18n/app_localization.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
// Entry point of the application
void main() {
runApp(const MyApp());
}
// Root widget of the application
class MyApp extends StatelessWidget {
const MyApp({super.key});
// Build method to describe the part of the user interface represented by this widget.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
// Localization delegates
localizationsDelegates: [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
// Supported locales for this app
supportedLocales: [
const Locale('en', ''),
const Locale('es', ''),
],
// Home page of the app
home: const MyHomePage(),
);
}
}
// Home page widget
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
// Create the mutable state for this widget
@override
State<MyHomePage> createState() => _MyHomePageState();
}
// State for the MyHomePage widget
class _MyHomePageState extends State<MyHomePage> {
// Build method to describe the part of the user interface represented by this widget.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Use localized string for the title
title: Text(AppLocalizations.of(context).translate('flutter_localization_demo'), style: Theme.of(context).textTheme.titleLarge!.apply(color: Colors.white)),
backgroundColor: Theme.of(context).colorScheme.primary,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
// Use localized string for the text
AppLocalizations.of(context).translate('hello'),
style: Theme.of(context).textTheme.titleLarge,
),
],
),
),
);
}
}
The localizationsDelegates list includes the custom AppLocalizationsDelegate, along with Flutter's default delegates for material, widgets, and Cupertino (iOS-style) localization. The supportedLocales list specifies the languages supported by the app.
Accessing Translated Text in Code
You can use the following code snippet to access language text keys in Flutter:
AppLocalizations.of(context).translate('key')
Replace the argument inside 'translate' with the desired key to fetch the corresponding translated text.
Testing Multi-Language
To test the language-switching functionality, follow these steps:
- Please go to the settings of your mobile device and find the option to change your language and region settings.
- To change the language of the system from English to Spanish.
- When you return to the app, you will notice that it now supports the Spanish language.
To ensure that your multi-language support implementation is effective, follow these steps.
You can download the source code from the GitHub link provided below.
Source code: https://github.com/socialmad/flutter_localization_demo
Conclusion
Enabling multi-language support in your Flutter app is a crucial step towards providing a better user experience for a diverse audience. The steps outlined above provide an easy way to integrate localization into your app, making it accessible to users worldwide. You can further customize and expand this foundation as per your localization needs. Thank you for reading this article! If you found it helpful, please connect with me on LinkedIn.