Flutter Localization

Flutter Localization

Localization is used to translate the application to several languages. Almost all of the apps needs localization for better user enagement.

Here we are going to implement Localization in a sample-simple flutter application.

Initial Setup for Localization

Add following dependancy in pubspec.yaml

provider: ^4.0.5

Provider is used to update and manage the state of the application, I am using provider and view model class to switch languages.

Add following files

app_localization.dart

AppLocalization class contains following functions

  • load function will load the string resources from the desired Locale as you can see in the parameter.
  • of function will be a helper like any other InheritedWidget to facilitate access to any string from any part of the app code.
  • translate this method is used to translate words from the json files

    add the file in lib/localization folder
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:localization_app/localization/supportedLanguages.dart';

class AppLocalization {
  // Helper method to keep the code in the widgets concise
  // Localizations are accessed using an InheritedWidget "of" syntax
  static AppLocalization of(BuildContext context) {
    return Localizations.of<AppLocalization>(context, AppLocalization);
  }

  // Static member to have a simple access to the delegate from the MaterialApp
  static const LocalizationsDelegate<AppLocalization> delegate =
      _AppLocalizationsDelegate();

  Map<String, String> _localizedStrings;

  Future<dynamic> load(locale) async {
    // Load the language JSON file from the "lang" folder
    // print("DATAAA" + 'assets/language/${locale.languageCode}.json');
    String jsonString = await rootBundle
        .loadString('assets/language/${locale.languageCode}.json');
    Map<String, dynamic> jsonMap = json.decode(jsonString);

    _localizedStrings = jsonMap.map((key, value) {
      return MapEntry(key, value.toString());
    });

    return true;
  }

  // This method will be called from every widget which needs a localized text
  String translate(String key) {
    return _localizedStrings[key] ?? "Missing Localized String";
  }
}

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

  @override
  bool isSupported(Locale locale) {
    // Include all of your supported language codes here
    return supportedLanguages.contains(locale.languageCode) ||
        supportedLanguages.contains(locale);
  }

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

  @override
  bool shouldReload(_AppLocalizationsDelegate old) => true;
}

supported_languages.dart

add the file in lib/localization folder

import 'dart:ui';

const supportedLanguages = [
  const Locale.fromSubtags(languageCode: 'en'), // generic Chinese 'zh'
  const Locale.fromSubtags(
      languageCode: 'zh',
      scriptCode: 'Hant'), // generic traditional Chinese 'zh_Hant'
];

Translated Json files

  • en.json file includes all the words for English
  • zh.json file has all the words in Chinese

    add this file in assets/language folder


en.json

{
  "TITLE":"Localization Example"

}

zh.json

{
  "TITLE": "本地化示例"
}

Now we have added all required files for Localization.

Lets move to the implementation part

Implement Localization in App

add the following code in main.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:localization_app/localization/LocalizationKeys.dart';
import 'package:localization_app/localization/app_localizations.dart';
import 'package:localization_app/localization/supported_languages.dart';
import 'package:localization_app/view_models/settings_view_model.dart';
import 'package:provider/provider.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) => SettingsViewModel(),
        ),
      ],
      child: Consumer<SettingsViewModel>(
        builder: (context, viewModel, child) {
          return MaterialApp(
            supportedLocales: supportedLanguages,
            localizationsDelegates: [
              AppLocalization.delegate,
              DefaultMaterialLocalizations.delegate,
              DefaultWidgetsLocalizations.delegate,
              DefaultCupertinoLocalizations.delegate,
            ],
            locale: viewModel.getLocale,
            title: 'Localization Example',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: MyHomePage(title: 'Localization Example'),
          );
        },
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Consumer<SettingsViewModel>(builder: (context, model, child) {
      return MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  AppLocalization.of(context).translate("TITLE"),
                ),
                ElevatedButton(
                    onPressed: () {
                      model.setLocale(model.getLocale == Locale("en")
                          ? Locale("zh")
                          : Locale("en"));
                    },
                    child: Text("Change Language"))
              ],
            ),
          ),
        ),
      );
    });
  }
}
  • HomePage has a Text widget and a ElevatedButton to switch languages.
  • In onPress of ElevatedButton we are switching languages based on the current language.

Don’t forget Add following line in pubspec.yaml

  assets:
    - assets/language/

Now we are all set to run the Application

Output

​The full source code is available here.

That’s it!! Thanks for Reading