Commit 89cbb8990f45433ef052c2efe6f86399064b6b52

Authored by 权海
1 parent d1a92435

feat(ui):watch_theme 国际化

Showing 25 changed files with 997 additions and 160 deletions
... ... @@ -12,6 +12,7 @@ import 'package:get/get.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../models/watch_theme_models.dart';
import '../widgets/watch_theme_dialogs.dart';
... ... @@ -26,7 +27,7 @@ class CreateWatchThemeController extends GetxController {
final customThemeName = ''.obs;
final agreedToSubmission = true.obs;
final customStatusNames = ['状态优秀', '状态正常', '注意压力', '压力过载'].obs;
late final RxList<String> customStatusNames;
final customImagePaths = RxList<String?>.filled(4, null);
final isRemovingBackground = RxList<bool>.filled(4, false);
final isSaving = false.obs;
... ... @@ -38,6 +39,12 @@ class CreateWatchThemeController extends GetxController {
@override
void onInit() {
super.onInit();
customStatusNames = [
l10n.watchThemeExcellent,
l10n.watchThemeNormal,
l10n.watchThemeSlightStressful,
l10n.watchThemeStressful,
].obs;
themeNameController = TextEditingController();
themeNameController.addListener(() {
customThemeName.value = themeNameController.text.trim();
... ... @@ -78,11 +85,11 @@ class CreateWatchThemeController extends GetxController {
compressQuality: 100,
uiSettings: [
AndroidUiSettings(
toolbarTitle: '裁剪表盘图片',
toolbarTitle: l10n.watchThemeCropImage,
lockAspectRatio: true,
),
IOSUiSettings(
title: '裁剪表盘图片',
title: l10n.watchThemeCropImage,
aspectRatioLockEnabled: true,
resetAspectRatioEnabled: false,
),
... ... @@ -102,7 +109,7 @@ class CreateWatchThemeController extends GetxController {
// 此处不等待结果,让裁切图先显示;处理完成后再原位替换。
unawaited(_removeBackgroundAndReplace(index, savedPath, taskVersion));
} catch (_) {
AppToast.show('图片处理失败,请重试');
AppToast.show(l10n.watchThemeImageProcessFailed);
}
}
... ... @@ -209,11 +216,11 @@ class CreateWatchThemeController extends GetxController {
return;
}
final abandon = await Get.dialog<bool>(
const WatchThemeConfirmDialog(
title: '放弃编辑',
message: '关闭此页面后,已编辑的内容不会保留,是否放弃编辑?',
primaryText: '放弃编辑',
secondaryText: '继续编辑',
WatchThemeConfirmDialog(
title: l10n.watchThemeAbandonEdit,
message: l10n.watchThemeAbandonMessage,
primaryText: l10n.watchThemeAbandonEdit,
secondaryText: l10n.watchThemeContinueEditing,
),
barrierDismissible: true,
);
... ... @@ -241,7 +248,7 @@ class CreateWatchThemeController extends GetxController {
HResourceType.image,
);
if (imageUrl == null || imageUrl.isEmpty) {
AppToast.show('图片上传失败,请重试');
AppToast.show(l10n.watchThemeImageUploadFailed);
return;
}
uploadedImageUrls.add(imageUrl);
... ... @@ -275,7 +282,7 @@ class CreateWatchThemeController extends GetxController {
);
return;
} catch (_) {
AppToast.show('创建表盘失败,请重试');
AppToast.show(l10n.watchThemeCreateFailed);
} finally {
isSaving.value = false;
}
... ...
... ... @@ -10,6 +10,7 @@ import 'package:doublefeel_flutter/pigeon/platform_api.g.dart';
import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../../friends/models/friend_health_data.dart';
import '../../friends/views/select_friend_view.dart';
... ... @@ -95,11 +96,11 @@ class CustomWatchThemePreviewController extends GetxController {
Future<void> confirmDeleteCustomTheme() async {
final shouldDelete = await Get.dialog<bool>(
const WatchThemeConfirmDialog(
title: '删除主题',
message: '主题删除后无法恢复,确认删除该主题吗?',
primaryText: '删除',
secondaryText: '取消',
WatchThemeConfirmDialog(
title: l10n.watchThemeDeleteTheme,
message: l10n.watchThemeDeleteMessage,
primaryText: l10n.watchThemeDelete,
secondaryText: l10n.watchThemeCancel,
),
barrierDismissible: true,
);
... ... @@ -113,10 +114,10 @@ class CustomWatchThemePreviewController extends GetxController {
final result = await _themeApi.deleteTheme(themeId);
isDeleting.value = false;
if (result is! AppSuccess<void>) {
AppToast.show('删除主题失败');
AppToast.show(l10n.watchThemeDeleteFailed);
return;
}
AppToast.show('已删除主题');
AppToast.show(l10n.watchThemeDeleted);
Get.back();
}
}
... ... @@ -188,7 +189,7 @@ class CustomWatchThemePreviewController extends GetxController {
Future<bool> applyAndSyncWatchFace() async {
final themeId = themeItem.id;
if (themeId == null) {
AppToast.show('主题信息不完整');
AppToast.show(l10n.watchThemeIncomplete);
return false;
}
... ... @@ -196,7 +197,7 @@ class CustomWatchThemePreviewController extends GetxController {
final result = await _themeApi.applyTheme(themeId);
if (result is! AppSuccess<void>) {
isApplying.value = false;
AppToast.show('应用主题失败');
AppToast.show(l10n.watchThemeApplyFailed);
return false;
}
... ... @@ -213,7 +214,7 @@ class CustomWatchThemePreviewController extends GetxController {
}
isApplying.value = false;
if (!syncSuccess) {
AppToast.show('表盘同步失败');
AppToast.show(l10n.watchThemeWatchSyncFailed);
}
return syncSuccess;
}
... ...
... ... @@ -8,6 +8,7 @@ import 'package:doublefeel_flutter/core/result/app_result.dart';
import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart';
import 'package:doublefeel_flutter/data/models/local/user_preferences.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../models/watch_theme_models.dart';
... ... @@ -86,13 +87,15 @@ class WatchThemeController extends GetxController {
final vipPrefs = UserPreferencesVipInfo.fromVipInfo(vip);
await Get.find<UserPreferencesStorage>().updateVipInfo(vipPrefs);
isPremium.value = vipPrefs.isVip;
} on Exception catch (e) {}
} on Exception catch (_) {
// Keep the current membership state when local persistence fails.
}
}
}
Future<void> _toPremiumPage() async {
await Get.toNamed(Routes.PURCHASE, arguments: {
IntentKeys.channelType: '表盘主题',
IntentKeys.channelType: l10n.watchThemePurchaseChannel,
});
await _refreshVip();
}
... ...
... ... @@ -10,6 +10,7 @@ import 'package:doublefeel_flutter/pigeon/platform_api.g.dart';
import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../../friends/models/friend_health_data.dart';
import '../../friends/views/select_friend_view.dart';
... ... @@ -160,7 +161,7 @@ class WatchThemePreviewController extends GetxController {
Future<bool> applyAndSyncWatchFace() async {
final themeId = themeItem.id;
if (themeId == null) {
AppToast.show('主题信息不完整');
AppToast.show(l10n.watchThemeIncomplete);
return false;
}
... ... @@ -168,7 +169,7 @@ class WatchThemePreviewController extends GetxController {
final result = await _themeApi.applyTheme(themeId);
if (result is! AppSuccess<void>) {
isApplying.value = false;
AppToast.show('应用主题失败');
AppToast.show(l10n.watchThemeApplyFailed);
return false;
}
... ... @@ -185,7 +186,7 @@ class WatchThemePreviewController extends GetxController {
}
isApplying.value = false;
if (!syncSuccess) {
AppToast.show('表盘同步失败');
AppToast.show(l10n.watchThemeWatchSyncFailed);
}
return syncSuccess;
}
... ...
import 'dart:ui';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../widgets/watch_theme_colors.dart';
class WatchThemeItem {
... ... @@ -46,18 +48,24 @@ class WatchThemeItem {
id: _intFromJson(json['id']),
userId: _intFromJson(json['user_id']),
status: _intFromJson(json['status']),
themeName: _stringFromJson(json['theme_name'], '自定义主题'),
energeticDescription:
_stringFromJson(json['energetic_description'], '状态优秀'),
themeName: _stringFromJson(
json['theme_name'],
l10n.watchThemeCustomTheme,
),
energeticDescription: _stringFromJson(
json['energetic_description'], l10n.watchThemeExcellent),
energeticImage: _nullableStringFromJson(json['energetic_image']),
normalDescription: _stringFromJson(json['normal_description'], '状态正常'),
normalDescription:
_stringFromJson(json['normal_description'], l10n.watchThemeNormal),
normalImage: _nullableStringFromJson(json['normal_image']),
slightStressfulDescription:
_stringFromJson(json['slight_stressful_description'], '注意压力'),
slightStressfulDescription: _stringFromJson(
json['slight_stressful_description'],
l10n.watchThemeSlightStressful,
),
slightStressfulImage:
_nullableStringFromJson(json['slight_stressful_image']),
stressfulDescription:
_stringFromJson(json['stressful_description'], '压力过载'),
stressfulDescription: _stringFromJson(
json['stressful_description'], l10n.watchThemeStressful),
stressfulImage: _nullableStringFromJson(json['stressful_image']),
isOfficial: _intFromJson(json['is_official']) ?? 0,
isDefaultTheme: _intFromJson(json['is_default_theme']) ?? 0,
... ... @@ -117,12 +125,12 @@ class WatchThemeItem {
];
static WatchThemeItem empty() {
return const WatchThemeItem(
themeName: '自定义主题',
energeticDescription: '状态优秀',
normalDescription: '状态正常',
slightStressfulDescription: '注意压力',
stressfulDescription: '压力过载',
return WatchThemeItem(
themeName: l10n.watchThemeCustomTheme,
energeticDescription: l10n.watchThemeExcellent,
normalDescription: l10n.watchThemeNormal,
slightStressfulDescription: l10n.watchThemeSlightStressful,
stressfulDescription: l10n.watchThemeStressful,
);
}
... ... @@ -226,12 +234,24 @@ class WatchThemeUpsertRequest {
}
}
final defaultThemeTemplates = [
WatchThemeTemplateItem(title: '状态优秀', color: WatchThemeColors.excellent),
WatchThemeTemplateItem(title: '状态正常', color: WatchThemeColors.normal),
WatchThemeTemplateItem(title: '注意压力', color: WatchThemeColors.stress),
WatchThemeTemplateItem(title: '压力过载', color: WatchThemeColors.overload),
];
List<WatchThemeTemplateItem> get defaultThemeTemplates => [
WatchThemeTemplateItem(
title: l10n.watchThemeExcellent,
color: WatchThemeColors.excellent,
),
WatchThemeTemplateItem(
title: l10n.watchThemeNormal,
color: WatchThemeColors.normal,
),
WatchThemeTemplateItem(
title: l10n.watchThemeSlightStressful,
color: WatchThemeColors.stress,
),
WatchThemeTemplateItem(
title: l10n.watchThemeStressful,
color: WatchThemeColors.overload,
),
];
class WatchThemeTemplateItem {
WatchThemeTemplateItem({required this.title, required this.color});
... ...
... ... @@ -2,6 +2,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../controllers/create_watch_theme_controller.dart';
import '../widgets/watch_face_preview.dart';
... ... @@ -22,7 +23,7 @@ class CreateWatchThemeView extends GetView<CreateWatchThemeController> {
}
},
child: WatchThemeGradientScaffold(
title: '创作主题',
title: context.l10n.watchThemeCreateTheme,
onBack: controller.handleCreateBack,
body: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
... ... @@ -74,7 +75,7 @@ class _EditorCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'自定义主题',
context.l10n.watchThemeCustomTheme,
style: TextStyle(
color: WatchThemeColors.textPrimary,
fontSize: 16,
... ... @@ -83,7 +84,7 @@ class _EditorCard extends StatelessWidget {
),
SizedBox(height: 4),
Text(
'仅支持上传图片',
context.l10n.watchThemeImagesOnly,
style: TextStyle(
color: WatchThemeColors.textSecondary,
fontSize: 12,
... ... @@ -116,7 +117,7 @@ class _EditorCard extends StatelessWidget {
),
SizedBox(height: 14),
Text(
'主题名称',
context.l10n.watchThemeName,
style: TextStyle(
color: WatchThemeColors.textPrimary,
fontSize: 16,
... ... @@ -137,7 +138,7 @@ class _EditorCard extends StatelessWidget {
maxLength: 10,
decoration: InputDecoration(
counterText: '',
hintText: '最多10个字符',
hintText: context.l10n.watchThemeNameMaxLength,
hintStyle: TextStyle(
color: WatchThemeColors.textTertiary,
fontSize: 14,
... ... @@ -251,7 +252,7 @@ class _AgreementRow extends StatelessWidget {
),
SizedBox(width: 4),
Text(
'我已阅读并同意用户投稿协议',
context.l10n.watchThemeSubmissionAgreement,
style: TextStyle(
color: WatchThemeColors.textSecondary,
fontSize: 12,
... ... @@ -287,7 +288,9 @@ class _SaveButton extends StatelessWidget {
borderRadius: BorderRadius.circular(24),
),
child: Text(
controller.isSaving.value ? '保存中' : '保存主题',
controller.isSaving.value
? context.l10n.watchThemeSaving
: context.l10n.watchThemeSaveTheme,
style: TextStyle(
color: Colors.white,
fontSize: 16,
... ...
import 'package:doublefeel_flutter/app/modules/watch_theme/widgets/dial_preview_card.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../controllers/custom_watch_theme_preview_controller.dart';
import '../widgets/status_preview_card.dart';
... ... @@ -16,13 +17,13 @@ class CustomWatchThemePreviewView
Widget build(BuildContext context) {
final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight;
return WatchThemeGradientScaffold(
title: '预览',
title: context.l10n.watchThemePreview,
onBack: controller.executeBackLogic,
trailing: GestureDetector(
onTap: controller.confirmDeleteCustomTheme,
child: const Text(
'删除',
style: TextStyle(
child: Text(
context.l10n.watchThemeDelete,
style: const TextStyle(
color: Color(0xFFFC4447),
fontSize: 14,
fontWeight: FontWeight.w600,
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../controllers/watch_theme_preview_controller.dart';
import '../widgets/dial_preview_card.dart';
... ... @@ -15,7 +16,7 @@ class WatchThemePreviewView extends GetView<WatchThemePreviewController> {
Widget build(BuildContext context) {
final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight;
return WatchThemeGradientScaffold(
title: '预览',
title: context.l10n.watchThemePreview,
onBack: controller.executeBackLogic,
body: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../controllers/watch_theme_controller.dart';
import '../widgets/custom_theme_card.dart';
... ... @@ -14,7 +15,7 @@ class WatchThemeView extends GetView<WatchThemeController> {
Widget build(BuildContext context) {
final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight;
return WatchThemeGradientScaffold(
title: 'Watch主题',
title: context.l10n.watchThemePageTitle,
onBack: controller.executeBackLogic,
body: Obx(
() => SingleChildScrollView(
... ...
import 'package:flutter/material.dart';
import 'package:get/utils.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../models/watch_theme_models.dart';
import 'watch_theme_character_avatar.dart';
... ... @@ -31,12 +32,12 @@ class CustomThemeCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
WatchThemeSectionTitle(
'自定义主题',
context.l10n.watchThemeCustomTheme,
trailing: isPremium ? null : const WatchThemeProBadge(),
),
SizedBox(height: 4),
Text(
'用创意记录每一次情绪波动,打造懂你的专属表盘吧~',
context.l10n.watchThemeCustomDescription,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
... ... @@ -57,12 +58,12 @@ class CustomThemeCard extends StatelessWidget {
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return _CustomThemeItem(
item: customThemes[index],
selected: customThemes[index].id != null &&
customThemes[index].id == activeThemeId,
onTap: onThemeTap == null
? null
: () => onThemeTap!(customThemes[index]),
item: customThemes[index],
selected: customThemes[index].id != null &&
customThemes[index].id == activeThemeId,
onTap: onThemeTap == null
? null
: () => onThemeTap!(customThemes[index]),
);
},
separatorBuilder: (context, index) {
... ... @@ -114,7 +115,7 @@ class _CreateThemeButton extends StatelessWidget {
),
SizedBox(width: 8),
Text(
'创作主题',
context.l10n.watchThemeCreateTheme,
style: TextStyle(
color: WatchThemeColors.textPrimary,
fontSize: 14,
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'watch_face_preview.dart';
import 'watch_theme_section_card.dart';
class DialPreviewCard extends StatelessWidget {
bool showFriend;
final bool showFriend;
final String? themeImageUrl;
final String? themeImageUrl2;
final Function()? switchFriend;
DialPreviewCard(
const DialPreviewCard(
{super.key,
required this.showFriend,
this.themeImageUrl,
... ... @@ -24,7 +24,8 @@ class DialPreviewCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const WatchThemeSectionTitle('表盘预览').paddingOnly(left: 20),
WatchThemeSectionTitle(context.l10n.watchThemeDialPreview)
.paddingOnly(left: 20),
SizedBox(height: 16),
SizedBox(
height: showFriend ? 172 : 136,
... ...
import 'package:flutter/material.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import '../models/watch_theme_models.dart';
import 'watch_theme_character_avatar.dart';
... ... @@ -24,58 +25,58 @@ class OfficialThemeGrid extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const WatchThemeSectionTitle('官方主题'),
WatchThemeSectionTitle(context.l10n.watchThemeOfficialTheme),
SizedBox(height: 22),
themes.isEmpty
? SizedBox(
height: 114,
)
:
GridView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
itemCount: themes.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 21,
crossAxisSpacing: 19,
mainAxisExtent: 114,
),
itemBuilder: (context, index) {
final theme = themes[index];
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => onThemeTap(index),
child: Column(
children: [
WatchThemeSelectedView(
selected: theme.id != null && theme.id == activeThemeId,
size: 88,
child: WatchThemeCharacterAvatar(
size: 88,
assetPath: theme.infoList.firstOrNull?.assetPath,
imageUrl: theme.infoList.firstOrNull?.imgUrl,
: GridView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
itemCount: themes.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 21,
crossAxisSpacing: 19,
mainAxisExtent: 114,
),
itemBuilder: (context, index) {
final theme = themes[index];
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => onThemeTap(index),
child: Column(
children: [
WatchThemeSelectedView(
selected:
theme.id != null && theme.id == activeThemeId,
size: 88,
child: WatchThemeCharacterAvatar(
size: 88,
assetPath: theme.infoList.firstOrNull?.assetPath,
imageUrl: theme.infoList.firstOrNull?.imgUrl,
),
),
SizedBox(height: 8),
Text(
theme.title,
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: WatchThemeColors.textPrimary,
fontSize: 12,
fontWeight: FontWeight.w400,
height: 1.25,
),
),
],
),
),
SizedBox(height: 8),
Text(
theme.title,
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: WatchThemeColors.textPrimary,
fontSize: 12,
fontWeight: FontWeight.w400,
height: 1.25,
),
),
],
);
},
),
);
},
),
],
),
);
... ...
import 'package:doublefeel_flutter/app/modules/watch_theme/models/watch_theme_models.dart';
import 'package:flutter/material.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'watch_theme_character_avatar.dart';
import 'watch_theme_section_card.dart';
... ... @@ -15,7 +16,7 @@ class StatusPreviewCard extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const WatchThemeSectionTitle('状态预览'),
WatchThemeSectionTitle(context.l10n.watchThemeStatusPreview),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
... ...
... ... @@ -3,6 +3,7 @@ import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
enum WatchFacePreviewType {
surface,
... ... @@ -64,17 +65,17 @@ class WatchFacePreview extends StatelessWidget {
children: [
Stack(
alignment: Alignment.topCenter,
clipBehavior: Clip.none,
children: [
Image(
image: AssetImage(_backgroundAsset),
width: size.width,
height: size.height,
fit: BoxFit.fitWidth,
clipBehavior: Clip.none,
children: [
Image(
image: AssetImage(_backgroundAsset),
width: size.width,
height: size.height,
fit: BoxFit.fitWidth,
),
_buildThemeImages(),
],
),
_buildThemeImages(),
],
),
type == WatchFacePreviewType.coupleSmall
? GestureDetector(
onTap: switchFriend,
... ... @@ -86,7 +87,7 @@ class WatchFacePreview extends StatelessWidget {
border: Border.all(width: 1, color: Color(0xFFC3ADFF)),
borderRadius: BorderRadius.all(Radius.circular(12))),
child: Text(
'切换好友',
context.l10n.watchThemeSwitchFriend,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
... ... @@ -143,7 +144,7 @@ class WatchFacePreview extends StatelessWidget {
height: themeSize.height,
child: _buildFaceImage(themeImageUrl,
'assets/images/watch_theme/official_default_green.png'),
),
),
SizedBox(
width: 12,
),
... ...
import 'package:flutter/material.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'watch_theme_colors.dart';
... ... @@ -26,7 +26,7 @@ class WatchThemeBottomActions extends StatelessWidget {
children: [
Expanded(
child: _ActionButton(
label: '添加表盘',
label: context.l10n.watchThemeAddWatchFace,
color: WatchThemeColors.brand,
textColor: Colors.white,
onTap: onAddTap,
... ... @@ -35,7 +35,9 @@ class WatchThemeBottomActions extends StatelessWidget {
SizedBox(width: 12),
Expanded(
child: _ActionButton(
label: isInUsage ? '正在使用' : '立即使用',
label: isInUsage
? context.l10n.watchThemeInUse
: context.l10n.watchThemeUseNow,
color: isInUsage
? WatchThemeColors.brand.withValues(alpha: 0.4)
: WatchThemeColors.brand,
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
class WatchThemeRenameDialog extends StatefulWidget {
const WatchThemeRenameDialog({super.key, required this.initialValue});
... ... @@ -40,9 +41,9 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
'修改状态名称',
style: TextStyle(
Text(
context.l10n.watchThemeRenameStatus,
style: const TextStyle(
color: Color(0xFF141414),
fontSize: 18,
fontWeight: FontWeight.w600,
... ... @@ -66,10 +67,11 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> {
child: TextField(
controller: _controller,
maxLength: 4,
decoration: const InputDecoration(
decoration: InputDecoration(
counterText: '',
hintText: '请输入昵称',
hintStyle: TextStyle(color: Color(0xFFB0B0B6)),
hintText: context.l10n.watchThemeEnterNickname,
hintStyle:
const TextStyle(color: Color(0xFFB0B0B6)),
border: InputBorder.none,
isCollapsed: true,
),
... ... @@ -105,9 +107,9 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> {
color: const Color(0xFF845EEE),
borderRadius: BorderRadius.circular(24),
),
child: const Text(
'保存',
style: TextStyle(
child: Text(
context.l10n.watchThemeSave,
style: const TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.w500,
... ...
import 'package:doublefeel_flutter/core/util/size_extensions.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'watch_theme_colors.dart';
... ... @@ -37,7 +38,7 @@ class WatchThemeFriendPickerDialog extends StatelessWidget {
alignment: Alignment.center,
children: [
Text(
'选择好友',
context.l10n.watchThemeSelectFriend,
style: TextStyle(
color: WatchThemeColors.textPrimary,
fontSize: 16.dp,
... ... @@ -90,7 +91,7 @@ class WatchThemeFriendPickerDialog extends StatelessWidget {
borderRadius: BorderRadius.circular(24.dp),
),
child: Text(
'选择并同步至表盘',
context.l10n.watchThemeSelectAndSync,
style: TextStyle(
color: Colors.white,
fontSize: 16.dp,
... ...
import 'package:flutter/material.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'watch_face_preview.dart';
import 'watch_theme_colors.dart';
... ... @@ -6,11 +7,11 @@ import 'watch_theme_colors.dart';
class WatchThemeHeader extends StatelessWidget {
const WatchThemeHeader({
super.key,
this.title = '默认主题',
this.title,
this.themeImageUrl,
});
final String title;
final String? title;
final String? themeImageUrl;
@override
... ... @@ -26,7 +27,7 @@ class WatchThemeHeader extends StatelessWidget {
),
SizedBox(height: 12),
Text(
title,
title ?? context.l10n.watchThemeDefaultTheme,
style: TextStyle(
color: WatchThemeColors.textPrimary,
fontSize: 20,
... ...
import 'package:doublefeel_flutter/core/util/size_extensions.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'watch_theme_colors.dart';
... ... @@ -23,7 +24,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
Text(
'未找到苹果手表',
context.l10n.watchThemeNoWatchTitle,
textAlign: TextAlign.center,
style: TextStyle(
color: const Color(0xFF141414),
... ... @@ -33,7 +34,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget {
),
SizedBox(height: 16.dp),
Text(
'请配对苹果手表后再尝试',
context.l10n.watchThemeNoWatchMessage,
textAlign: TextAlign.center,
style: TextStyle(
color: const Color(0xFF6E6D80),
... ... @@ -53,7 +54,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget {
borderRadius: BorderRadius.circular(24.dp),
),
child: Text(
'好的',
context.l10n.watchThemeOk,
style: TextStyle(
color: Colors.white,
fontSize: 14.dp,
... ...
import 'package:doublefeel_flutter/core/util/size_extensions.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'watch_face_preview.dart';
import 'watch_theme_colors.dart';
... ... @@ -104,7 +105,7 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> {
_WatchThemeSyncState.intro => Padding(
padding: EdgeInsets.symmetric(horizontal: 46.dp),
child: Text(
'请先打开DoubleFeel手表端App,然后点击下方的“下一步”按钮',
context.l10n.watchThemeSyncIntro,
textAlign: TextAlign.center,
style: TextStyle(
color: WatchThemeColors.textPrimary,
... ... @@ -114,7 +115,7 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> {
),
),
_WatchThemeSyncState.syncing => Text(
'请保持打开手表App,等待同步',
context.l10n.watchThemeSyncWaiting,
textAlign: TextAlign.center,
style: TextStyle(
color: WatchThemeColors.textPrimary,
... ... @@ -141,7 +142,9 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> {
),
SizedBox(width: 4.dp),
Text(
_success ? '同步完成' : '同步失败',
_success
? context.l10n.watchThemeSyncComplete
: context.l10n.watchThemeSyncFailed,
style: TextStyle(
color: WatchThemeColors.textPrimary,
fontSize: 14.dp,
... ... @@ -155,12 +158,12 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> {
Widget _buildAction() {
return switch (_state) {
_WatchThemeSyncState.intro => _PrimaryButton(
label: '下一步',
label: context.l10n.watchThemeNext,
onTap: _startSync,
),
_WatchThemeSyncState.syncing => const _ProgressButton(progress: 0.85),
_WatchThemeSyncState.done => _PrimaryButton(
label: '好的',
label: context.l10n.watchThemeOk,
onTap: Get.back,
),
};
... ... @@ -223,7 +226,9 @@ class _ProgressButton extends StatelessWidget {
),
Center(
child: Text(
'同步中 ${(progress * 100).round()}%',
context.l10n.watchThemeSyncingProgress(
(progress * 100).round(),
),
style: TextStyle(
color: Colors.white,
fontSize: 16.dp,
... ...
... ... @@ -578,5 +578,66 @@
"noHealthDataError2Body": "DoubleFeel requires access to Apple Health data to provide stress stats, alerts, and recommendations. If not authorized, some features may not work properly.\n\nRest assured, all health data is only stored locally and will not be uploaded.\n\nTo enable permissions, follow the prompt and select Allow All -> Health -> DoubleFeel in iOS Settings.",
"noHealthDataError3Title": "Error 3: System Issue",
"noHealthDataError3Body": "Based on user feedback, we found two reasons why HRV or heart rate data might be missing:\n\n1. Apple Watch not connected\n · If your Apple Watch has not been worn for a long time, heart rate data may not be collected.\n · Please check iOS Health App -> 'My Watch' to confirm if recent heart rate data was recorded while wearing the Apple Watch.\n · If not, please try wearing your Apple Watch for data collection and turn on the heart rate feature supported by Apple.\n\n2. Heart rate or HRV data missing in the past 30 days\n · Open iOS Health App -> Browse -> 'Heart Rate' or 'HRV' -> 'No Data Found' to confirm if it's missing.\n · If data is missing, please wear the watch again, restart your iPhone and Apple Watch, then open DoubleFeel again.",
"noHealthDataGoToSettings": "Go to Settings"
}
\ No newline at end of file
"noHealthDataGoToSettings": "Go to Settings",
"watchThemeDefaultTheme": "Default Theme",
"watchThemeNoWatchTitle": "Apple Watch Not Found",
"watchThemeNoWatchMessage": "Pair an Apple Watch and try again",
"watchThemeOk": "OK",
"watchThemeSelectFriend": "Select Friend",
"watchThemeSelectAndSync": "Select and Sync to Watch Face",
"watchThemeCustomTheme": "Custom Themes",
"watchThemeCustomDescription": "Capture every mood with your creativity and make a watch face that's uniquely yours.",
"watchThemeCreateTheme": "Create Theme",
"watchThemeOfficialTheme": "Official Themes",
"watchThemeRenameStatus": "Rename Status",
"watchThemeEnterNickname": "Enter a name",
"watchThemeSave": "Save",
"watchThemeDialPreview": "Watch Face Preview",
"watchThemeSwitchFriend": "Switch Friend",
"watchThemeStatusPreview": "Status Preview",
"watchThemeAddWatchFace": "Add Watch Face",
"watchThemeInUse": "In Use",
"watchThemeUseNow": "Use Now",
"watchThemeSyncIntro": "Open the DoubleFeel app on your Apple Watch, then tap Next below.",
"watchThemeSyncWaiting": "Keep the Watch app open while syncing",
"watchThemeSyncComplete": "Sync Complete",
"watchThemeSyncFailed": "Sync Failed",
"watchThemeNext": "Next",
"watchThemeSyncingProgress": "Syncing {progress}%",
"@watchThemeSyncingProgress": {
"placeholders": {
"progress": {
"type": "int"
}
}
},
"watchThemePreview": "Preview",
"watchThemeDelete": "Delete",
"watchThemePageTitle": "Watch Themes",
"watchThemeImagesOnly": "Images only",
"watchThemeName": "Theme Name",
"watchThemeNameMaxLength": "Up to 10 characters",
"watchThemeSubmissionAgreement": "I have read and agree to the User Submission Agreement",
"watchThemeSaving": "Saving",
"watchThemeSaveTheme": "Save Theme",
"watchThemeExcellent": "Excellent",
"watchThemeNormal": "Normal",
"watchThemeSlightStressful": "Watch Your Stress",
"watchThemeStressful": "Stress Overload",
"watchThemeCropImage": "Crop Watch Face Image",
"watchThemeImageProcessFailed": "Image processing failed. Please try again",
"watchThemeAbandonEdit": "Discard Changes",
"watchThemeAbandonMessage": "Your changes won't be saved if you close this page. Discard them?",
"watchThemeContinueEditing": "Continue Editing",
"watchThemeImageUploadFailed": "Image upload failed. Please try again",
"watchThemeCreateFailed": "Failed to create watch face. Please try again",
"watchThemeDeleteTheme": "Delete Theme",
"watchThemeDeleteMessage": "Deleted themes cannot be restored. Delete this theme?",
"watchThemeCancel": "Cancel",
"watchThemeDeleteFailed": "Failed to delete theme",
"watchThemeDeleted": "Theme deleted",
"watchThemeIncomplete": "Theme information is incomplete",
"watchThemeApplyFailed": "Failed to apply theme",
"watchThemeWatchSyncFailed": "Watch face sync failed",
"watchThemePurchaseChannel": "Watch Face Themes"
}
... ...
... ... @@ -866,5 +866,66 @@
"noHealthDataError2Body": "DoubleFeel 需要访问 Apple Health 数据的权限,以提供压力统计、提醒和建议。如果未授权,部分功能可能无法正常使用。\n\n请放心,所有健康数据仅存储在本地,不会上传。\n\n要启用权限,请按提示操作,并在 iOS 设置中选择 允许所有 → 健康 → DoubleFeel。",
"noHealthDataError3Title": "错误 3:系统问题",
"noHealthDataError3Body": "根据用户反馈,我们发现 HRV 或心率数据可能缺失的两个原因:\n\n1. Apple Watch 未连接\n · 如果你的 Apple Watch 长时间未佩戴,心率数据可能无法采集。\n · 请检查 iOS 健康 App → “我的手表”,确认最近的心率数据是否在佩戴 Apple Watch 时记录。\n · 如果没有,请尝试佩戴 Apple Watch 进行数据采集,并打开 Apple 支持的心率功能。\n\n2. 过去 30 天的心率或 HRV 数据缺失\n · 打开 iOS 健康 App → 浏览 → “心率” 或 “HRV” → “未找到数据”,确认是否缺失。\n · 如果数据缺失,请重新佩戴手表,并重启 iPhone 和 Apple Watch 后,再次打开 DoubleFeel。",
"noHealthDataGoToSettings": "前往开启"
}
\ No newline at end of file
"noHealthDataGoToSettings": "前往开启",
"watchThemeDefaultTheme": "默认主题",
"watchThemeNoWatchTitle": "未找到苹果手表",
"watchThemeNoWatchMessage": "请配对苹果手表后再尝试",
"watchThemeOk": "好的",
"watchThemeSelectFriend": "选择好友",
"watchThemeSelectAndSync": "选择并同步至表盘",
"watchThemeCustomTheme": "自定义主题",
"watchThemeCustomDescription": "用创意记录每一次情绪波动,打造懂你的专属表盘吧~",
"watchThemeCreateTheme": "创作主题",
"watchThemeOfficialTheme": "官方主题",
"watchThemeRenameStatus": "修改状态名称",
"watchThemeEnterNickname": "请输入昵称",
"watchThemeSave": "保存",
"watchThemeDialPreview": "表盘预览",
"watchThemeSwitchFriend": "切换好友",
"watchThemeStatusPreview": "状态预览",
"watchThemeAddWatchFace": "添加表盘",
"watchThemeInUse": "正在使用",
"watchThemeUseNow": "立即使用",
"watchThemeSyncIntro": "请先打开DoubleFeel手表端App,然后点击下方的“下一步”按钮",
"watchThemeSyncWaiting": "请保持打开手表App,等待同步",
"watchThemeSyncComplete": "同步完成",
"watchThemeSyncFailed": "同步失败",
"watchThemeNext": "下一步",
"watchThemeSyncingProgress": "同步中 {progress}%",
"@watchThemeSyncingProgress": {
"placeholders": {
"progress": {
"type": "int"
}
}
},
"watchThemePreview": "预览",
"watchThemeDelete": "删除",
"watchThemePageTitle": "Watch主题",
"watchThemeImagesOnly": "仅支持上传图片",
"watchThemeName": "主题名称",
"watchThemeNameMaxLength": "最多10个字符",
"watchThemeSubmissionAgreement": "我已阅读并同意用户投稿协议",
"watchThemeSaving": "保存中",
"watchThemeSaveTheme": "保存主题",
"watchThemeExcellent": "状态优秀",
"watchThemeNormal": "状态正常",
"watchThemeSlightStressful": "注意压力",
"watchThemeStressful": "压力过载",
"watchThemeCropImage": "裁剪表盘图片",
"watchThemeImageProcessFailed": "图片处理失败,请重试",
"watchThemeAbandonEdit": "放弃编辑",
"watchThemeAbandonMessage": "关闭此页面后,已编辑的内容不会保留,是否放弃编辑?",
"watchThemeContinueEditing": "继续编辑",
"watchThemeImageUploadFailed": "图片上传失败,请重试",
"watchThemeCreateFailed": "创建表盘失败,请重试",
"watchThemeDeleteTheme": "删除主题",
"watchThemeDeleteMessage": "主题删除后无法恢复,确认删除该主题吗?",
"watchThemeCancel": "取消",
"watchThemeDeleteFailed": "删除主题失败",
"watchThemeDeleted": "已删除主题",
"watchThemeIncomplete": "主题信息不完整",
"watchThemeApplyFailed": "应用主题失败",
"watchThemeWatchSyncFailed": "表盘同步失败",
"watchThemePurchaseChannel": "表盘主题"
}
... ...
... ... @@ -3428,6 +3428,330 @@ abstract class AppLocalizations {
/// In zh, this message translates to:
/// **'前往开启'**
String get noHealthDataGoToSettings;
/// No description provided for @watchThemeDefaultTheme.
///
/// In zh, this message translates to:
/// **'默认主题'**
String get watchThemeDefaultTheme;
/// No description provided for @watchThemeNoWatchTitle.
///
/// In zh, this message translates to:
/// **'未找到苹果手表'**
String get watchThemeNoWatchTitle;
/// No description provided for @watchThemeNoWatchMessage.
///
/// In zh, this message translates to:
/// **'请配对苹果手表后再尝试'**
String get watchThemeNoWatchMessage;
/// No description provided for @watchThemeOk.
///
/// In zh, this message translates to:
/// **'好的'**
String get watchThemeOk;
/// No description provided for @watchThemeSelectFriend.
///
/// In zh, this message translates to:
/// **'选择好友'**
String get watchThemeSelectFriend;
/// No description provided for @watchThemeSelectAndSync.
///
/// In zh, this message translates to:
/// **'选择并同步至表盘'**
String get watchThemeSelectAndSync;
/// No description provided for @watchThemeCustomTheme.
///
/// In zh, this message translates to:
/// **'自定义主题'**
String get watchThemeCustomTheme;
/// No description provided for @watchThemeCustomDescription.
///
/// In zh, this message translates to:
/// **'用创意记录每一次情绪波动,打造懂你的专属表盘吧~'**
String get watchThemeCustomDescription;
/// No description provided for @watchThemeCreateTheme.
///
/// In zh, this message translates to:
/// **'创作主题'**
String get watchThemeCreateTheme;
/// No description provided for @watchThemeOfficialTheme.
///
/// In zh, this message translates to:
/// **'官方主题'**
String get watchThemeOfficialTheme;
/// No description provided for @watchThemeRenameStatus.
///
/// In zh, this message translates to:
/// **'修改状态名称'**
String get watchThemeRenameStatus;
/// No description provided for @watchThemeEnterNickname.
///
/// In zh, this message translates to:
/// **'请输入昵称'**
String get watchThemeEnterNickname;
/// No description provided for @watchThemeSave.
///
/// In zh, this message translates to:
/// **'保存'**
String get watchThemeSave;
/// No description provided for @watchThemeDialPreview.
///
/// In zh, this message translates to:
/// **'表盘预览'**
String get watchThemeDialPreview;
/// No description provided for @watchThemeSwitchFriend.
///
/// In zh, this message translates to:
/// **'切换好友'**
String get watchThemeSwitchFriend;
/// No description provided for @watchThemeStatusPreview.
///
/// In zh, this message translates to:
/// **'状态预览'**
String get watchThemeStatusPreview;
/// No description provided for @watchThemeAddWatchFace.
///
/// In zh, this message translates to:
/// **'添加表盘'**
String get watchThemeAddWatchFace;
/// No description provided for @watchThemeInUse.
///
/// In zh, this message translates to:
/// **'正在使用'**
String get watchThemeInUse;
/// No description provided for @watchThemeUseNow.
///
/// In zh, this message translates to:
/// **'立即使用'**
String get watchThemeUseNow;
/// No description provided for @watchThemeSyncIntro.
///
/// In zh, this message translates to:
/// **'请先打开DoubleFeel手表端App,然后点击下方的“下一步”按钮'**
String get watchThemeSyncIntro;
/// No description provided for @watchThemeSyncWaiting.
///
/// In zh, this message translates to:
/// **'请保持打开手表App,等待同步'**
String get watchThemeSyncWaiting;
/// No description provided for @watchThemeSyncComplete.
///
/// In zh, this message translates to:
/// **'同步完成'**
String get watchThemeSyncComplete;
/// No description provided for @watchThemeSyncFailed.
///
/// In zh, this message translates to:
/// **'同步失败'**
String get watchThemeSyncFailed;
/// No description provided for @watchThemeNext.
///
/// In zh, this message translates to:
/// **'下一步'**
String get watchThemeNext;
/// No description provided for @watchThemeSyncingProgress.
///
/// In zh, this message translates to:
/// **'同步中 {progress}%'**
String watchThemeSyncingProgress(int progress);
/// No description provided for @watchThemePreview.
///
/// In zh, this message translates to:
/// **'预览'**
String get watchThemePreview;
/// No description provided for @watchThemeDelete.
///
/// In zh, this message translates to:
/// **'删除'**
String get watchThemeDelete;
/// No description provided for @watchThemePageTitle.
///
/// In zh, this message translates to:
/// **'Watch主题'**
String get watchThemePageTitle;
/// No description provided for @watchThemeImagesOnly.
///
/// In zh, this message translates to:
/// **'仅支持上传图片'**
String get watchThemeImagesOnly;
/// No description provided for @watchThemeName.
///
/// In zh, this message translates to:
/// **'主题名称'**
String get watchThemeName;
/// No description provided for @watchThemeNameMaxLength.
///
/// In zh, this message translates to:
/// **'最多10个字符'**
String get watchThemeNameMaxLength;
/// No description provided for @watchThemeSubmissionAgreement.
///
/// In zh, this message translates to:
/// **'我已阅读并同意用户投稿协议'**
String get watchThemeSubmissionAgreement;
/// No description provided for @watchThemeSaving.
///
/// In zh, this message translates to:
/// **'保存中'**
String get watchThemeSaving;
/// No description provided for @watchThemeSaveTheme.
///
/// In zh, this message translates to:
/// **'保存主题'**
String get watchThemeSaveTheme;
/// No description provided for @watchThemeExcellent.
///
/// In zh, this message translates to:
/// **'状态优秀'**
String get watchThemeExcellent;
/// No description provided for @watchThemeNormal.
///
/// In zh, this message translates to:
/// **'状态正常'**
String get watchThemeNormal;
/// No description provided for @watchThemeSlightStressful.
///
/// In zh, this message translates to:
/// **'注意压力'**
String get watchThemeSlightStressful;
/// No description provided for @watchThemeStressful.
///
/// In zh, this message translates to:
/// **'压力过载'**
String get watchThemeStressful;
/// No description provided for @watchThemeCropImage.
///
/// In zh, this message translates to:
/// **'裁剪表盘图片'**
String get watchThemeCropImage;
/// No description provided for @watchThemeImageProcessFailed.
///
/// In zh, this message translates to:
/// **'图片处理失败,请重试'**
String get watchThemeImageProcessFailed;
/// No description provided for @watchThemeAbandonEdit.
///
/// In zh, this message translates to:
/// **'放弃编辑'**
String get watchThemeAbandonEdit;
/// No description provided for @watchThemeAbandonMessage.
///
/// In zh, this message translates to:
/// **'关闭此页面后,已编辑的内容不会保留,是否放弃编辑?'**
String get watchThemeAbandonMessage;
/// No description provided for @watchThemeContinueEditing.
///
/// In zh, this message translates to:
/// **'继续编辑'**
String get watchThemeContinueEditing;
/// No description provided for @watchThemeImageUploadFailed.
///
/// In zh, this message translates to:
/// **'图片上传失败,请重试'**
String get watchThemeImageUploadFailed;
/// No description provided for @watchThemeCreateFailed.
///
/// In zh, this message translates to:
/// **'创建表盘失败,请重试'**
String get watchThemeCreateFailed;
/// No description provided for @watchThemeDeleteTheme.
///
/// In zh, this message translates to:
/// **'删除主题'**
String get watchThemeDeleteTheme;
/// No description provided for @watchThemeDeleteMessage.
///
/// In zh, this message translates to:
/// **'主题删除后无法恢复,确认删除该主题吗?'**
String get watchThemeDeleteMessage;
/// No description provided for @watchThemeCancel.
///
/// In zh, this message translates to:
/// **'取消'**
String get watchThemeCancel;
/// No description provided for @watchThemeDeleteFailed.
///
/// In zh, this message translates to:
/// **'删除主题失败'**
String get watchThemeDeleteFailed;
/// No description provided for @watchThemeDeleted.
///
/// In zh, this message translates to:
/// **'已删除主题'**
String get watchThemeDeleted;
/// No description provided for @watchThemeIncomplete.
///
/// In zh, this message translates to:
/// **'主题信息不完整'**
String get watchThemeIncomplete;
/// No description provided for @watchThemeApplyFailed.
///
/// In zh, this message translates to:
/// **'应用主题失败'**
String get watchThemeApplyFailed;
/// No description provided for @watchThemeWatchSyncFailed.
///
/// In zh, this message translates to:
/// **'表盘同步失败'**
String get watchThemeWatchSyncFailed;
/// No description provided for @watchThemePurchaseChannel.
///
/// In zh, this message translates to:
/// **'表盘主题'**
String get watchThemePurchaseChannel;
}
class _AppLocalizationsDelegate
... ...
... ... @@ -1913,4 +1913,176 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get noHealthDataGoToSettings => 'Go to Settings';
@override
String get watchThemeDefaultTheme => 'Default Theme';
@override
String get watchThemeNoWatchTitle => 'Apple Watch Not Found';
@override
String get watchThemeNoWatchMessage => 'Pair an Apple Watch and try again';
@override
String get watchThemeOk => 'OK';
@override
String get watchThemeSelectFriend => 'Select Friend';
@override
String get watchThemeSelectAndSync => 'Select and Sync to Watch Face';
@override
String get watchThemeCustomTheme => 'Custom Themes';
@override
String get watchThemeCustomDescription =>
'Capture every mood with your creativity and make a watch face that\'s uniquely yours.';
@override
String get watchThemeCreateTheme => 'Create Theme';
@override
String get watchThemeOfficialTheme => 'Official Themes';
@override
String get watchThemeRenameStatus => 'Rename Status';
@override
String get watchThemeEnterNickname => 'Enter a name';
@override
String get watchThemeSave => 'Save';
@override
String get watchThemeDialPreview => 'Watch Face Preview';
@override
String get watchThemeSwitchFriend => 'Switch Friend';
@override
String get watchThemeStatusPreview => 'Status Preview';
@override
String get watchThemeAddWatchFace => 'Add Watch Face';
@override
String get watchThemeInUse => 'In Use';
@override
String get watchThemeUseNow => 'Use Now';
@override
String get watchThemeSyncIntro =>
'Open the DoubleFeel app on your Apple Watch, then tap Next below.';
@override
String get watchThemeSyncWaiting => 'Keep the Watch app open while syncing';
@override
String get watchThemeSyncComplete => 'Sync Complete';
@override
String get watchThemeSyncFailed => 'Sync Failed';
@override
String get watchThemeNext => 'Next';
@override
String watchThemeSyncingProgress(int progress) {
return 'Syncing $progress%';
}
@override
String get watchThemePreview => 'Preview';
@override
String get watchThemeDelete => 'Delete';
@override
String get watchThemePageTitle => 'Watch Themes';
@override
String get watchThemeImagesOnly => 'Images only';
@override
String get watchThemeName => 'Theme Name';
@override
String get watchThemeNameMaxLength => 'Up to 10 characters';
@override
String get watchThemeSubmissionAgreement =>
'I have read and agree to the User Submission Agreement';
@override
String get watchThemeSaving => 'Saving';
@override
String get watchThemeSaveTheme => 'Save Theme';
@override
String get watchThemeExcellent => 'Excellent';
@override
String get watchThemeNormal => 'Normal';
@override
String get watchThemeSlightStressful => 'Watch Your Stress';
@override
String get watchThemeStressful => 'Stress Overload';
@override
String get watchThemeCropImage => 'Crop Watch Face Image';
@override
String get watchThemeImageProcessFailed =>
'Image processing failed. Please try again';
@override
String get watchThemeAbandonEdit => 'Discard Changes';
@override
String get watchThemeAbandonMessage =>
'Your changes won\'t be saved if you close this page. Discard them?';
@override
String get watchThemeContinueEditing => 'Continue Editing';
@override
String get watchThemeImageUploadFailed =>
'Image upload failed. Please try again';
@override
String get watchThemeCreateFailed =>
'Failed to create watch face. Please try again';
@override
String get watchThemeDeleteTheme => 'Delete Theme';
@override
String get watchThemeDeleteMessage =>
'Deleted themes cannot be restored. Delete this theme?';
@override
String get watchThemeCancel => 'Cancel';
@override
String get watchThemeDeleteFailed => 'Failed to delete theme';
@override
String get watchThemeDeleted => 'Theme deleted';
@override
String get watchThemeIncomplete => 'Theme information is incomplete';
@override
String get watchThemeApplyFailed => 'Failed to apply theme';
@override
String get watchThemeWatchSyncFailed => 'Watch face sync failed';
@override
String get watchThemePurchaseChannel => 'Watch Face Themes';
}
... ...
... ... @@ -1812,4 +1812,168 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String get noHealthDataGoToSettings => '前往开启';
@override
String get watchThemeDefaultTheme => '默认主题';
@override
String get watchThemeNoWatchTitle => '未找到苹果手表';
@override
String get watchThemeNoWatchMessage => '请配对苹果手表后再尝试';
@override
String get watchThemeOk => '好的';
@override
String get watchThemeSelectFriend => '选择好友';
@override
String get watchThemeSelectAndSync => '选择并同步至表盘';
@override
String get watchThemeCustomTheme => '自定义主题';
@override
String get watchThemeCustomDescription => '用创意记录每一次情绪波动,打造懂你的专属表盘吧~';
@override
String get watchThemeCreateTheme => '创作主题';
@override
String get watchThemeOfficialTheme => '官方主题';
@override
String get watchThemeRenameStatus => '修改状态名称';
@override
String get watchThemeEnterNickname => '请输入昵称';
@override
String get watchThemeSave => '保存';
@override
String get watchThemeDialPreview => '表盘预览';
@override
String get watchThemeSwitchFriend => '切换好友';
@override
String get watchThemeStatusPreview => '状态预览';
@override
String get watchThemeAddWatchFace => '添加表盘';
@override
String get watchThemeInUse => '正在使用';
@override
String get watchThemeUseNow => '立即使用';
@override
String get watchThemeSyncIntro => '请先打开DoubleFeel手表端App,然后点击下方的“下一步”按钮';
@override
String get watchThemeSyncWaiting => '请保持打开手表App,等待同步';
@override
String get watchThemeSyncComplete => '同步完成';
@override
String get watchThemeSyncFailed => '同步失败';
@override
String get watchThemeNext => '下一步';
@override
String watchThemeSyncingProgress(int progress) {
return '同步中 $progress%';
}
@override
String get watchThemePreview => '预览';
@override
String get watchThemeDelete => '删除';
@override
String get watchThemePageTitle => 'Watch主题';
@override
String get watchThemeImagesOnly => '仅支持上传图片';
@override
String get watchThemeName => '主题名称';
@override
String get watchThemeNameMaxLength => '最多10个字符';
@override
String get watchThemeSubmissionAgreement => '我已阅读并同意用户投稿协议';
@override
String get watchThemeSaving => '保存中';
@override
String get watchThemeSaveTheme => '保存主题';
@override
String get watchThemeExcellent => '状态优秀';
@override
String get watchThemeNormal => '状态正常';
@override
String get watchThemeSlightStressful => '注意压力';
@override
String get watchThemeStressful => '压力过载';
@override
String get watchThemeCropImage => '裁剪表盘图片';
@override
String get watchThemeImageProcessFailed => '图片处理失败,请重试';
@override
String get watchThemeAbandonEdit => '放弃编辑';
@override
String get watchThemeAbandonMessage => '关闭此页面后,已编辑的内容不会保留,是否放弃编辑?';
@override
String get watchThemeContinueEditing => '继续编辑';
@override
String get watchThemeImageUploadFailed => '图片上传失败,请重试';
@override
String get watchThemeCreateFailed => '创建表盘失败,请重试';
@override
String get watchThemeDeleteTheme => '删除主题';
@override
String get watchThemeDeleteMessage => '主题删除后无法恢复,确认删除该主题吗?';
@override
String get watchThemeCancel => '取消';
@override
String get watchThemeDeleteFailed => '删除主题失败';
@override
String get watchThemeDeleted => '已删除主题';
@override
String get watchThemeIncomplete => '主题信息不完整';
@override
String get watchThemeApplyFailed => '应用主题失败';
@override
String get watchThemeWatchSyncFailed => '表盘同步失败';
@override
String get watchThemePurchaseChannel => '表盘主题';
}
... ...