Skip to content

Commit 2f5ad6d

Browse files
authored
Merge pull request #246 from amitamrutiya2210/multi-lang-support
Multi-language support implementation for flood-mobile app
2 parents 82ebc96 + 442ae0c commit 2f5ad6d

File tree

75 files changed

+6612
-567
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+6612
-567
lines changed

.github/workflows/dart.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
with:
2020
flutter-version: '3.10.5'
2121
- run: flutter pub get
22+
- run: flutter gen-l10n --arb-dir=lib/l10n/arb
2223
- run: flutter analyze
2324
- run: dart format --output=none --set-exit-if-changed .
2425
- run: flutter test

CONTRIBUTING.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,20 @@ flutter doctor
6868
flutter pub get
6969
```
7070

71-
5. Installing packages (**IOS ONLY**)
71+
5. Initialize localization for multi-language support.
72+
73+
```bash
74+
flutter gen-l10n --arb-dir=lib/l10n/arb
75+
```
76+
77+
6. Installing packages (**IOS ONLY**)
7278

7379
```bash
7480
cd ios
7581
pod install --verbose
7682
```
7783

78-
6. Run the app:
84+
7. Run the app:
7985

8086
```bash
8187
flutter run

lib/Blocs/bloc_provider_list.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:flood_mobile/Blocs/language_bloc/language_bloc.dart';
12
import 'package:flutter_bloc/flutter_bloc.dart';
23
import 'package:flood_mobile/Blocs/api_bloc/api_bloc.dart';
34
import 'package:flood_mobile/Blocs/filter_torrent_bloc/filter_torrent_bloc.dart';
@@ -51,5 +52,9 @@ class BlocProviders {
5152
BlocProvider<OnBoardingPageColorBloc>(
5253
create: (context) => OnBoardingPageColorBloc(),
5354
),
55+
BlocProvider<LanguageBloc>(
56+
create: (context) => LanguageBloc(),
57+
lazy: false,
58+
),
5459
];
5560
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import 'dart:ui';
2+
import 'package:bloc/bloc.dart';
3+
import 'package:equatable/equatable.dart';
4+
import 'package:shared_preferences/shared_preferences.dart';
5+
6+
part 'language_event.dart';
7+
part 'language_state.dart';
8+
9+
class LanguageBloc extends Bloc<LanguageEvent, LanguageState> {
10+
LanguageBloc() : super(LanguageState.initial()) {
11+
on<ChangeLanguageEvent>(_handleChangeLanguageEvent);
12+
on<GetPreviousLanguageEvent>(_handleGetPreviousSetLanguage);
13+
}
14+
15+
Future<void> _handleChangeLanguageEvent(
16+
ChangeLanguageEvent event, Emitter<LanguageState> emit) async {
17+
await storeCurrentLang(event.languageCode);
18+
emit(state.copyWith(event.languageCode));
19+
}
20+
21+
void _handleGetPreviousSetLanguage(
22+
GetPreviousLanguageEvent event, Emitter<LanguageState> emit) async {
23+
Locale? storedLanguageCode = await getPreviousLang();
24+
emit(state.copyWith(storedLanguageCode));
25+
}
26+
27+
Future<Locale?> getPreviousLang() async {
28+
try {
29+
final prefs = await SharedPreferences.getInstance();
30+
if (prefs.getString('languageCode') != 'null')
31+
return Locale(prefs.getString('languageCode')!);
32+
else {
33+
return null;
34+
}
35+
} catch (error) {
36+
print('Error retrieving language code from SharedPreferences: $error');
37+
}
38+
return null;
39+
}
40+
41+
Future<void> storeCurrentLang(Locale? code) async {
42+
try {
43+
final prefs = await SharedPreferences.getInstance();
44+
if (code == null)
45+
await prefs.setString('languageCode', 'null');
46+
else
47+
await prefs.setString('languageCode', code.languageCode);
48+
} catch (error) {
49+
print('Error retrieving language code from SharedPreferences: $error');
50+
}
51+
}
52+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
part of 'language_bloc.dart';
2+
3+
abstract class LanguageEvent extends Equatable {
4+
const LanguageEvent();
5+
6+
@override
7+
List<Object?> get props => [];
8+
}
9+
10+
class ChangeLanguageEvent extends LanguageEvent {
11+
final Locale? languageCode;
12+
13+
const ChangeLanguageEvent(this.languageCode);
14+
15+
@override
16+
List<Object?> get props => [languageCode];
17+
}
18+
19+
class GetPreviousLanguageEvent extends LanguageEvent {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
part of 'language_bloc.dart';
2+
3+
class LanguageState extends Equatable {
4+
final Locale? locale;
5+
6+
LanguageState(this.locale);
7+
8+
factory LanguageState.initial() => LanguageState(null);
9+
10+
LanguageState copyWith(Locale? locale) => LanguageState(locale);
11+
12+
@override
13+
List<Object?> get props => [locale];
14+
}
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
import 'package:bloc/bloc.dart';
22
import 'package:equatable/equatable.dart';
3-
import 'package:flood_mobile/Pages/onboarding_main_screen/data/onboard_page_data.dart';
43
import 'package:flutter/material.dart';
54

65
part 'on_boarding_page_color_event.dart';
76
part 'on_boarding_page_color_state.dart';
87

98
class OnBoardingPageColorBloc
109
extends Bloc<OnBoardingPageColorEvent, OnBoardingPageColorState> {
11-
Color color = onboardData[0].accentColor;
12-
OnBoardingPageColorBloc() : super(OnBoardingPageColorInitial()) {
10+
OnBoardingPageColorBloc() : super(OnBoardingPageColorState.initial()) {
1311
on<SetColorEvent>((event, emit) {
14-
// Update the color variable with the new color
15-
color = event.color;
1612
// Emit a ColorUpdated state with the new color
17-
emit(ColorUpdated(color: event.color));
13+
emit(state.copyWith(color: event.color));
1814
});
1915
}
2016
}

lib/Blocs/onboarding_main_page_bloc/on_boarding_page_color_state.dart

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
part of 'on_boarding_page_color_bloc.dart';
22

3-
abstract class OnBoardingPageColorState extends Equatable {
4-
const OnBoardingPageColorState();
5-
6-
@override
7-
List<Object> get props => [];
8-
}
3+
class OnBoardingPageColorState extends Equatable {
4+
final Color color;
95

10-
class OnBoardingPageColorInitial extends OnBoardingPageColorState {}
6+
OnBoardingPageColorState({required this.color});
117

12-
class ColorUpdated extends OnBoardingPageColorState {
13-
final Color color;
8+
factory OnBoardingPageColorState.initial() =>
9+
OnBoardingPageColorState(color: Color(0xff39C481));
1410

15-
ColorUpdated({required this.color});
11+
OnBoardingPageColorState copyWith({required Color? color}) =>
12+
OnBoardingPageColorState(color: color ?? this.color);
1613

1714
@override
1815
List<Object> get props => [color];

lib/Constants/languages.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const Languages = {
2+
'auto': 'Automatic',
3+
'en': 'English',
4+
'hi': 'हिन्दी',
5+
'cs': 'Čeština',
6+
'de': 'Deutsch',
7+
'es': 'Español',
8+
'fr': 'Français',
9+
'it': 'italiano',
10+
'hu': 'Magyar',
11+
'nl': 'Nederlands',
12+
'no': 'norsk',
13+
'pl': 'Polskie',
14+
'pt': 'português',
15+
'ru': 'русский язык',
16+
'ro': 'Romanian',
17+
'fi': 'suomi',
18+
'sv': 'svenska',
19+
'uk': 'українська мова',
20+
'ko': '한국어',
21+
'ja': '日本語',
22+
'zh': '中文(繁體)',
23+
'ar': 'اَلْعَرَبِيَّةُ',
24+
};

lib/Pages/about_screen/about_screen.dart

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:flood_mobile/l10n/l10n.dart';
12
import 'package:flutter/material.dart';
23
import 'package:flood_mobile/Blocs/theme_bloc/theme_bloc.dart';
34
import 'package:flutter_svg/flutter_svg.dart';
@@ -65,7 +66,7 @@ class _AboutScreenState extends State<AboutScreen> {
6566
crossAxisAlignment: CrossAxisAlignment.start,
6667
children: [
6768
Text(
68-
'Flood is a monitoring service for various torrent clients. It\'s a Node.js service that communicates with your favorite torrent client and serves a decent mobile UI for administration. This project is based on the original Flood project.',
69+
context.l10n.app_info,
6970
key: Key('App info text key'),
7071
style: TextStyle(
7172
color: ThemeBloc.theme(widget.themeIndex)
@@ -78,7 +79,7 @@ class _AboutScreenState extends State<AboutScreen> {
7879
height: 20,
7980
),
8081
Text(
81-
'Feedback',
82+
context.l10n.feedback_heading,
8283
style: TextStyle(
8384
color: ThemeBloc.theme(widget.themeIndex)
8485
.textTheme
@@ -91,7 +92,7 @@ class _AboutScreenState extends State<AboutScreen> {
9192
height: 10,
9293
),
9394
Text(
94-
'If you have a specific issue or bug, please file a GitHub issue. Please join the Flood Discord server to discuss feature requests and implementation details.',
95+
context.l10n.feedback_text,
9596
key: Key('Feedback text key'),
9697
style: TextStyle(
9798
color: ThemeBloc.theme(widget.themeIndex)
@@ -104,7 +105,7 @@ class _AboutScreenState extends State<AboutScreen> {
104105
height: 20,
105106
),
106107
Text(
107-
'More Information',
108+
context.l10n.more_info_text,
108109
style: TextStyle(
109110
color: ThemeBloc.theme(widget.themeIndex)
110111
.textTheme
@@ -117,7 +118,7 @@ class _AboutScreenState extends State<AboutScreen> {
117118
height: 10,
118119
),
119120
Text(
120-
'Check out the Wiki for more information.',
121+
context.l10n.check_out_info,
121122
key: Key('More info text key'),
122123
style: TextStyle(
123124
color: ThemeBloc.theme(widget.themeIndex)

0 commit comments

Comments
 (0)