Flutter Localization in my words

I write articles for my own reference only, whenever I learn stuff, I make use of medium.com to keep note of what things I’m doing to make something work, so in future I can read it in my own words and solve my problem

  1. add dependencies
dependencies:

provider: ^3.1.0

add asset in pubspec.yaml like this

assets:
- i18n/en.json
- i18n/gu.json

for example, en.json contains

{
"title": "Hello!",
"Message" : "This is English language"
}

and gu.json contains

{
"title": "નમસ્તે!",
"Message" : "આ ગુજરાતી ભાષા છે"
}

you can define all strings required for your app in like this way. Here, en and gu are language code

2. AppLocalizations class

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

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

Map<String, String> _localizedStrings;

Future<bool> load() async {

String jsonString =
await rootBundle.loadString('i18n/${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];
}
}


class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {

const _AppLocalizationsDelegate();

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

@override
Future<AppLocalizations> load(Locale locale) async {

AppLocalizations localizations = new AppLocalizations(locale);
await localizations.load();
return localizations;
}

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

3. create demo page to check if everything works fine, but before it work, we need to wrap our MaterialApp with provider like this,

return ChangeNotifierProvider<AppLanguage>(
create: (context) => appLanguage,
child: Consumer<AppLanguage>(builder: (context, model, child) {
return MaterialApp(
locale: model.appLocal,
supportedLocales: [
Locale('en', 'US'),
Locale('gu', ''),
],
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: HomePage(),
);
}),
);

In order to save locale state, we can make use of shared_preference

create AppLanguage class like this,

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class AppLanguage extends ChangeNotifier {
Locale _appLocale = Locale('en');

Locale get appLocal => _appLocale ?? Locale("en");
fetchLocale() async {
var prefs = await SharedPreferences.getInstance();
if (prefs.getString('language_code') == null) {
_appLocale = Locale('en');
return Null;
}
_appLocale = Locale(prefs.getString('language_code'));
return Null;
}

void changeLanguage(Locale type) async {
var prefs = await SharedPreferences.getInstance();
if (_appLocale == type) {
return;
}
if (type == Locale("gu")) {
_appLocale = Locale("gu");
await prefs.setString('language_code', 'gu');
await prefs.setString('countryCode', '');
} else {
_appLocale = Locale("en");
await prefs.setString('language_code', 'en');
await prefs.setString('countryCode', 'US');
}
notifyListeners();
print(_appLocale);
}
}

we used notifyListeners() here, so when there is some change happen, it will listen to change and we used Consumer on top of our app, so whole app language will be changed in realtime without reloading app

I write articles for my own reference only. I use medium.com as my digital notebook