Skip to content

Commit

Permalink
Merge pull request #279 from odisha-muktasoft/ref-dynamic-localization
Browse files Browse the repository at this point in the history
 Hive no-SQL database has been implemented in replace of flutter secure storage for the localisation issues.
  • Loading branch information
Tulika-eGov authored Mar 7, 2024
2 parents 33b5319 + c5d46c2 commit 34e00c4
Show file tree
Hide file tree
Showing 29 changed files with 2,004 additions and 1,120 deletions.
8 changes: 4 additions & 4 deletions frontend/works_shg_app/.env
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
BASE_URL='https://works-dev.digit.org/'
BASE_URL='https://mukta-uat.digit.org/'
MDMS_API_PATH='egov-mdms-service/v1/_search'
GLOBAL_ASSETS='https://works-dev.digit.org/works-dev-asset/worksGlobalConfig.json'
TENANT_ID='pg'
GLOBAL_ASSETS='https://mukta-uat.digit.org/mukta-uat-bucket-s3/muktaGlobalConfig.json'
TENANT_ID='statea'
CONNECT_TIMEOUT="120000"
RECEIVE_TIMEOUT="120000"
SEND_TIMEOUT="120000"
ENV_NAME="DEV"
ENV_NAME="UAT"
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import 'dart:async';
import 'dart:convert';
import 'dart:ui';

import 'package:collection/collection.dart';
import 'package:digit_components/models/digit_row_card/digit_row_card_model.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:universal_html/html.dart' as html;
Expand All @@ -16,7 +16,7 @@ import '../../data/repositories/remote/getGlobalConfig_repo.dart';
import '../../data/repositories/remote/mdms.dart';
import '../../models/init_mdms/global_config_model.dart';
import '../../services/local_storage.dart';
import '../localization/app_localization.dart';
import '../localization/localization.dart';

part 'app_initilization.freezed.dart';

Expand All @@ -27,20 +27,26 @@ List<DigitRowCardModel>? digitRowCardItems;

class AppInitializationBloc
extends Bloc<AppInitializationEvent, AppInitializationState> {
final LocalizationBloc localizationBloc;
final MdmsRepository mdmsRepository;
AppInitializationBloc(super.initialState, this.mdmsRepository) {
AppInitializationBloc(
super.initialState, this.mdmsRepository, this.localizationBloc) {
on<AppInitializationSetupEvent>(_onAppInitializeSetup);
}

// Event handler for initializing the application
FutureOr<void> _onAppInitializeSetup(
AppInitializationSetupEvent event,
AppInitializationEmitter emit,
) async {
// Check if global configuration and state info are not yet fetched

if (GlobalVariables.globalConfigObject == null ||
GlobalVariables.stateInfoListModel == null) {
GlobalConfigModel globalConfigModel =
await GetGlobalConfig().getGlobalConfig();

// Initialize MDMS registry
InitMdmsModel result = await mdmsRepository.initMdmsRegistry(
apiEndPoint: Urls.initServices.mdms,
tenantId: globalConfigModel.globalConfigs!.stateTenantId.toString(),
Expand Down Expand Up @@ -73,13 +79,16 @@ class AppInitializationBloc
languages: [
...result.commonMastersModel!.stateInfoListModel![0].languages!
.mapIndexed((i, element) {
if (element.value == event.selectedLang) {
if (element.value == result.commonMastersModel!.stateInfoListModel!.first.languages!.first.value) {
return element.copyWith(isSelected: true);
} else {
return element;
}
})
].toList());

// Store fetched data locally
// Session storage for web, local storage for other platforms
if (kIsWeb) {
html.window.sessionStorage['initData'] = jsonEncode(result.toJson());
html.window.sessionStorage['StateInfo'] = jsonEncode(ss);
Expand All @@ -106,6 +115,9 @@ class AppInitializationBloc
localLanguageData = await storage.read(key: 'languages');
}

// Update local variables with fetched data
// Initialize digitRowCardItems with languages

if (localInitData != null &&
localInitData.trim().isNotEmpty &&
localStateData != null &&
Expand All @@ -118,39 +130,30 @@ class AppInitializationBloc
.toList();
} else {}

await AppLocalizations(
Locale(
digitRowCardItems!
.firstWhere((e) => e.isSelected)
.value
.split('_')
.first,
digitRowCardItems!
.firstWhere((e) => e.isSelected)
.value
.split('_')
.last),
).load();

emit(state.copyWith(
// Dispatch LocalizationEvent for loading localization data
localizationBloc.add(
LocalizationEvent.onLoadLocalization(
module:
'rainmaker-common,rainmaker-common-masters,rainmaker-${stateInfoListModel?.code}',
tenantId: initMdmsModelData
.commonMastersModel!.stateInfoListModel!.first.code
.toString(),
locale: digitRowCardItems!.firstWhere((e) => e.isSelected).value,
languages: ss.languages,
localizationModules: ss.localizationModules,
),
);
// Emit updated state
emit(
state.copyWith(
isInitializationCompleted: true,
initMdmsModel: initMdmsModelData,
stateInfoListModel: stateInfoListModel,
digitRowCardItems: digitRowCardItems));
await AppLocalizations(
Locale(
digitRowCardItems!
.firstWhere((e) => e.isSelected)
.value
.split('_')
.first,
digitRowCardItems!
.firstWhere((e) => e.isSelected)
.value
.split('_')
.last),
).load();
digitRowCardItems: digitRowCardItems,
),
);
} else {
// State info is already fetched, update language selection
StateInfoListModel ss = GlobalVariables.stateInfoListModel!.copyWith(
languages: [
...GlobalVariables.stateInfoListModel!.languages!
Expand All @@ -162,11 +165,15 @@ class AppInitializationBloc
}
})
].toList());

// Store updated language selection
if (kIsWeb) {
html.window.sessionStorage['languages'] = jsonEncode(ss.languages);
} else {
await storage.write(key: 'languages', value: jsonEncode(ss.languages));
}

// Fetch locally stored data
dynamic localInitData;
dynamic localStateData;
dynamic localLanguageData;
Expand All @@ -184,6 +191,7 @@ class AppInitializationBloc
localInitData.trim().isNotEmpty &&
localStateData != null &&
localLanguageData != null) {
// Update local variables with fetched data
initMdmsModelData = InitMdmsModel.fromJson(jsonDecode(localInitData));
stateInfoListModel =
StateInfoListModel.fromJson(jsonDecode(localStateData));
Expand All @@ -192,38 +200,28 @@ class AppInitializationBloc
.toList();
} else {}

await AppLocalizations(
Locale(
digitRowCardItems!
.firstWhere((e) => e.isSelected)
.value
.split('_')
.first,
digitRowCardItems!
.firstWhere((e) => e.isSelected)
.value
.split('_')
.last),
).load();

emit(state.copyWith(
// Dispatch LocalizationEvent for loading localization data
localizationBloc.add(
LocalizationEvent.onLoadLocalization(
module:
'rainmaker-common,rainmaker-common-masters,rainmaker-${stateInfoListModel?.code}',
tenantId: initMdmsModelData
.commonMastersModel!.stateInfoListModel!.first.code
.toString(),
locale: digitRowCardItems!.firstWhere((e) => e.isSelected).value,
languages: ss.languages,
localizationModules: ss.localizationModules,
),
);
// Emit updated state
emit(
state.copyWith(
isInitializationCompleted: true,
initMdmsModel: initMdmsModelData,
stateInfoListModel: stateInfoListModel,
digitRowCardItems: digitRowCardItems));
await AppLocalizations(
Locale(
digitRowCardItems!
.firstWhere((e) => e.isSelected)
.value
.split('_')
.first,
digitRowCardItems!
.firstWhere((e) => e.isSelected)
.value
.split('_')
.last),
).load();
digitRowCardItems: digitRowCardItems,
),
);
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions frontend/works_shg_app/lib/blocs/auth/auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:universal_html/html.dart' as html;
import 'package:works_shg_app/data/schema/localization.dart';
import 'package:works_shg_app/models/user_details/user_details_model.dart';
import 'package:works_shg_app/services/urls.dart';
import 'package:works_shg_app/utils/global_variables.dart';
Expand Down Expand Up @@ -89,7 +91,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
if (kIsWeb) {
html.window.sessionStorage.remove(e.value);
} else {
await storage.delete(key: e.value);

await Hive.box<KeyLocaleModel>('keyValueModel').clear();
await Hive.box<Localization>('localization').clear();
}
});
await AuthRepository(client.init()).logOutUser(
Expand Down Expand Up @@ -152,4 +156,4 @@ class AuthState with _$AuthState {
const factory AuthState.loaded(
UserDetailsModel? userDetailsModel, String? accessToken) = _Loaded;
const factory AuthState.error() = _Error;
}
}
85 changes: 34 additions & 51 deletions frontend/works_shg_app/lib/blocs/localization/app_localization.dart
Original file line number Diff line number Diff line change
@@ -1,73 +1,56 @@
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:universal_html/html.dart' as html;
import 'package:works_shg_app/blocs/localization/localization.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:works_shg_app/data/schema/localization.dart';

import '../../models/localization/localization_model.dart';
import '../../services/local_storage.dart';
import '../../utils/constants.dart';
import 'app_localizations_delegate.dart';

class AppLocalizations {
final Locale? locale;
final Locale locale;

AppLocalizations(this.locale);
AppLocalizations(
this.locale,
);
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations)!;
}

static List<LocalizationMessageModel> localizedStrings =
<LocalizationMessageModel>[];
static const LocalizationsDelegate<AppLocalizations> delegate =
AppLocalizationsDelegate();

Future<List<LocalizationMessageModel>?> getLocalizationLabels() async {
dynamic localLabelResponse;
if (kIsWeb) {
localLabelResponse = html.window.sessionStorage[
'${locale?.languageCode}_${locale?.countryCode}' ?? ''];
} else {
localLabelResponse = await storage.read(
key: '${locale?.languageCode}_${locale?.countryCode}');
}
await Future.delayed(const Duration(seconds: 1));
if (localLabelResponse != null && localLabelResponse.trim().isNotEmpty) {
return localizedStrings = jsonDecode(localLabelResponse)
.map<LocalizationMessageModel>(
(e) => LocalizationMessageModel.fromJson(e))
.toList();
} else {
localizedStrings = BlocProvider.of<LocalizationBloc>(
scaffoldMessengerKey.currentContext!)
.state
.maybeWhen(
orElse: () => [],
loaded: (List<LocalizationMessageModel>? localization) {
return localization;
}) ??
[];

return localizedStrings;
static List<dynamic> localizedStrings = <dynamic>[];

// Returns instance of custom localizations delegate
static LocalizationsDelegate<AppLocalizations> getDelegate() =>
const AppLocalizationsDelegate();

/* it fetches data from hive box based on the locale selection:
- store the list of data to localizedStrings
- for searching increasing efficiency
*/
Future<bool> load({required String locale}) async {
// Clear the list before loading localized strings
localizedStrings.clear();

// Get box for localization
final box = Hive.box<KeyLocaleModel>('keyValueModel');
// Convert values to list
final List<KeyLocaleModel> ll = box.values.toList();
if (ll.isNotEmpty) {
final localizationList =
ll.firstWhere((element) => element.locale == locale);

if (localizationList.localizationsList != null) {
localizedStrings.addAll(localizationList.localizationsList!);
}
}
}

Future<bool> load() async {
if (scaffoldMessengerKey.currentContext != null) {
await getLocalizationLabels();
return true;
} else {
return false;
}
return true;
}

translate(
String localizedValues,
) {
// Find index of localized string
var index =
localizedStrings.indexWhere((medium) => medium.code == localizedValues);
// Return localized string if found, otherwise return original value
return index != -1 ? localizedStrings[index].message : localizedValues;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
Locale locale,
) async {
AppLocalizations appLocalizations = AppLocalizations(locale);
await appLocalizations.load();
await appLocalizations.load(locale: "${locale.languageCode}_${locale.countryCode}");

return appLocalizations;
}
Expand Down
Loading

0 comments on commit 34e00c4

Please sign in to comment.