Skip to content

Commit a675cc8

Browse files
committed
Update V1.1.2: Localization.
- Implemented a very unique Localization system. - Dart based CLI generator with isolates for extracting messages. - Auto merging all message files into one json. - Automatic google trnaslation for new messsages. - Automatic generated class based keys for accessing messages. - Implemented provider state solution.
1 parent eeb5c9f commit a675cc8

28 files changed

+1019
-271
lines changed

android/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ if (flutterVersionCode == null) {
1818

1919
def flutterVersionName = localProperties.getProperty('flutter.versionName')
2020
if (flutterVersionName == null) {
21-
flutterVersionName = '1.1.1'
21+
flutterVersionName = '1.1.2'
2222
}
2323

2424
apply plugin: 'com.android.application'

assets/langs/ar.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"DownloadScreen/title": "تحميل",
3+
"HomeScreen/title": "أهلا بك",
4+
"HomeScreen/desc": "استكشاف معهد اليونسكو للإحصاء وضعت بشكل رائع مع رفرفة جوجل صممه المصممين المبدعين.",
5+
"HomeScreen/uiList": "استكشاف معهد اليونسكو للإحصاء",
6+
"HomeScreen/about": "حول التطبيقات",
7+
"HomeScreen/aboutDeveloper": "وشك المطور",
8+
"HomeScreen/download": "تحميل",
9+
"HomeScreen/settings": "الإعدادات",
10+
"HomeScreen/modalWebTitle": "تحذير",
11+
"HomeScreen/modalWebDesc": "رفرفة ليس لديه دعم جيد لشبكة الإنترنت للخروج من مربع. هذا هو السبب في أنك سوف تواجه الخلل والتخلف. لا يوجد شيء خاطئ مع بلدي implementaion بيكوس كل شيء يعمل بشكل جيد على تطبيقات الوطنية.\n\nوذلك لخالية من المتاعب على نحو سلس تجربة فإنني أوصي لكم لتحميل التطبيق الأصلي",
12+
"HomeScreen/modalWebButton1": "تحميل",
13+
"HomeScreen/modalWebButton2": "استمر",
14+
"HomeScreen/modalDesktopTitle": "إنذار",
15+
"HomeScreen/modalDesktopDesc": "في \"BackButton\" بعض الشاشات ليست أفيبل بيكوس انها حققت UI البشعة. لذلك كبديل I نفذت اختصار لوحة المفاتيح لاعادة التنقل.\n\nماك: خيار + مسافة للخلف\nلينكس: البديل + مسافة للخلف\nنوافذ: السيطرة + مسافة للخلف",
16+
"HomeScreen/modalDesktopButton": "استمر",
17+
"HomeScreen/version": "الإصدار",
18+
"HomeScreen/settingsModalTitle": "اختار اللغة",
19+
"HomeScreen/settingsModalEnglish": "الإنجليزية",
20+
"HomeScreen/settingsModalChinese": "صينى",
21+
"HomeScreen/settingsModalArabic": "عربى",
22+
"HomeScreen/settingsModalSystemDefault": "النظام الافتراضي"
23+
}

assets/langs/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"welcome":"Welcome","test":"YUPPP","DownloadScreen/title":"Download","HomeScreen/welcome":"Welcome","HomeScreen/desc":"Explore elegantly crafted UIs with Google's Flutter designed by creative designers.","HomeScreen/title":"Welcome","HomeScreen/uiList":"Explore UIs","HomeScreen/about":"About App","HomeScreen/aboutDeveloper":"About Developer","HomeScreen/download":"Download","HomeScreen/modalWebTitle":"Warning","HomeScreen/modalWebDesc":"Flutter does not have good support for web out of box. That's why you will face bugs and lag. There is nothing wrong with my implementaion becuase every things works well on native apps.\n\nSo for hassle free smooth experience I recommend you to download native app","HomeScreen/modalWebButton1":"Download","HomeScreen/modalWebButton2":"Continue","HomeScreen/ModalDesktopTitle":"Alert","HomeScreen/ModalDesktopDesc":"In some screens 'BackButton' isn't avaible becuase it made UI hideous. So as an alternative I implemented keyboard shortcut to navigate back.\n\nMacOS: Option + Backspace\nLinux: Alt + Backsoace\nWindows: Ctrl + Backspace","HomeScreen/ModalDesktopButton":"Continue","HomeScreen/modalDesktopTitle":"Alert","HomeScreen/modalDesktopDesc":"In some screens 'BackButton' isn't avaible becuase it made UI hideous. So as an alternative I implemented keyboard shortcut to navigate back.\n\nMacOS: Option + Backspace\nLinux: Alt + Backspace\nWindows: Ctrl + Backspace","HomeScreen/modalDesktopButton":"Continue","HomeScreen/version":"VERSION","HomeScreen/settings":"Settings","SettingsScreen/title":"Settings","HomeScreen/settingsModalTitle":"Select Language","HomeScreen/settingsModalEnglish":"english","HomeScreen/settingsModalChinese":"chinese","HomeScreen/settingsModalArabic":"arabic","HomeScreen/settingsModalSystemDefault":"system default"}

assets/langs/zh.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"DownloadScreen/title":"下载","HomeScreen/title":"欢迎","HomeScreen/desc":"探索与谷歌的扑优雅制作的UI由创意的设计师设计的。","HomeScreen/uiList":"浏览用户界面","HomeScreen/about":"关于应用程序","HomeScreen/aboutDeveloper":"关于开发者","HomeScreen/download":"下载","HomeScreen/settings":"设置","HomeScreen/modalWebTitle":"警告","HomeScreen/modalWebDesc":"扑不具备开箱对网络的良好支持。这就是为什么你会面临漏洞和滞后。有什么错我implementaion监守每一件事上的本地应用效果很好。\n\n因此,对于轻松自由流畅的体验,我建议你下载本机应用程序","HomeScreen/modalWebButton1":"下载","HomeScreen/modalWebButton2":"继续","HomeScreen/modalDesktopTitle":"警报","HomeScreen/modalDesktopDesc":"在某些屏幕“后退按钮”不avaible,原因是其取得UI狰狞。因此,作为一种替代我实现了键盘快捷键,即可返回。\n\nMacOS的:选项+ Backspace键\nLinux的键:Alt + Backspace键\nWindows系统:按Ctrl + Backspace键","HomeScreen/modalDesktopButton":"继续","HomeScreen/version":"版","HomeScreen/settingsModalTitle":"选择语言","HomeScreen/settingsModalEnglish":"英语","HomeScreen/settingsModalChinese":"中文","HomeScreen/settingsModalArabic":"阿拉伯","HomeScreen/settingsModalSystemDefault":"系统默认"}

lib/AppLocalizations.dart

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import 'dart:async';
2+
import 'dart:convert';
3+
4+
import 'package:flutter/material.dart';
5+
import 'package:flutter/services.dart';
6+
import 'package:intl/intl.dart';
7+
8+
class AppLocalizations {
9+
AppLocalizations(this.locale);
10+
final Locale locale;
11+
12+
// Helper method to keep the code in the widgets concise
13+
// Localizations are accessed using an InheritedWidget "of" syntax
14+
static const LocalizationsDelegate<AppLocalizations> delegate =
15+
_AppLocalizationsDelegate();
16+
17+
static AppLocalizations of(BuildContext context) {
18+
return Localizations.of<AppLocalizations>(context, AppLocalizations);
19+
}
20+
21+
Map<String, String> _localizedStrings;
22+
23+
Future<bool> load() async {
24+
// Load the language JSON file from the "lang" folder
25+
String jsonString = await rootBundle.loadString(
26+
'assets/langs/${locale.languageCode}.json',
27+
);
28+
Map<String, dynamic> jsonMap = json.decode(jsonString);
29+
_localizedStrings = jsonMap.map((key, value) {
30+
return MapEntry(key, value.toString());
31+
});
32+
33+
return true;
34+
}
35+
36+
// This method will be called from every widget which needs a localized text
37+
String translate(String key) {
38+
return _localizedStrings[key];
39+
}
40+
}
41+
42+
// LocalizationsDelegate is a factory for a set of localized resources
43+
// In this case, the localized strings will be gotten in an AppLocalizations object
44+
class _AppLocalizationsDelegate
45+
extends LocalizationsDelegate<AppLocalizations> {
46+
// This delegate instance will never change (it doesn't even have fields!)
47+
// It can provide a constant constructor.
48+
const _AppLocalizationsDelegate();
49+
50+
@override
51+
bool isSupported(Locale locale) {
52+
// Include all of your supported language codes here
53+
return ['en', 'zh', 'ar'].contains(locale.languageCode);
54+
}
55+
56+
@override
57+
Future<AppLocalizations> load(Locale locale) async {
58+
// AppLocalizations class is where the JSON loading actually runs
59+
AppLocalizations localizations = new AppLocalizations(locale);
60+
await localizations.load();
61+
return localizations;
62+
}
63+
64+
@override
65+
bool shouldReload(_AppLocalizationsDelegate old) => false;
66+
}

lib/Navigator.dart

Lines changed: 80 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_localizations/flutter_localizations.dart';
3+
import 'package:flutter_uis/AppLocalizations.dart';
4+
import 'package:provider/provider.dart';
25
// import 'package:firebase/firebase.dart' as firebase;
36

47
import './configs/Theme.dart' as theme;
@@ -24,6 +27,7 @@ import './MiniApps/SkyView/Screens/DetailScreen/SKDetailScreen.dart';
2427
import 'package:flutter_uis/MiniApps/AsicsShoesConcept/Screens/HomeScreen/ASCHomeScreen.dart';
2528

2629
import 'MiniApps/EggTimerConcept/Screens/HomeScreen/EggTimerConcept.dart';
30+
import 'Providers/AppProvider.dart';
2731

2832
bool isAlt = false;
2933

@@ -45,73 +49,93 @@ class AppNavigator extends StatelessWidget {
4549
if (Platform.isWindows && keyName == ctrl) {
4650
isAlt = (runtime == 'RawKeyDownEvent');
4751
}
48-
49-
// print(
50-
// "runtime:${event.runtimeType} | keyName:${event.logicalKey.debugName} | alt:${event.isAltPressed}");
5152
if (runtime == 'RawKeyUpEvent' &&
5253
(keyName == 'Backspace' || keyName == 'Digit 1') &&
5354
(event.isAltPressed || isAlt) &&
5455
this.navigator.currentState.canPop()) {
5556
this.navigator.currentState.pop();
5657
}
5758
},
58-
child: MaterialApp(
59-
debugShowCheckedModeBanner: false,
60-
navigatorKey: this.navigator,
61-
theme: ThemeData(
62-
fontFamily: "Muli",
63-
primaryColor: theme.primary,
64-
accentColor: theme.primary,
65-
textTheme: TextTheme(
66-
bodyText2: TextStyle(
67-
color: Colors.black.withOpacity(0.6),
68-
),
69-
),
70-
),
71-
navigatorObservers: observers,
72-
home: HomeScreen(),
73-
onGenerateRoute: (settings) {
74-
final index = ["skDetail", "hfdDetail"].indexOf(settings.name);
75-
if (index > -1) {
76-
return PageRouteBuilder(
77-
settings: settings,
78-
pageBuilder: (_, __, ___) {
79-
if (index == 1) {
80-
return HFDDetailScreen();
59+
child: ChangeNotifierProvider<AppProvider>(
60+
create: (_) => AppProvider(),
61+
child: Consumer<AppProvider>(
62+
// stream: null,
63+
builder: (context, value, _) {
64+
return MaterialApp(
65+
debugShowCheckedModeBanner: false,
66+
locale: value.activeLocale,
67+
supportedLocales: AppProvider.locales,
68+
localizationsDelegates: [
69+
AppLocalizations.delegate,
70+
GlobalMaterialLocalizations.delegate,
71+
GlobalWidgetsLocalizations.delegate,
72+
],
73+
localeResolutionCallback: (locale, supportedLocales) {
74+
for (var supportedLocale in supportedLocales) {
75+
if (locale != null &&
76+
supportedLocale.languageCode == locale.languageCode &&
77+
supportedLocale.countryCode == locale.countryCode) {
78+
return supportedLocale;
79+
}
8180
}
82-
return SKDetailScreen(settings.arguments);
81+
return supportedLocales.first;
8382
},
84-
transitionsBuilder: (_, anim, __, child) {
85-
return FadeTransition(opacity: anim, child: child);
83+
navigatorKey: this.navigator,
84+
theme: ThemeData(
85+
fontFamily: "Muli",
86+
primaryColor: theme.primary,
87+
accentColor: theme.primary,
88+
textTheme: TextTheme(
89+
bodyText2: TextStyle(),
90+
),
91+
),
92+
navigatorObservers: observers,
93+
home: HomeScreen(),
94+
onGenerateRoute: (settings) {
95+
final index = ["skDetail", "hfdDetail"].indexOf(settings.name);
96+
if (index > -1) {
97+
return PageRouteBuilder(
98+
settings: settings,
99+
pageBuilder: (_, __, ___) {
100+
if (index == 1) {
101+
return HFDDetailScreen();
102+
}
103+
return SKDetailScreen(settings.arguments);
104+
},
105+
transitionsBuilder: (_, anim, __, child) {
106+
return FadeTransition(opacity: anim, child: child);
107+
},
108+
);
109+
}
110+
return MaterialPageRoute(builder: (context) => HomeScreen());
111+
},
112+
routes: <String, WidgetBuilder>{
113+
"home": (ctx) => new HomeScreen(),
114+
"about": (ctx) => new AboutAppScreen(),
115+
"aboutDeveloper": (ctx) => new AboutDeveloperScreen(),
116+
"download": (ctx) => new DownloadScreen(),
117+
"uiList": (ctx) => new UiListScreen(),
118+
"uiDetail": (ctx) => new UiDetailScreen(),
119+
"designerProfile": (ctx) => new DesignerProfileScreen(),
120+
121+
// Healthy Food Delivery
122+
"hfdHome": (ctx) => new HFDHomeScreen(),
123+
// "hfdDetail": (ctx) => new HFDDetailScreen(),
124+
125+
// Hot Air Balloon
126+
"habHome": (ctx) => new HABHomeScreen(),
127+
128+
// Sky View
129+
"skHome": (ctx) => new SKHomeScreen(),
130+
// "skDetail": (ctx) => new SKDetailScreen(),
131+
132+
"ascHome": (ctx) => new ASCHomeScreen(),
133+
134+
"etcHome": (ctx) => new ETCHomeScreen(),
86135
},
87136
);
88-
}
89-
return MaterialPageRoute(builder: (context) => HomeScreen());
90-
},
91-
routes: <String, WidgetBuilder>{
92-
"home": (ctx) => new HomeScreen(),
93-
"about": (ctx) => new AboutAppScreen(),
94-
"aboutDeveloper": (ctx) => new AboutDeveloperScreen(),
95-
"download": (ctx) => new DownloadScreen(),
96-
"uiList": (ctx) => new UiListScreen(),
97-
"uiDetail": (ctx) => new UiDetailScreen(),
98-
"designerProfile": (ctx) => new DesignerProfileScreen(),
99-
100-
// Healthy Food Delivery
101-
"hfdHome": (ctx) => new HFDHomeScreen(),
102-
// "hfdDetail": (ctx) => new HFDDetailScreen(),
103-
104-
// Hot Air Balloon
105-
"habHome": (ctx) => new HABHomeScreen(),
106-
107-
// Sky View
108-
"skHome": (ctx) => new SKHomeScreen(),
109-
// "skDetail": (ctx) => new SKDetailScreen(),
110-
111-
"ascHome": (ctx) => new ASCHomeScreen(),
112-
113-
"etcHome": (ctx) => new ETCHomeScreen(),
114-
},
137+
},
138+
),
115139
),
116140
);
117141
}

lib/Providers/AppProvider.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import 'package:flutter/material.dart';
2+
3+
class AppProvider extends ChangeNotifier {
4+
Locale _activeLocale;
5+
6+
static List<Locale> locales = [
7+
Locale('en', 'US'),
8+
Locale('zh', 'CN'),
9+
Locale('ar', 'SA'),
10+
];
11+
12+
Locale get activeLocale => this._activeLocale;
13+
14+
set activeLocale(Locale newLocale) {
15+
this._activeLocale = newLocale;
16+
notifyListeners();
17+
}
18+
}

lib/configs/App.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_uis/AppLocalizations.dart';
3+
4+
import 'package:flutter_uis/configs/AppDimensions.dart';
5+
import 'package:flutter_uis/configs/TextStyles.dart';
6+
7+
class App {
8+
static BuildContext ctx;
9+
10+
static init(BuildContext context) {
11+
AppDimensions.init(context);
12+
TextStyles.init();
13+
App.ctx = context;
14+
}
15+
16+
static translate(String key) {
17+
return AppLocalizations.of(App.ctx).translate(key);
18+
}
19+
}

lib/configs/TextStyles.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:flutter/material.dart';
2+
3+
import 'AppDimensions.dart';
4+
5+
abstract class TextStyles {
6+
static TextStyle heading1;
7+
static TextStyle heading2;
8+
9+
static init() {
10+
// INIT HEADINGS
11+
heading1 = TextStyle(
12+
fontSize: 20 + AppDimensions.ratio * 10,
13+
fontWeight: FontWeight.w700,
14+
);
15+
heading2 = TextStyle(
16+
fontSize: 16 + AppDimensions.ratio * 8,
17+
fontWeight: FontWeight.w600,
18+
);
19+
}
20+
}

lib/screens/AboutDeveloper/AboutDeveloper.dart

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,22 @@ class AboutDeveloperScreen extends StatelessWidget {
159159
),
160160
),
161161
),
162+
Container(
163+
decoration: BoxDecoration(),
164+
padding: EdgeInsets.only(
165+
left: AppDimensions.padding,
166+
top: AppDimensions.padding,
167+
bottom: AppDimensions.padding * 2,
168+
),
169+
child: Text(
170+
"NOTE: These contact links are not any kind of flutter helpline. I shared my contacts only for buisness related inquiries.\n\nAny help related query will not be entertain. For any help/answer follow docs or post your query on stackoverflow & community group.",
171+
style: TextStyle(
172+
fontSize: 16,
173+
color: Colors.white.withOpacity(0.5),
174+
fontWeight: FontWeight.w600,
175+
),
176+
),
177+
),
162178
Padding(
163179
padding: EdgeInsets.only(
164180
right: AppDimensions.padding,
@@ -234,7 +250,7 @@ class AboutDeveloperScreen extends StatelessWidget {
234250
top: AppDimensions.padding,
235251
),
236252
child: Text(
237-
"If you like the project and want to appreciate my effort. Then please click any of these links and perform any action you may like.",
253+
"If you like the project and want to appreciate my effort. Then click any of these links below and perform the action.",
238254
style: TextStyle(
239255
fontSize: 8 + AppDimensions.ratio * 4,
240256
// fontWeight: FontWeight.w300,

0 commit comments

Comments
 (0)