Flutter Localization Integration

In this article, we are going to learn how to support flutter application in multiple languages through flutter localization. You can also checkout sample app at HERE.

People speak different languages in different countries. If you want to make your flutter app for global audience then you need to support your flutter app in multiple languages.

Flutter provides flutter_localizations package to support localization in flutter applications. You have to create json file for every language you want to support it. For this you need to give file name according to language code.

 

Add flutter package under dependencies section in pubspec file

flutter_localizations:
  sdk: flutter
 
 

Create Json Files

You have to add all texts of your application in every json file. You have to keep same key for single text in all json files. You also have to translate your text in language you want to support it.

For english language, You have to create en.json file.

{
     “player_name”: “Player Name”,
     “club_name”: “Club Name”,
     “country”: “Country”
}
 

If you want to support your flutter app in spanish language then you need to create es.json file.

{
     “player_name”: “Nombre del jugador”,
     “club_name”: “Nombre del club”,
     “country”: “PaĆ­s”
}
 

If you want to support your flutter app in french language then you need to create fr.json file.

{
     “player_name”: “Nom de joueur”,
     “club_name”: “Nom du club”,
     “country”: “Pays”
}
 
 

Set json files paths under flutter section in pubspec file

We created json file for every language we want to support. Now we need to give their paths in our pubspec.yaml file. If we create language folder at root level and placed all our json files in this language folder then we need to add following lines in out pubspec.yaml file.

assets:
  – language/en.json
  – language/es.json
  – language/fr.json
 
 

Create Classes For Flutter Localization

We are creating custom class ApplicationLocalizations.dart. This class is used to get locale from users devices according to their selected language. Then it will get values from our created json file which is same as this selected language and generate data in the form of key values pair.

There are two methods used in this class. load() and translate(). load() is used to convert json into map data. translate() is used to get value according to our key which will we use to display text.

class ApplicationLocalizations {
final Locale appLocale;

ApplicationLocalizations(this.appLocale);

static ApplicationLocalizations of(BuildContext context) {
     return Localizations.of(context, ApplicationLocalizations);
}

static const LocalizationsDelegate delegate = ApplicationLocalizationsDelegate();

Map _localizedStrings;

Future load() async {
     // Load JSON file from the “language” folder
     String jsonString = await rootBundle.loadString(‘assets/ language/ ${appLocale.languageCode}.json’);
     Map jsonLanguageMap = json.decode(jsonString);
     _localizedStrings = jsonLanguageMap.map((key, value) {
     return MapEntry(key, value.toString());
     });
     return true;
}

// called from every widget which needs a localized text
String translate(String jsonkey) {
     return _localizedStrings[jsonkey];
}
}

 

In ApplicationLocalizationsDelegate class, we are adding all our supported locales in isSupported() method.

class ApplicationLocalizationsDelegate extends LocalizationsDelegate {
// This delegate instance will never change (it doesn’t even have fields!)
// It can provide a constant constructor.
const ApplicationLocalizationsDelegate();

@override
bool isSupported(Locale locale) {
     // Include all of your supported language codes here
     return [‘en’, ‘es’, ‘fr’].contains(locale.languageCode);
}

@override
Future load(Locale locale) async {
     ApplicationLocalizations localizations = new ApplicationLocalizations(locale);
     await localizations.load();
     return localizations;
}

@override
bool shouldReload(ApplicationLocalizationsDelegate old) => false;
}

 
 

Integrate flutter localization in main.dart file

Material App widget provides supportedLocales parameter which is used to set supported languages. Locale widget contains language code and country code. We need to and create locale widget for all our supported languages and add in the array which is assigned to supportedLocales parameter.

localizationsDelegates parameter is used in materialApp to get localized values from localize delegates. GlobalMaterialLocalizations.delegate is used to get localized values for material components. GlobalWidgetsLocalizations.delegate is used to set text direction for the widgets.

localeResolutionCallback parameter is used to check device language code and country code match with any supported locale which we are passing to supportedLocales parameter. If it matches then it will return data in supported language otherwise it will return data in first language of supportedLocales array.

supportedLocales: [
Locale( ‘en’ , ‘US’ ),
Locale( ‘es’ , ‘ES’ ),
Locale( ‘fr’ , ‘FR’ ),
],

localizationsDelegates: [
ApplicationLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],

localeResolutionCallback: (locale, supportedLocales) {
for (var supportedLocaleLanguage in supportedLocales) {
if (supportedLocaleLanguage.languageCode == locale.languageCode &&
supportedLocaleLanguage.countryCode == locale.countryCode) {
     return supportedLocaleLanguage;
}
}
return supportedLocales.first;
},

 
 

Display Localized Text

Text( ApplicationLocalizations.of( context ).translate(“player_name”) );
 
 

Final Code

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutterlocalizationsample/application_localizations_delegate.dart';

class ApplicationLocalizations {
  final Locale appLocale;

  ApplicationLocalizations(this.appLocale);

  static ApplicationLocalizations of(BuildContext context) {
    return Localizations.of<ApplicationLocalizations>(context, ApplicationLocalizations);
  }

  static const LocalizationsDelegate<ApplicationLocalizations> delegate =
  ApplicationLocalizationsDelegate();

  Map<String, String> _localizedStrings;

  Future<bool> load() async {
    // Load JSON file from the "language" folder
    String jsonString =
    await rootBundle.loadString('assets/language/${appLocale.languageCode}.json');
    Map<String, dynamic> jsonLanguageMap = json.decode(jsonString);
    _localizedStrings = jsonLanguageMap.map((key, value) {
      return MapEntry(key, value.toString());
    });
    return true;
  }

  // called from every widget which needs a localized text
  String translate(String jsonkey) {
    return _localizedStrings[jsonkey];
  }
}
 
import 'package:flutter/material.dart';
import 'package:flutterlocalizationsample/application_localizations.dart';

class ApplicationLocalizationsDelegate extends LocalizationsDelegate<ApplicationLocalizations> {
  // This delegate instance will never change (it doesn't even have fields!)
  // It can provide a constant constructor.
  const ApplicationLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) {
    // Include all of your supported language codes here
    return ['en', 'es', 'fr'].contains(locale.languageCode);
  }

  @override
  Future<ApplicationLocalizations> load(Locale locale) async {
    // AppLocalizations class is where the JSON loading actually runs
    ApplicationLocalizations localizations = new ApplicationLocalizations(locale);
    await localizations.load();
    return localizations;
  }

  @override
  bool shouldReload(ApplicationLocalizationsDelegate old) => false;
}
 
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutterlocalizationsample/application_localizations.dart';
import 'package:flutterlocalizationsample/application_localizations_delegate.dart';

class Home extends StatelessWidget{

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return SafeArea(
      child: Scaffold(
        body: Container(
          padding: EdgeInsets.all(25),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("player_name") + " : Cristiano Ronaldo", style: TextStyle(fontSize: 22)),
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("club_name") + " : Juventus", style: TextStyle(fontSize: 22)),
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("country") + " : Portugal", style: TextStyle(fontSize: 22)),
              SizedBox(height: 15),
              Divider(thickness: 3),
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("player_name") + " : Lionel Messi", style: TextStyle(fontSize: 22)),
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("club_name") + " : Barcelona", style: TextStyle(fontSize: 22)),
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("country") + " : Argentina", style: TextStyle(fontSize: 22)),
              SizedBox(height: 15),
              Divider(thickness: 3),
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("player_name") + " : Neymar Jr.", style: TextStyle(fontSize: 22)),
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("club_name") + " : Paris Saint-Germain", style: TextStyle(fontSize: 22)),
              SizedBox(height: 15),
              Text(ApplicationLocalizations.of(context).translate("country") + " : Brazil", style: TextStyle(fontSize: 22)),
            ],
          ),
        )
      ),
    );
  }

}
 
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

import 'application_localizations.dart';
import 'home.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      supportedLocales: [
        Locale( 'en' , 'US' ),
        Locale( 'es' , 'ES' ),
        Locale( 'fr' , 'FR' ),
      ],

      localizationsDelegates: [
        ApplicationLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],

      localeResolutionCallback: (locale, supportedLocales) {
        for (var supportedLocaleLanguage in supportedLocales) {
          if (supportedLocaleLanguage.languageCode == locale.languageCode &amp;&amp;
              supportedLocaleLanguage.countryCode == locale.countryCode) {
            return supportedLocaleLanguage;
          }
        }
        return supportedLocales.first;
      },
      home: Home(),
    );
  }
}
 
 
 
 
flutter localization
 
 
 

Leave a Reply