Skip to content

Commit

Permalink
Add preferences page and select language function
Browse files Browse the repository at this point in the history
  • Loading branch information
yungwenpeng committed Nov 30, 2022
1 parent 0b188b0 commit 875a138
Show file tree
Hide file tree
Showing 23 changed files with 546 additions and 96 deletions.
Binary file modified flutter_with_localapi_example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"drawerDevice": "Device",
"drawerDashboard": "Dashboard",
"drawerLogout": "Logout",
"drawerPreferences": "Preferences",
"alertDialogConfirm": "Ok",
"usersFloatActionViewModule": "Change view module",
"usersFloatActionAddUser": "Add new account",
Expand All @@ -32,5 +33,6 @@
"usersDataTableHeaderAuthority": "Authority",
"usersDataTableSearchbyName": "Search by name",
"usersDataTableSearchbyEmail": "Search by SW email",
"usersDataTableSearchbyAuthority": "Search by Authority"
"usersDataTableSearchbyAuthority": "Search by Authority",
"preferencesSelectLanguage": "Select Language :"
}
4 changes: 3 additions & 1 deletion lib/l10n/app_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"drawerDevice": "設備",
"drawerDashboard": "儀表版",
"drawerLogout": "登出",
"drawerPreferences": "偏好設定",
"alertDialogConfirm": "確定",
"usersFloatActionViewModule": "切換模式",
"usersFloatActionAddUser": "新增使用者帳號",
Expand All @@ -32,5 +33,6 @@
"usersDataTableHeaderAuthority": "權限",
"usersDataTableSearchbyName": "按姓名搜尋",
"usersDataTableSearchbyEmail": "按電子信箱搜尋",
"usersDataTableSearchbyAuthority": "按權限搜尋"
"usersDataTableSearchbyAuthority": "按權限搜尋",
"preferencesSelectLanguage": "選擇語言 :"
}
28 changes: 28 additions & 0 deletions lib/l10n/l10n.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';

class L10n {
static final all = [
const Locale('en'),
const Locale('zh'),
];
static String getName(String code) {
switch (code) {
case 'zh':
return '繁體中文';
case 'en':
default:
return 'English';
}
}

static String getCountryFlag(String code) {
// See https://en.wikipedia.org/wiki/Regional_indicator_symbol
switch (code) {
case 'zh':
return 'TW';
case 'en':
default:
return 'US';
}
}
}
35 changes: 35 additions & 0 deletions lib/localization/app_translations.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:shared_preferences/shared_preferences.dart';

class AppTranslations {
Locale locale;
static Map<dynamic, dynamic>? _localisedValues;

AppTranslations(this.locale);

static AppTranslations? of(BuildContext context) {
return Localizations.of<AppTranslations>(context, AppTranslations);
}

static Future<AppTranslations> load(Locale locale) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var languageCode = prefs.getString('languageCode');
if (languageCode != null) {
locale = Locale(languageCode);
}
AppTranslations appTranslations = AppTranslations(locale);
String jsonContent =
await rootBundle.loadString("lib/l10n/app_${locale.languageCode}.arb");
_localisedValues = json.decode(jsonContent);
return appTranslations;
}

get currentLanguage => locale.languageCode;

String text(String key) {
return _localisedValues![key] ?? "$key not found";
}
}
25 changes: 25 additions & 0 deletions lib/localization/app_translations_delegate.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'app_translations.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class AppTranslationsDelegate extends LocalizationsDelegate<AppTranslations> {
final Locale newLocale;

const AppTranslationsDelegate({required this.newLocale});

@override
bool isSupported(Locale locale) {
return AppLocalizations.supportedLocales.contains(locale);
}

@override
Future<AppTranslations> load(Locale locale) {
return AppTranslations.load(newLocale);
}

@override
bool shouldReload(LocalizationsDelegate<AppTranslations> old) {
return true;
}
}
18 changes: 18 additions & 0 deletions lib/localization/application.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'dart:ui';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class Application {
static final Application _application = Application._internal();

factory Application() => _application;

Application._internal();

//returns the list of supported Locales
Iterable<Locale> supportedLocales() => AppLocalizations.supportedLocales;
late LocaleChangeCallback onLocaleChanged;
}

Application application = Application();

typedef LocaleChangeCallback = void Function(Locale locale);
3 changes: 3 additions & 0 deletions lib/localization/localization.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'application.dart';
export 'app_translations.dart';
export 'app_translations_delegate.dart';
20 changes: 18 additions & 2 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:provider/provider.dart';
import 'package:url_strategy/url_strategy.dart';

import 'localization/localization.dart';
import 'models/models.dart';
import 'pages/pages.dart';
import 'route/route.dart';

Future<void> main() async {
Expand All @@ -26,12 +27,15 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> {
late MyAppRouterDelegate delegate;
late MyAppRouteInformationParser parser;
late AppTranslationsDelegate _newLocaleDelegate;

@override
void initState() {
super.initState();
delegate = MyAppRouterDelegate();
parser = MyAppRouteInformationParser();
_newLocaleDelegate = const AppTranslationsDelegate(newLocale: Locale("en"));
application.onLocaleChanged = onLocaleChange;
}

// This widget is the root of your application.
Expand All @@ -56,9 +60,21 @@ class _MyAppState extends State<MyApp> {
routerDelegate: delegate,
routeInformationParser: parser,
backButtonDispatcher: RootBackButtonDispatcher(),
localizationsDelegates: AppLocalizations.localizationsDelegates,
localizationsDelegates: [
_newLocaleDelegate,
//provides localised strings
GlobalMaterialLocalizations.delegate,
//provides RTL support
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
),
);
}

void onLocaleChange(Locale locale) {
setState(() {
_newLocaleDelegate = AppTranslationsDelegate(newLocale: locale);
});
}
}
37 changes: 35 additions & 2 deletions lib/models/pages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ class LoginPage extends Page {
class HomePage extends Page {
final VoidCallback onLogout;
final VoidCallback onUserList;
const HomePage({required this.onLogout, required this.onUserList})
final VoidCallback onPreferences;
const HomePage(
{required this.onLogout,
required this.onUserList,
required this.onPreferences})
: super(key: const ValueKey('HomePage'));

@override
Expand All @@ -40,6 +44,7 @@ class HomePage extends Page {
builder: (BuildContext context) => MyHomePage(
onLogout: onLogout,
onUserList: onUserList,
onPreferences: onPreferences,
),
);
}
Expand All @@ -48,7 +53,11 @@ class HomePage extends Page {
class UserListPage extends Page {
final VoidCallback onLogout;
final VoidCallback onUserList;
const UserListPage({required this.onLogout, required this.onUserList})
final VoidCallback onPreferences;
const UserListPage(
{required this.onLogout,
required this.onUserList,
required this.onPreferences})
: super(key: const ValueKey('UserListPage'));

@override
Expand All @@ -58,6 +67,30 @@ class UserListPage extends Page {
builder: (BuildContext context) => UserList(
onLogout: onLogout,
onUserList: onUserList,
onPreferences: onPreferences,
),
);
}
}

class PreferencesPage extends Page {
final VoidCallback onLogout;
final VoidCallback onUserList;
final VoidCallback onPreferences;
const PreferencesPage(
{required this.onLogout,
required this.onUserList,
required this.onPreferences})
: super(key: const ValueKey('PreferencesPage'));

@override
Route createRoute(BuildContext context) {
return MaterialPageRoute(
settings: this,
builder: (BuildContext context) => MyPreferences(
onLogout: onLogout,
onUserList: onUserList,
onPreferences: onPreferences,
),
);
}
Expand Down
36 changes: 26 additions & 10 deletions lib/pages/drawer.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../localization/localization.dart';
import '../models/models.dart';
import '../route/route.dart';
import 'pages.dart';

enum DrawerIDs { home, users, devices, dashboard, logout }
enum DrawerIDs { home, users, devices, dashboard, logout, preferences }

class MyDrawer extends StatefulWidget {
final VoidCallback onLogout;
final VoidCallback onUserList;
final VoidCallback onPreferences;
const MyDrawer({
super.key,
required this.onLogout,
required this.onUserList,
required this.onPreferences,
});

@override
Expand Down Expand Up @@ -98,6 +100,10 @@ class _MyDrawerState extends State<MyDrawer> {
},
)));
break;
case 5:
widget.onPreferences();
MyAppRouterDelegate().loggedIn = true;
break;
}
}

Expand All @@ -112,16 +118,26 @@ class _MyDrawerState extends State<MyDrawer> {
),
));
drawerList.add(const Divider(height: 2, thickness: 2, color: Colors.white));
drawerList.add(buildListTile(AppLocalizations.of(context)!.drawerHome,
DrawerIDs.home.index, Icons.home));
drawerList.add(buildListTile(AppLocalizations.of(context)!.drawerUsers,
DrawerIDs.users.index, Icons.people));
/*drawerList.add(buildListTile(AppLocalizations.of(context)!.drawerDevice,
drawerList.add(buildListTile(
AppTranslations.of(context)!.text('drawerHome'),
DrawerIDs.home.index,
Icons.home));
drawerList.add(buildListTile(
AppTranslations.of(context)!.text('drawerUsers'),
DrawerIDs.users.index,
Icons.people));
/*drawerList.add(buildListTile(AppTranslations.of(context)!.text('drawerDevice'),
DrawerIDs.devices.index, Icons.devices));
drawerList.add(buildListTile(AppLocalizations.of(context)!.drawerDashboard,
drawerList.add(buildListTile(AppTranslations.of(context)!.text('drawerDashboard'),
DrawerIDs.dashboard.index, Icons.dashboard));*/
drawerList.add(buildListTile(AppLocalizations.of(context)!.drawerLogout,
DrawerIDs.logout.index, Icons.logout));
drawerList.add(buildListTile(
AppTranslations.of(context)!.text('drawerLogout'),
DrawerIDs.logout.index,
Icons.logout));
drawerList.add(buildListTile(
AppTranslations.of(context)!.text('drawerPreferences'),
DrawerIDs.preferences.index,
Icons.settings));
}

Widget buildListTile(String title, int index, IconData iconName) {
Expand Down
6 changes: 4 additions & 2 deletions lib/pages/expandable_fab.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../localization/localization.dart';

class ExpandableFab extends StatefulWidget {
const ExpandableFab({
Expand Down Expand Up @@ -134,7 +135,8 @@ class _ExpandableFabState extends State<ExpandableFab>
child: FloatingActionButton(
onPressed: _toggle,
heroTag: "viewModule",
tooltip: AppLocalizations.of(context)!.usersFloatActionViewModule,
tooltip:
AppTranslations.of(context)!.text('usersFloatActionViewModule'),
elevation: 0.0,
backgroundColor: const Color.fromARGB(255, 102, 168, 223),
hoverColor: Colors.orange,
Expand Down
Loading

0 comments on commit 875a138

Please sign in to comment.