add locale to app using intl

This commit is contained in:
周强
2021-12-09 09:24:36 +08:00
parent 1a07bcd7a0
commit 13bd12cfe9
21 changed files with 1466 additions and 101 deletions

View File

@@ -5,6 +5,7 @@ import 'package:intl/intl.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/utils/utils.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
@@ -238,7 +239,7 @@ class _AlarmCardState extends TbContextState<AlarmCard> {
CircleAvatar(
radius: 16,
backgroundColor: Color(0xffF0F4F9),
child: IconButton(icon: Icon(Icons.done, size: 18), padding: EdgeInsets.all(7.0), onPressed: () => _ackAlarm(alarm))
child: IconButton(icon: Icon(Icons.done, size: 18), padding: EdgeInsets.all(7.0), onPressed: () => _ackAlarm(alarm,context))
),
if ([AlarmStatus.ACTIVE_UNACK, AlarmStatus.ACTIVE_ACK].contains(alarm.status))
Row(
@@ -247,7 +248,7 @@ class _AlarmCardState extends TbContextState<AlarmCard> {
CircleAvatar(
radius: 16,
backgroundColor: Color(0xffF0F4F9),
child: IconButton(icon: Icon(Icons.clear, size: 18), padding: EdgeInsets.all(7.0), onPressed: () => _clearAlarm(alarm))
child: IconButton(icon: Icon(Icons.clear, size: 18), padding: EdgeInsets.all(7.0), onPressed: () => _clearAlarm(alarm,context))
)
]
)
@@ -267,8 +268,8 @@ class _AlarmCardState extends TbContextState<AlarmCard> {
}
}
_clearAlarm(AlarmInfo alarm) async {
var res = await confirm(title: 'Clear Alarm', message: 'Are you sure you want to clear Alarm?', cancel: 'No', ok: 'Yes');
_clearAlarm(AlarmInfo alarm,BuildContext context) async {
var res = await confirm(title: '${S.of(context).alarmClearTitle}', message: '${S.of(context).alarmClearText}', cancel: '${S.of(context).No}', ok: '${S.of(context).Yes}');
if (res != null && res) {
setState(() {
loading = true;
@@ -283,8 +284,8 @@ class _AlarmCardState extends TbContextState<AlarmCard> {
}
}
_ackAlarm(AlarmInfo alarm) async {
var res = await confirm(title: 'Acknowledge Alarm', message: 'Are you sure you want to acknowledge Alarm?', cancel: 'No', ok: 'Yes');
_ackAlarm(AlarmInfo alarm,BuildContext context) async {
var res = await confirm(title: '${S.of(context).alarmAcknowledgeTitle}', message: '${S.of(context).alarmAcknowledgeText}', cancel: '${S.of(context).No}', ok: '${S.of(context).Yes}');
if (res != null && res) {
setState(() {
loading = true;

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/entity/entity_details_page.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
class AssetDetailsPage extends EntityDetailsPage<AssetInfo> {
@@ -24,16 +25,16 @@ class AssetDetailsPage extends EntityDetailsPage<AssetInfo> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Text('Asset name', style: labelTextStyle),
Text('${S.of(context).assetName}', style: labelTextStyle),
Text(asset.name, style: valueTextStyle),
SizedBox(height: 16),
Text('Type', style: labelTextStyle),
Text('${S.of(context).type}', style: labelTextStyle),
Text(asset.type, style: valueTextStyle),
SizedBox(height: 16),
Text('Label', style: labelTextStyle),
Text('${S.of(context).label}', style: labelTextStyle),
Text(asset.label ?? '', style: valueTextStyle),
SizedBox(height: 16),
Text('Assigned to customer', style: labelTextStyle),
Text('${S.of(context).assignedToCustomer}', style: labelTextStyle),
Text(asset.customerTitle ?? '', style: valueTextStyle),
]
)

View File

@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/modules/audit_log/audit_logs_base.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
@@ -50,7 +51,7 @@ class _AuditLogDetailsPageState extends TbContextState<AuditLogDetailsPage> {
fontSize: 16,
height: 20 / 16
)),
Text('Audit log details', style: TextStyle(
Text('${S.of(context).auditLogDetails}', style: TextStyle(
color: Theme.of(context).primaryTextTheme.headline6!.color!.withAlpha((0.38 * 255).ceil()),
fontSize: 12,
fontWeight: FontWeight.normal,
@@ -65,22 +66,22 @@ class _AuditLogDetailsPageState extends TbContextState<AuditLogDetailsPage> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Text('Entity Type', style: labelTextStyle),
Text('${S.of(context).entityType}', style: labelTextStyle),
Text(entityTypeTranslations[widget.auditLog.entityId.entityType]!, style: valueTextStyle),
SizedBox(height: 16),
Text('Type', style: labelTextStyle),
Text('${S.of(context).type}', style: labelTextStyle),
Text(actionTypeTranslations[widget.auditLog.actionType]!, style: valueTextStyle),
SizedBox(height: 16),
Flexible(
fit: FlexFit.loose,
child: buildBorderedText('Action data', encoder.convert(widget.auditLog.actionData))
child: buildBorderedText('${S.of(context).actionData}', encoder.convert(widget.auditLog.actionData))
),
if (widget.auditLog.actionStatus == ActionStatus.FAILURE)
SizedBox(height: 16),
if (widget.auditLog.actionStatus == ActionStatus.FAILURE)
Flexible(
fit: FlexFit.loose,
child: buildBorderedText('Failure details', widget.auditLog.actionFailureDetails!)
child: buildBorderedText('${S.of(context).failureDetails}', widget.auditLog.actionFailureDetails!)
)
]
),

View File

@@ -8,6 +8,7 @@ import 'package:thingsboard_app/constants/assets_path.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/utils/services/device_profile_cache.dart';
import 'package:thingsboard_app/utils/services/entity_query_api.dart';
import 'package:thingsboard_app/utils/utils.dart';
@@ -135,7 +136,7 @@ class _AllDevicesCardState extends TbContextState<AllDevicesCard> {
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('All devices',
Text('${S.of(context).allDevices}',
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14,
@@ -409,7 +410,7 @@ Widget _buildDeviceCount(BuildContext context, bool active, int count) {
],
),
SizedBox(width: 8.67),
Text(active ? 'Active' : 'Inactive', style: TextStyle(
Text(active ? '${S.of(context).active}' : '${S.of(context).inactive}', style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
height: 16 / 12,

View File

@@ -8,6 +8,7 @@ import 'package:thingsboard_app/constants/assets_path.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/utils/services/device_profile_cache.dart';
import 'package:thingsboard_app/utils/services/entity_query_api.dart';
import 'package:thingsboard_app/utils/utils.dart';
@@ -241,7 +242,7 @@ class _DeviceCardState extends TbContextState<DeviceCard> {
fontWeight: FontWeight.normal,
height: 16 / 12
)),
Text(widget.device.attribute('active') == 'true' ? 'Active' : 'Inactive',
Text(widget.device.attribute('active') == 'true' ? '${S.of(context).active}' : '${S.of(context).inactive}',
style: TextStyle(
color: widget.device.attribute('active') == 'true' ? Color(0xFF008A00) : Color(0xFFAFAFAF),
fontSize: 12,

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/modules/device/devices_base.dart';
import 'package:thingsboard_app/modules/device/devices_list.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
@@ -38,10 +39,10 @@ class _DevicesListPageState extends TbPageState<DevicesListPage> {
onSearch: (searchText) => _deviceQueryController.onSearchText(searchText),
);
} else {
String titleText = widget.deviceType != null ? widget.deviceType! : 'All devices';
String titleText = widget.deviceType != null ? widget.deviceType! : '${S.of(context).allDevices}';
String? subTitleText;
if (widget.active != null) {
subTitleText = widget.active == true ? 'Active' : 'Inactive';
subTitleText = widget.active == true ? '${S.of(context).active}' : '${S.of(context).inactive}';
}
Column title = Column(
crossAxisAlignment: CrossAxisAlignment.start,

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/modules/alarm/alarms_page.dart';
import 'package:thingsboard_app/modules/device/devices_main_page.dart';
import 'package:thingsboard_app/modules/home/home_page.dart';
@@ -11,7 +12,7 @@ import 'package:thingsboard_client/thingsboard_client.dart';
class TbMainNavigationItem {
final Widget page;
final String title;
String title;
final Icon icon;
final String path;
@@ -24,8 +25,10 @@ class TbMainNavigationItem {
static Map<Authority, Set<String>> mainPageStateMap = {
Authority.SYS_ADMIN: Set.unmodifiable(['/home', '/more']),
Authority.TENANT_ADMIN: Set.unmodifiable(['/home', '/alarms', '/devices', '/more']),
Authority.CUSTOMER_USER: Set.unmodifiable(['/home', '/alarms', '/devices', '/more']),
Authority.TENANT_ADMIN: Set.unmodifiable(
['/home', '/alarms', '/devices', '/more']),
Authority.CUSTOMER_USER: Set.unmodifiable(
['/home', '/alarms', '/devices', '/more']),
};
static bool isMainPageState(TbContext tbContext, String path) {
@@ -47,26 +50,26 @@ class TbMainNavigationItem {
path: '/home'
)
];
switch(tbContext.tbClient.getAuthUser()!.authority) {
switch (tbContext.tbClient.getAuthUser()!.authority) {
case Authority.SYS_ADMIN:
break;
case Authority.TENANT_ADMIN:
case Authority.CUSTOMER_USER:
items.addAll([
TbMainNavigationItem(
page: AlarmsPage(tbContext),
title: 'Alarms',
icon: Icon(Icons.notifications),
path: '/alarms'
),
TbMainNavigationItem(
page: DevicesMainPage(tbContext),
title: 'Devices',
icon: Icon(Icons.devices_other),
path: '/devices'
)
]);
break;
items.addAll([
TbMainNavigationItem(
page: AlarmsPage(tbContext),
title: 'Alarms',
icon: Icon(Icons.notifications),
path: '/alarms'
),
TbMainNavigationItem(
page: DevicesMainPage(tbContext),
title: 'Devices',
icon: Icon(Icons.devices_other),
path: '/devices'
)
]);
break;
case Authority.REFRESH_TOKEN:
break;
case Authority.ANONYMOUS:
@@ -83,8 +86,32 @@ class TbMainNavigationItem {
return [];
}
}
static void changeItemsTitleIntl(List<TbMainNavigationItem> items,BuildContext context) {
for(var item in items){
switch (item.path) {
case '/home':
item.title = '${S.of(context).home}';
break;
case '/alarms':
item.title = '${S.of(context).alarms}';
break;
case '/devices':
item.title = '${S.of(context).devices}';
break;
case '/more':
item.title = '${S.of(context).more}';
break;
}
}
}
}
class MainPage extends TbPageWidget {
final String _path;
@@ -132,6 +159,7 @@ class _MainPageState extends TbPageState<MainPage> with TbMainState, TickerProvi
@override
Widget build(BuildContext context) {
TbMainNavigationItem.changeItemsTitleIntl(_tabItems, context);
return WillPopScope(
onWillPop: () async {
if (_tabController.index > 0) {

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
class MorePage extends TbContextWidget {
@@ -45,7 +46,7 @@ class _MorePageState extends TbContextState<MorePage> {
)
),
SizedBox(height: 2),
Text(_getAuthorityName(),
Text(_getAuthorityName(context),
style: TextStyle(
color: Color(0xFFAFAFAF),
fontWeight: FontWeight.normal,
@@ -71,7 +72,7 @@ class _MorePageState extends TbContextState<MorePage> {
children: [
Icon(Icons.logout, color: Color(0xFFE04B2F)),
SizedBox(width: 34),
Text('Log out',
Text('${S.of(context).logout}',
style: TextStyle(
color: Color(0xFFE04B2F),
fontStyle: FontStyle.normal,
@@ -95,7 +96,7 @@ class _MorePageState extends TbContextState<MorePage> {
}
Widget buildMoreMenuItems(BuildContext context) {
List<Widget> items = MoreMenuItem.getItems(tbContext).map((menuItem) {
List<Widget> items = MoreMenuItem.getItems(tbContext,context).map((menuItem) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
child: Container(
@@ -151,20 +152,20 @@ class _MorePageState extends TbContextState<MorePage> {
return name;
}
String _getAuthorityName() {
String _getAuthorityName(BuildContext context) {
var user = tbContext.userDetails;
var name = '';
if (user != null) {
var authority = user.authority;
switch(authority) {
case Authority.SYS_ADMIN:
name = 'System Administrator';
name = '${S.of(context).systemAdministrator}';
break;
case Authority.TENANT_ADMIN:
name = 'Tenant Administrator';
name = '${S.of(context).tenantAdministrator}';
break;
case Authority.CUSTOMER_USER:
name = 'Customer';
name = '${S.of(context).customer}';
break;
}
}
@@ -184,7 +185,7 @@ class MoreMenuItem {
required this.path
});
static List<MoreMenuItem> getItems(TbContext tbContext) {
static List<MoreMenuItem> getItems(TbContext tbContext,BuildContext context) {
if (tbContext.isAuthenticated) {
List<MoreMenuItem> items = [];
switch (tbContext.tbClient.getAuthUser()!.authority) {
@@ -193,17 +194,17 @@ class MoreMenuItem {
case Authority.TENANT_ADMIN:
items.addAll([
MoreMenuItem(
title: 'Customers',
title: '${S.of(context).customers}',
icon: Icons.supervisor_account,
path: '/customers'
),
MoreMenuItem(
title: 'Assets',
title: '${S.of(context).asserts}',
icon: Icons.domain,
path: '/assets'
),
MoreMenuItem(
title: 'Audit Logs',
title: '${S.of(context).auditLogs}',
icon: Icons.track_changes,
path: '/auditLogs'
)
@@ -212,7 +213,7 @@ class MoreMenuItem {
case Authority.CUSTOMER_USER:
items.addAll([
MoreMenuItem(
title: 'Assets',
title: '${S.of(context).asserts}',
icon: Icons.domain,
path: '/assets'
)

View File

@@ -3,6 +3,7 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
import 'package:thingsboard_app/widgets/tb_progress_indicator.dart';
@@ -31,7 +32,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
backgroundColor: Colors.white,
appBar: TbAppBar(
tbContext,
title: const Text('Change Password'),
title: Text('${S.of(context).changePassword}'),
),
body: Stack(
children: [
@@ -50,11 +51,11 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
valueListenable: _showCurrentPasswordNotifier,
builder: (BuildContext context, bool showPassword, child) {
return FormBuilderTextField(
name: 'currentPassword',
name: '${S.of(context).currentPassword}',
obscureText: !showPassword,
autofocus: true,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context, errorText: 'Current password is required.')
FormBuilderValidators.required(context, errorText: '${S.of(context).currentPasswordRequireText}')
]),
decoration: InputDecoration(
suffixIcon: IconButton(
@@ -64,7 +65,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
},
),
border: OutlineInputBorder(),
labelText: 'Current password *'
labelText: '${S.of(context).currentPasswordStar}'
),
);
}
@@ -74,10 +75,10 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
valueListenable: _showNewPasswordNotifier,
builder: (BuildContext context, bool showPassword, child) {
return FormBuilderTextField(
name: 'newPassword',
name: '${S.of(context).newPassword}',
obscureText: !showPassword,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context, errorText: 'New password is required.')
FormBuilderValidators.required(context, errorText: '${S.of(context).newPasswordRequireText}')
]),
decoration: InputDecoration(
suffixIcon: IconButton(
@@ -87,7 +88,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
},
),
border: OutlineInputBorder(),
labelText: 'New password *'
labelText: '${S.of(context).newPasswordStar}'
),
);
}
@@ -97,10 +98,10 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
valueListenable: _showNewPassword2Notifier,
builder: (BuildContext context, bool showPassword, child) {
return FormBuilderTextField(
name: 'newPassword2',
name: '${S.of(context).newPassword2}',
obscureText: !showPassword,
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context, errorText: 'New password again is required.')
FormBuilderValidators.required(context, errorText: '${S.of(context).newPassword2RequireText}')
]),
decoration: InputDecoration(
suffixIcon: IconButton(
@@ -110,7 +111,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
},
),
border: OutlineInputBorder(),
labelText: 'New password again *'
labelText: '${S.of(context).newPassword2Star}'
),
);
}
@@ -122,7 +123,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
onPressed: () {
_changePassword();
},
child: Center(child: Text('Change Password'))
child: Center(child: Text('${S.of(context).changePassword}'))
)
]
),
@@ -158,7 +159,7 @@ class _ChangePasswordPageState extends TbContextState<ChangePasswordPage> {
String newPassword = formValue['newPassword'];
String newPassword2 = formValue['newPassword2'];
if (newPassword != newPassword2) {
showErrorNotification('Entered passwords must be same!');
showErrorNotification('${S.of(context).passwordErrorNotification}');
} else {
_isLoadingNotifier.value = true;
try {

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/modules/profile/change_password_page.dart';
import 'package:thingsboard_app/widgets/tb_app_bar.dart';
@@ -80,30 +81,30 @@ class _ProfilePageState extends TbPageState<ProfilePage> {
children: [
SizedBox(height: 16),
FormBuilderTextField(
name: 'email',
name: '${S.of(context).email}',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context, errorText: 'Email is required.'),
FormBuilderValidators.email(context, errorText: 'Invalid email format.')
FormBuilderValidators.required(context, errorText: '${S.of(context).emailRequireText}'),
FormBuilderValidators.email(context, errorText: '${S.of(context).emailInvalidText}')
]),
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email *'
labelText: '${S.of(context).emailStar}'
),
),
SizedBox(height: 24),
FormBuilderTextField(
name: 'firstName',
name: '${S.of(context).firstName}',
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'First Name'
labelText: '${S.of(context).firstNameUpper}'
),
),
SizedBox(height: 24),
FormBuilderTextField(
name: 'lastName',
name: '${S.of(context).lastName}',
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Last Name'
labelText: '${S.of(context).lastNameUpper}'
),
),
SizedBox(height: 24),
@@ -113,7 +114,7 @@ class _ProfilePageState extends TbPageState<ProfilePage> {
onPressed: () {
_changePassword();
},
child: Center(child: Text('Change Password'))
child: Center(child: Text('${S.of(context).changePassword}'))
)
]
),
@@ -170,7 +171,7 @@ class _ProfilePageState extends TbPageState<ProfilePage> {
_setUser();
await Future.delayed(Duration(milliseconds: 300));
_isLoadingNotifier.value = false;
showSuccessNotification('Profile successfully updated', duration: Duration(milliseconds: 1500));
showSuccessNotification('${S.of(context).profileSuccessNotification}', duration: Duration(milliseconds: 1500));
}
}
}
@@ -178,7 +179,7 @@ class _ProfilePageState extends TbPageState<ProfilePage> {
_changePassword() async {
var res = await tbContext.showFullScreenDialog<bool>(new ChangePasswordPage(tbContext));
if (res == true) {
showSuccessNotification('Password successfully changed', duration: Duration(milliseconds: 1500));
showSuccessNotification('${S.of(context).passwordSuccessNotification}', duration: Duration(milliseconds: 1500));
}
}
}