Almost all the countries have their own language and most people understand only one or two languages. The application experience can be painful if the application is not available in its own language. So localization is needed to ensure people can use the application easily.
The localization implementation becomes painful if it is not integrated in a proper way. Here I am adding quick steps to integrate the localization feature.
Step 1:
Enable localization from the pubspec.yaml
. Take a look at four lines with the comment # Add this line
### pubspec.yaml
name: language_switch
description: A new Flutter project.
# Prevent accidental publishing to pub.dev.
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: ">=2.16.2 <3.0.0"
dependencies:
cupertino_icons: ^1.0.2
flutter:
sdk: flutter
flutter_localizations: # Add this line
sdk: flutter # Add this line
intl: ^0.17.0 # Add this line
dev_dependencies:
flutter_lints: ^1.0.0
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
generate: true # Add this line
uses-material-design: true
Step 2:
Add file l10n.yaml
to the root of the flutter project stating the localized JSON file location and generated localization file location.
### l10n.yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
Step 4:
Add respective localized strings inside the folder lib/l10n
.
// app_en.arb
{
"helloWorld": "Hello World!",
"@helloWorld": {
"description": "The conventional newborn programmer greeting"
}
}
// app_ja.arb
{
"helloWorld": "「こんにちは世界」"
}
// app_ne.arb
{
"helloWorld": "नमस्कार संसार!"
}
Step 5:
Configure the application to support the localized language values, restoring the previously used locale.
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'src/home.dart';
void main() {
// For simplicity default language is set to English
// You should persist language to local storage and retrieve from there
Locale locale = const Locale.fromSubtags(languageCode: 'en');
runApp(MyApp(locale));
}
class MyApp extends StatefulWidget {
const MyApp(this.locale, {Key? key}) : super(key: key);
final Locale locale;
@override
State<MyApp> createState() => _MyAppState();
// This function is used to switch the language in runtime
static _MyAppState? of(BuildContext context) =>
context.findAncestorStateOfType<_MyAppState>();
}
class _MyAppState extends State<MyApp> {
late Locale _locale;
void setLocale(Locale value) {
setState(() {
_locale = value;
});
}
@override
void initState() {
super.initState();
_locale = widget.locale;
}
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Language Demo',
theme: ThemeData(primarySwatch: Colors.blue),
// if locale value is not set, default system provided locale will be used
locale: _locale,
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
AppLocalizations.delegate,
],
supportedLocales: const [
Locale('en', 'US'),
Locale('ne', 'NP'),
Locale('ja', 'JP'),
],
home: const MyHomePage(),
);
}
}
Step 6:
Use the localized string and update the locale setting while using the application.
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../main.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _switchLanguage(BuildContext context, String languageCode) {
// switch language; also persist the value to local storage to retrieve later
// when application is restarted; retrieved and used inside main.dart
MyApp.of(context)
?.setLocale(Locale.fromSubtags(languageCode: languageCode));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Language Switch'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(AppLocalizations.of(context)?.helloWorld ?? 'n/a'),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _switchLanguage(context, 'en'),
child: const Text('English'),
),
ElevatedButton(
onPressed: () => _switchLanguage(context, 'ne'),
child: const Text('Nepali')),
ElevatedButton(
onPressed: () => _switchLanguage(context, 'ja'),
child: const Text('Japanese')),
],
),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Bonus :
The access to the localized string needs to import the AppLocalizations
file generated which might be shown as an error by the IDE. Even its showing red, the application will run without any errors if the localization key is correct. An extension of context can also be used to fetch the localization values like below.
// localization_ext.dart
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
extension ContextExt on BuildContext {
AppLocalizations? get localization => AppLocalizations.of(this);
}
class ExtensionSample extends StatelessWidget {
const ExtensionSample({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
//return Text(AppLocalizations.of(context)?.helloWorld ?? 'n/a');
// using extension
return Text(context.localization?.helloWorld ?? 'n/a');
}
}
References: