The Potential of Localisation and Internationalisation in Flutter: Connecting with Audiences Around the World

Introduction

In the linked world of today, creating applications that can serve a worldwide audience is essential. The flexible cross-platform framework Flutter has strong localization (l10n) and internationalization (i18n) features. Developers can easily adapt their user interfaces to accommodate various languages and cultural preferences by integrating i18n and l10n into Flutter apps. This allows them to reach a wider range of users worldwide.

Understanding Internationalization and Localization.

The process of creating and building an application to make it readily adaptable to many languages, countries, and cultures is known as internationalization, or i18n. On the other hand, localization, or l10n, is the process of modifying an application to fit a particular language or geographical area. This includes things like text translations, currency symbols, date and time formats, and number formatting.

Flutter’s Internationalization Support.

Strong tools and libraries offered by Flutter make internationalisation easier. The intl package, which provides tools for locale-specific formatting of dates, times, currencies, and messages, is the foundation of Flutter’s i18n support. This package can also be used by developers to manage language-specific text translations. Additionally, Flutter offers the flutter_localizations package, which saves developers a great deal of time and work by providing pre-defined localisation resources for a variety of languages.

Implementing Internationalization and Localization in Flutter.

Developers must take a few crucial actions in order to enable i18n and l10n in a Flutter application. The intl package or external localisation files should be used to define localised strings first. It is simple to translate and localise these strings for many languages. The Localisations widget in Flutter can then be used by developers to load the appropriate localisation resources according to the user’s selected locale. Additionally, they can format dates and numbers consistently across regions by using the intl techniques. Furthermore, several localisation settings, such language direction and text direction, are automatically handled by Flutter’s MaterialApp and CupertinoApp widgets.

Benefits and Challenges of Internationalization and Localization in Flutter.

Developers can gain a lot of advantages by integrating localisation and internationalisation into Flutter. By offering localised experiences that let users interact with the app in the language of their choice, they can increase the number of users. Because users feel more at ease interacting with content that is adapted to their cultural norms, localisation also improves user experience and engagement. Nevertheless, there may be difficulties in adopting i18n and l10n, including maintaining language-specific UI design, handling translation files, and making sure that each supported language is tested effectively.

A step-by-step guide on implementing internationalization and localization in Flutter:

Get Your Flutter Project Ready Make sure your Flutter project is configured and operational. Launch your project with the text editor or IDE of your choice.

Steps:

Add Dependencies In your project’s pubspec.yaml file, add the following dependencies:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any
  intl_utils:
flutter:
  generate: true
YAML

Save the file and run flutter pub get to fetch the dependencies.

Define Localized Strings Create a new directory in your project’s root directory called l10n or i18n inside this directory create intl_en.arb file and other lan file with intl_{lamguage_code}.arb

intl_en.arb

{
    "@@locale":"en",
    "hello":"Hello"
}
Dart

intl_hi.arb

{
    "@@locale":"hi",
    "hello":"नमस्ते"
}
Dart

Run the below command in project terminal

This command generates a .arb file for each supported language. You can then provide translations for these files and use the intl package to load and use them.

dart run intl_utils:generate

Import the necessary packages:

import 'package:flutter/material.dart';
import 'package:multi_lan_flutter_demo/generated/l10n.dart';
Dart

In customize MaterialApp Widget

 @override
  Widget build(BuildContext context) {
    return  MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          ),
          locale: Locale.fromSubtags(languageCode: localeLan.languageCode),
          localizationsDelegates: [
            S.delegate,
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          supportedLocales: S.delegate.supportedLocales,
          home: HomeScreen(),
    );
  }
Dart

State Management

Add Dependencies In your project’s pubspec.yaml file, add the following dependencies:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any
  intl_utils:

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.8
  intl_translation:
  shared_preferences:

  # state management
  flutter_bloc:
  bloc:
  get: 
YAML

Create Bloc Controller

import 'dart:ui';

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:multi_lan_flutter_demo/bloc/state/app_bloc_state.dart';
import 'package:shared_preferences/shared_preferences.dart';

class AppBlocController extends Cubit<AppBlocState> {
  String staticKeyForLan = "/shared/locale";
  AppBlocController() : super(AppBlocState(locale: Locale('en'))) {
    _initializeLocale(); // Automatically load the locale when AppBlocController is created
  }

  changeLocale(Locale locale) async {
    var pref = await SharedPreferences.getInstance();
    pref.setString(staticKeyForLan, locale.languageCode);
    Get.updateLocale(Locale.fromSubtags(languageCode: locale.languageCode));
    emit(state.copyWith(locale: locale));
  }

  Future<void> _initializeLocale() async {
    var pref = await SharedPreferences.getInstance();
    String lanKey = (pref.getString(staticKeyForLan)) ?? 'en';
    Get.updateLocale(Locale.fromSubtags(languageCode: lanKey));
    emit(state.copyWith(locale: Locale.fromSubtags(languageCode: lanKey)));
  }
}
Dart

Create Bloc State

import 'package:flutter/widgets.dart';

class AppBlocState {
  Locale locale;

  AppBlocState({required this.locale});

  copyWith({Locale? locale}) {
    return AppBlocState(locale: locale ?? this.locale);
  }
}
Dart

In main.dart create blocprovider and bloc selector to apply chnages

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get.dart';
import 'package:multi_lan_flutter_demo/bloc/controller/app_bloc_controller.dart';
import 'package:multi_lan_flutter_demo/bloc/state/app_bloc_state.dart';
import 'package:multi_lan_flutter_demo/generated/l10n.dart';
import 'package:multi_lan_flutter_demo/view/home_screen.dart';

void main() {
  runApp(
    BlocProvider(create: (_) => AppBlocController(), child: const MyApp()),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return BlocSelector<AppBlocController, AppBlocState, Locale>(
      selector: (AppBlocState state) => state.locale,
      builder: (BuildContext context, Locale localeLan) {
        return GetMaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          ),
          locale: Locale.fromSubtags(languageCode: localeLan.languageCode),
          localizationsDelegates: [
            S.delegate,
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
          ],
          supportedLocales: S.delegate.supportedLocales,
          home: HomeScreen(),
        );
      },
    );
  }
}
Dart

Now, within your widget, you can listen to the AppBlocController to change the language dynamically.

For example, in your MyHomePage widget:

@override
  Widget build(BuildContext context) {
    var locale = S.of(context);
    return Scaffold(
      appBar: AppBar(title: Text("Intl Language Demo")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("${locale.hello}"),
            SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Text("Change Language"),
                Container(
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.grey[200]!),
                  ),
                  child: Builder(
                    builder: (context) {
                      var items = S.delegate.supportedLocales;
                      return BlocSelector<
                        AppBlocController,
                        AppBlocState,
                        Locale
                      >(
                        selector: (AppBlocState state) => state.locale,
                        builder:
                            (BuildContext context, Locale state) =>
                                DropdownButton(
                                  isDense: true,
                                  value: state.languageCode,
                                  items: List.generate(
                                    items.length,
                                    (index) => DropdownMenuItem(
                                      value: items[index].languageCode,
                                      child: Text(items[index].languageCode),
                                    ),
                                  ),
                                  onChanged: (value) {
                                    context
                                        .read<AppBlocController>()
                                        .changeLocale(Locale(value!));
                                  },
                                ),
                      );
                    },
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
Dart

NOTE: Get.updateLocale use only when you are using a getx in your project insted of MaterialApp Widget.

That’s it! You’ve successfully implemented internationalization and localization in your Flutter app. Remember to add more localized strings and provide translations for each language as needed.

Conclusion

Flutter’s extensive support for localisation and internationalisation enables developers to produce applications that appeal to users around the world. By adopting i18n and l10n, developers can maximise the impact and reach of their applications by removing language barriers and providing users with immersive experiences throughout the globe.