Jindal India Mobile App - Localization Guide

Overview

The Jindal India Mobile App supports multilingual user interfaces using Flutter's built-in localization framework. The localization system is implemented using Application Resource Bundle (ARB) files, code-generated localization classes, Riverpod state management, and SharedPreferences for language persistence.

This document describes the localization architecture, file structure, implementation flow, and maintenance procedures.


Technology Stack

The localization implementation is based on the following technologies:

Technology

Purpose

flutter_localizations

Provides Flutter's localization infrastructure and delegates

intl

Handles message translation, pluralization, and formatting

Riverpod

Manages the application's locale state reactively

SharedPreferences

Persists the user's selected language across app sessions

ARB Files

Stores translation resources for each supported language

flutter gen-l10n

Generates strongly typed localization classes from ARB files


Project Structure

The localization system consists of the following files and directories:

lib/l10n/

Contains:

  • Translation source files (app_*.arb)

  • Generated localization files:

    • app_localizations.dart

    • app_localizations_en.dart

    • app_localizations_hi.dart

    • Other language-specific generated classes

lib/localization/locale_provider.dart

Responsible for:

  • Defining localeProvider

  • Managing the active locale through LocaleNotifier

  • Maintaining the list of supported locales

  • Providing display names for supported languages

lib/config/shared_pref.dart

Responsible for:

  • Saving the selected locale

  • Loading the saved locale during application startup

lib/views/home/language_selection_screen.dart

Responsible for:

  • Displaying available languages

  • Allowing users to select a preferred language

  • Displaying language icons

lib/main.dart

Responsible for:

  • Configuring localization delegates

  • Registering supported locales

  • Applying the active locale to MaterialApp.router


Supported Languages

The application currently supports the following languages:

Language Code

Display Name

Icon Path

en

English (Default)

assets/images/english_icon.png

hi

हिन्दी (Hindi)

assets/images/hindi_icon.png

gu

ગુજરાતી (Gujarati)

assets/images/gujrati_icon.png

bn

বাংলা (Bengali)

assets/images/bengali_icon.png

mr

मराठी (Marathi)

assets/images/marathi_icon.png

te

తెలుగు (Telugu)

assets/images/telugu_icon.png

ta

தமிழ் (Tamil)

assets/images/tamil_icon.png

or

ଓଡ଼ିଆ (Odia)

assets/images/odia_icon.png

pa

ਪੰਜਾਬੀ (Punjabi)

assets/images/punjabi_icon.png

kn

ಕನ್ನಡ (Kannada)

assets/images/kannada_icon.png

ml

മലയാളം (Malayalam)

assets/images/malayalam_icon.png

as

অসমীয়া (Assamese)

assets/images/assamese_icon.png (Falls back to a default icon if unavailable)


Localization Workflow

The following flow illustrates how the application loads, updates, and persists the selected locale:

graph TD
    A[Application Startup] --> B[Load Locale from SharedPreferences]
    B --> C[Initialize LocaleNotifier]
    C --> D[Update localeProvider State]
    D --> E[MaterialApp Rebuilds with Active Locale]

    F[User Opens Language Selection Screen] --> G[User Selects a Language]
    G --> H[LocaleNotifier.setLocale()]
    H --> I[Persist Locale in SharedPreferences]
    H --> J[Update localeProvider State]
    J --> E


Persistence Layer

Save Locale

static const String localeKey = 'app_locale';

static Future<void> saveLocale(String localeCode) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString(localeKey, localeCode);
}

Load Locale

static Future<String?> loadLocale() async {
  final prefs = await SharedPreferences.getInstance();
  return prefs.getString(localeKey);
}


Locale State Management

The application uses Riverpod's StateNotifierProvider to manage the active locale.

final localeProvider = StateNotifierProvider<LocaleNotifier, Locale>((ref) {
  return LocaleNotifier();
});

class LocaleNotifier extends StateNotifier<Locale> {
  LocaleNotifier() : super(const Locale('en')) {
    _loadLocale();
  }

  Future<void> _loadLocale() async {
    final savedLocale = await SharedPrefsHelper.loadLocale();

    if (savedLocale != null) {
      state = Locale(savedLocale);
    }
  }

  Future<void> setLocale(Locale locale) async {
    if (!L10n.supportedLocales.contains(locale)) {
      return;
    }

    state = locale;
    await SharedPrefsHelper.saveLocale(locale.languageCode);
  }
}


MaterialApp Configuration

The selected locale is applied to MaterialApp.router.

@override
Widget build(BuildContext context) {
  final locale = ref.watch(localeProvider);

  return MaterialApp.router(
    locale: locale,
    localizationsDelegates: const [
      AppLocalizations.delegate,
      GlobalMaterialLocalizations.delegate,
      GlobalWidgetsLocalizations.delegate,
      GlobalCupertinoLocalizations.delegate,
    ],
    supportedLocales: const [
      Locale('en'),
      Locale('hi'),
      Locale('gu'),
      // Additional supported locales
    ],
  );
}


Using Localized Strings

Import Localization Class

import 'package:jindal_india/l10n/app_localizations.dart';

Access Localizations

final l10n = AppLocalizations.of(context)!;

Display Localized Text

Text(l10n.loginScreenTitle)


Working with Dynamic Placeholders

Define Placeholders in ARB File

"insufficientPoints": "You need at least {points} points to place this order. Currently, you have {available} points.",
"@insufficientPoints": {
  "placeholders": {
    "points": {
      "type": "String"
    },
    "available": {
      "type": "String"
    }
  }
}

Access in Dart

l10n.insufficientPoints(
  requiredPointsStr,
  availablePointsStr,
);


Adding a New Translation Key

Step 1: Add the key in app_en.arb

"welcomeUser": "Welcome, {name}!",
"@welcomeUser": {
  "placeholders": {
    "name": {
      "type": "String"
    }
  }
}

Step 2: Add translations in other ARB files

Example (app_hi.arb):

"welcomeUser": "स्वागत है, {name}!"

Step 3: Generate Localization Files

flutter gen-l10n

Note: Since generate: true is enabled in pubspec.yaml, localization files are also generated automatically during compilation and hot restart.


Enabling Assamese (as) Locale

Update locale_provider.dart

Add the locale:

Locale('as')

Update language name mapping:

case 'as':
  return 'অসমীয়া (Assamese)';

Update main.dart

Add Assamese to supportedLocales:

Locale('as')

Update language_selection_screen.dart

Add icon mapping:

case 'as':
  return 'assets/images/assamese_icon.png';

Ensure the icon asset exists or provide a fallback icon.


Adding a New Language

To introduce a completely new language:

Step 1: Create a New ARB File

Example:

lib/l10n/app_ta.arb

Add:

{
  "@@locale": "ta",
  "loginScreenTitle": "மீண்டும் வருக,"
}

Step 2: Generate Localization Classes

flutter gen-l10n

Step 3: Register the Locale

Update the following files:

main.dart

Add the locale to:

supportedLocales

locale_provider.dart

Add the locale to:

  • L10n.supportedLocales

  • L10n.getLanguageName()

language_selection_screen.dart

Add language icon mapping:

_getLanguageIcon(String code)


Best Practices

  • Always add new translation keys to app_en.arb first.

  • Maintain identical translation keys across all ARB files.

  • Use placeholders instead of string concatenation.

  • Run flutter gen-l10n after modifying ARB files.

  • Keep language names and icons synchronized with supported locales.

  • Validate translations before releasing to production.

  • Prefer descriptive and meaningful translation keys (for example, loginScreenTitle instead of title1).


Summary

The Jindal India Mobile App localization framework provides:

  • Reactive language switching using Riverpod

  • Persistent locale storage using SharedPreferences

  • Type-safe localization through generated classes

  • Support for multiple Indian languages

  • Easy onboarding of new languages with minimal code changes

  • Centralized translation management through ARB files

This architecture ensures scalability, maintainability, and a consistent multilingual experience across the application.

Written by :- Ajay kumar

On this page