Showing
25 changed files
with
997 additions
and
160 deletions
| @@ -12,6 +12,7 @@ import 'package:get/get.dart'; | @@ -12,6 +12,7 @@ import 'package:get/get.dart'; | ||
| 12 | import 'package:image_cropper/image_cropper.dart'; | 12 | import 'package:image_cropper/image_cropper.dart'; |
| 13 | import 'package:image_picker/image_picker.dart'; | 13 | import 'package:image_picker/image_picker.dart'; |
| 14 | import 'package:path_provider/path_provider.dart'; | 14 | import 'package:path_provider/path_provider.dart'; |
| 15 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 15 | 16 | ||
| 16 | import '../models/watch_theme_models.dart'; | 17 | import '../models/watch_theme_models.dart'; |
| 17 | import '../widgets/watch_theme_dialogs.dart'; | 18 | import '../widgets/watch_theme_dialogs.dart'; |
| @@ -26,7 +27,7 @@ class CreateWatchThemeController extends GetxController { | @@ -26,7 +27,7 @@ class CreateWatchThemeController extends GetxController { | ||
| 26 | 27 | ||
| 27 | final customThemeName = ''.obs; | 28 | final customThemeName = ''.obs; |
| 28 | final agreedToSubmission = true.obs; | 29 | final agreedToSubmission = true.obs; |
| 29 | - final customStatusNames = ['状态优秀', '状态正常', '注意压力', '压力过载'].obs; | 30 | + late final RxList<String> customStatusNames; |
| 30 | final customImagePaths = RxList<String?>.filled(4, null); | 31 | final customImagePaths = RxList<String?>.filled(4, null); |
| 31 | final isRemovingBackground = RxList<bool>.filled(4, false); | 32 | final isRemovingBackground = RxList<bool>.filled(4, false); |
| 32 | final isSaving = false.obs; | 33 | final isSaving = false.obs; |
| @@ -38,6 +39,12 @@ class CreateWatchThemeController extends GetxController { | @@ -38,6 +39,12 @@ class CreateWatchThemeController extends GetxController { | ||
| 38 | @override | 39 | @override |
| 39 | void onInit() { | 40 | void onInit() { |
| 40 | super.onInit(); | 41 | super.onInit(); |
| 42 | + customStatusNames = [ | ||
| 43 | + l10n.watchThemeExcellent, | ||
| 44 | + l10n.watchThemeNormal, | ||
| 45 | + l10n.watchThemeSlightStressful, | ||
| 46 | + l10n.watchThemeStressful, | ||
| 47 | + ].obs; | ||
| 41 | themeNameController = TextEditingController(); | 48 | themeNameController = TextEditingController(); |
| 42 | themeNameController.addListener(() { | 49 | themeNameController.addListener(() { |
| 43 | customThemeName.value = themeNameController.text.trim(); | 50 | customThemeName.value = themeNameController.text.trim(); |
| @@ -78,11 +85,11 @@ class CreateWatchThemeController extends GetxController { | @@ -78,11 +85,11 @@ class CreateWatchThemeController extends GetxController { | ||
| 78 | compressQuality: 100, | 85 | compressQuality: 100, |
| 79 | uiSettings: [ | 86 | uiSettings: [ |
| 80 | AndroidUiSettings( | 87 | AndroidUiSettings( |
| 81 | - toolbarTitle: '裁剪表盘图片', | 88 | + toolbarTitle: l10n.watchThemeCropImage, |
| 82 | lockAspectRatio: true, | 89 | lockAspectRatio: true, |
| 83 | ), | 90 | ), |
| 84 | IOSUiSettings( | 91 | IOSUiSettings( |
| 85 | - title: '裁剪表盘图片', | 92 | + title: l10n.watchThemeCropImage, |
| 86 | aspectRatioLockEnabled: true, | 93 | aspectRatioLockEnabled: true, |
| 87 | resetAspectRatioEnabled: false, | 94 | resetAspectRatioEnabled: false, |
| 88 | ), | 95 | ), |
| @@ -102,7 +109,7 @@ class CreateWatchThemeController extends GetxController { | @@ -102,7 +109,7 @@ class CreateWatchThemeController extends GetxController { | ||
| 102 | // 此处不等待结果,让裁切图先显示;处理完成后再原位替换。 | 109 | // 此处不等待结果,让裁切图先显示;处理完成后再原位替换。 |
| 103 | unawaited(_removeBackgroundAndReplace(index, savedPath, taskVersion)); | 110 | unawaited(_removeBackgroundAndReplace(index, savedPath, taskVersion)); |
| 104 | } catch (_) { | 111 | } catch (_) { |
| 105 | - AppToast.show('图片处理失败,请重试'); | 112 | + AppToast.show(l10n.watchThemeImageProcessFailed); |
| 106 | } | 113 | } |
| 107 | } | 114 | } |
| 108 | 115 | ||
| @@ -209,11 +216,11 @@ class CreateWatchThemeController extends GetxController { | @@ -209,11 +216,11 @@ class CreateWatchThemeController extends GetxController { | ||
| 209 | return; | 216 | return; |
| 210 | } | 217 | } |
| 211 | final abandon = await Get.dialog<bool>( | 218 | final abandon = await Get.dialog<bool>( |
| 212 | - const WatchThemeConfirmDialog( | ||
| 213 | - title: '放弃编辑', | ||
| 214 | - message: '关闭此页面后,已编辑的内容不会保留,是否放弃编辑?', | ||
| 215 | - primaryText: '放弃编辑', | ||
| 216 | - secondaryText: '继续编辑', | 219 | + WatchThemeConfirmDialog( |
| 220 | + title: l10n.watchThemeAbandonEdit, | ||
| 221 | + message: l10n.watchThemeAbandonMessage, | ||
| 222 | + primaryText: l10n.watchThemeAbandonEdit, | ||
| 223 | + secondaryText: l10n.watchThemeContinueEditing, | ||
| 217 | ), | 224 | ), |
| 218 | barrierDismissible: true, | 225 | barrierDismissible: true, |
| 219 | ); | 226 | ); |
| @@ -241,7 +248,7 @@ class CreateWatchThemeController extends GetxController { | @@ -241,7 +248,7 @@ class CreateWatchThemeController extends GetxController { | ||
| 241 | HResourceType.image, | 248 | HResourceType.image, |
| 242 | ); | 249 | ); |
| 243 | if (imageUrl == null || imageUrl.isEmpty) { | 250 | if (imageUrl == null || imageUrl.isEmpty) { |
| 244 | - AppToast.show('图片上传失败,请重试'); | 251 | + AppToast.show(l10n.watchThemeImageUploadFailed); |
| 245 | return; | 252 | return; |
| 246 | } | 253 | } |
| 247 | uploadedImageUrls.add(imageUrl); | 254 | uploadedImageUrls.add(imageUrl); |
| @@ -275,7 +282,7 @@ class CreateWatchThemeController extends GetxController { | @@ -275,7 +282,7 @@ class CreateWatchThemeController extends GetxController { | ||
| 275 | ); | 282 | ); |
| 276 | return; | 283 | return; |
| 277 | } catch (_) { | 284 | } catch (_) { |
| 278 | - AppToast.show('创建表盘失败,请重试'); | 285 | + AppToast.show(l10n.watchThemeCreateFailed); |
| 279 | } finally { | 286 | } finally { |
| 280 | isSaving.value = false; | 287 | isSaving.value = false; |
| 281 | } | 288 | } |
| @@ -10,6 +10,7 @@ import 'package:doublefeel_flutter/pigeon/platform_api.g.dart'; | @@ -10,6 +10,7 @@ import 'package:doublefeel_flutter/pigeon/platform_api.g.dart'; | ||
| 10 | import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart'; | 10 | import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart'; |
| 11 | import 'package:flutter/material.dart'; | 11 | import 'package:flutter/material.dart'; |
| 12 | import 'package:get/get.dart'; | 12 | import 'package:get/get.dart'; |
| 13 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 13 | 14 | ||
| 14 | import '../../friends/models/friend_health_data.dart'; | 15 | import '../../friends/models/friend_health_data.dart'; |
| 15 | import '../../friends/views/select_friend_view.dart'; | 16 | import '../../friends/views/select_friend_view.dart'; |
| @@ -95,11 +96,11 @@ class CustomWatchThemePreviewController extends GetxController { | @@ -95,11 +96,11 @@ class CustomWatchThemePreviewController extends GetxController { | ||
| 95 | 96 | ||
| 96 | Future<void> confirmDeleteCustomTheme() async { | 97 | Future<void> confirmDeleteCustomTheme() async { |
| 97 | final shouldDelete = await Get.dialog<bool>( | 98 | final shouldDelete = await Get.dialog<bool>( |
| 98 | - const WatchThemeConfirmDialog( | ||
| 99 | - title: '删除主题', | ||
| 100 | - message: '主题删除后无法恢复,确认删除该主题吗?', | ||
| 101 | - primaryText: '删除', | ||
| 102 | - secondaryText: '取消', | 99 | + WatchThemeConfirmDialog( |
| 100 | + title: l10n.watchThemeDeleteTheme, | ||
| 101 | + message: l10n.watchThemeDeleteMessage, | ||
| 102 | + primaryText: l10n.watchThemeDelete, | ||
| 103 | + secondaryText: l10n.watchThemeCancel, | ||
| 103 | ), | 104 | ), |
| 104 | barrierDismissible: true, | 105 | barrierDismissible: true, |
| 105 | ); | 106 | ); |
| @@ -113,10 +114,10 @@ class CustomWatchThemePreviewController extends GetxController { | @@ -113,10 +114,10 @@ class CustomWatchThemePreviewController extends GetxController { | ||
| 113 | final result = await _themeApi.deleteTheme(themeId); | 114 | final result = await _themeApi.deleteTheme(themeId); |
| 114 | isDeleting.value = false; | 115 | isDeleting.value = false; |
| 115 | if (result is! AppSuccess<void>) { | 116 | if (result is! AppSuccess<void>) { |
| 116 | - AppToast.show('删除主题失败'); | 117 | + AppToast.show(l10n.watchThemeDeleteFailed); |
| 117 | return; | 118 | return; |
| 118 | } | 119 | } |
| 119 | - AppToast.show('已删除主题'); | 120 | + AppToast.show(l10n.watchThemeDeleted); |
| 120 | Get.back(); | 121 | Get.back(); |
| 121 | } | 122 | } |
| 122 | } | 123 | } |
| @@ -188,7 +189,7 @@ class CustomWatchThemePreviewController extends GetxController { | @@ -188,7 +189,7 @@ class CustomWatchThemePreviewController extends GetxController { | ||
| 188 | Future<bool> applyAndSyncWatchFace() async { | 189 | Future<bool> applyAndSyncWatchFace() async { |
| 189 | final themeId = themeItem.id; | 190 | final themeId = themeItem.id; |
| 190 | if (themeId == null) { | 191 | if (themeId == null) { |
| 191 | - AppToast.show('主题信息不完整'); | 192 | + AppToast.show(l10n.watchThemeIncomplete); |
| 192 | return false; | 193 | return false; |
| 193 | } | 194 | } |
| 194 | 195 | ||
| @@ -196,7 +197,7 @@ class CustomWatchThemePreviewController extends GetxController { | @@ -196,7 +197,7 @@ class CustomWatchThemePreviewController extends GetxController { | ||
| 196 | final result = await _themeApi.applyTheme(themeId); | 197 | final result = await _themeApi.applyTheme(themeId); |
| 197 | if (result is! AppSuccess<void>) { | 198 | if (result is! AppSuccess<void>) { |
| 198 | isApplying.value = false; | 199 | isApplying.value = false; |
| 199 | - AppToast.show('应用主题失败'); | 200 | + AppToast.show(l10n.watchThemeApplyFailed); |
| 200 | return false; | 201 | return false; |
| 201 | } | 202 | } |
| 202 | 203 | ||
| @@ -213,7 +214,7 @@ class CustomWatchThemePreviewController extends GetxController { | @@ -213,7 +214,7 @@ class CustomWatchThemePreviewController extends GetxController { | ||
| 213 | } | 214 | } |
| 214 | isApplying.value = false; | 215 | isApplying.value = false; |
| 215 | if (!syncSuccess) { | 216 | if (!syncSuccess) { |
| 216 | - AppToast.show('表盘同步失败'); | 217 | + AppToast.show(l10n.watchThemeWatchSyncFailed); |
| 217 | } | 218 | } |
| 218 | return syncSuccess; | 219 | return syncSuccess; |
| 219 | } | 220 | } |
| @@ -8,6 +8,7 @@ import 'package:doublefeel_flutter/core/result/app_result.dart'; | @@ -8,6 +8,7 @@ import 'package:doublefeel_flutter/core/result/app_result.dart'; | ||
| 8 | import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart'; | 8 | import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart'; |
| 9 | import 'package:doublefeel_flutter/data/models/local/user_preferences.dart'; | 9 | import 'package:doublefeel_flutter/data/models/local/user_preferences.dart'; |
| 10 | import 'package:get/get.dart'; | 10 | import 'package:get/get.dart'; |
| 11 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 11 | 12 | ||
| 12 | import '../models/watch_theme_models.dart'; | 13 | import '../models/watch_theme_models.dart'; |
| 13 | 14 | ||
| @@ -86,13 +87,15 @@ class WatchThemeController extends GetxController { | @@ -86,13 +87,15 @@ class WatchThemeController extends GetxController { | ||
| 86 | final vipPrefs = UserPreferencesVipInfo.fromVipInfo(vip); | 87 | final vipPrefs = UserPreferencesVipInfo.fromVipInfo(vip); |
| 87 | await Get.find<UserPreferencesStorage>().updateVipInfo(vipPrefs); | 88 | await Get.find<UserPreferencesStorage>().updateVipInfo(vipPrefs); |
| 88 | isPremium.value = vipPrefs.isVip; | 89 | isPremium.value = vipPrefs.isVip; |
| 89 | - } on Exception catch (e) {} | 90 | + } on Exception catch (_) { |
| 91 | + // Keep the current membership state when local persistence fails. | ||
| 92 | + } | ||
| 90 | } | 93 | } |
| 91 | } | 94 | } |
| 92 | 95 | ||
| 93 | Future<void> _toPremiumPage() async { | 96 | Future<void> _toPremiumPage() async { |
| 94 | await Get.toNamed(Routes.PURCHASE, arguments: { | 97 | await Get.toNamed(Routes.PURCHASE, arguments: { |
| 95 | - IntentKeys.channelType: '表盘主题', | 98 | + IntentKeys.channelType: l10n.watchThemePurchaseChannel, |
| 96 | }); | 99 | }); |
| 97 | await _refreshVip(); | 100 | await _refreshVip(); |
| 98 | } | 101 | } |
| @@ -10,6 +10,7 @@ import 'package:doublefeel_flutter/pigeon/platform_api.g.dart'; | @@ -10,6 +10,7 @@ import 'package:doublefeel_flutter/pigeon/platform_api.g.dart'; | ||
| 10 | import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart'; | 10 | import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart'; |
| 11 | import 'package:flutter/material.dart'; | 11 | import 'package:flutter/material.dart'; |
| 12 | import 'package:get/get.dart'; | 12 | import 'package:get/get.dart'; |
| 13 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 13 | 14 | ||
| 14 | import '../../friends/models/friend_health_data.dart'; | 15 | import '../../friends/models/friend_health_data.dart'; |
| 15 | import '../../friends/views/select_friend_view.dart'; | 16 | import '../../friends/views/select_friend_view.dart'; |
| @@ -160,7 +161,7 @@ class WatchThemePreviewController extends GetxController { | @@ -160,7 +161,7 @@ class WatchThemePreviewController extends GetxController { | ||
| 160 | Future<bool> applyAndSyncWatchFace() async { | 161 | Future<bool> applyAndSyncWatchFace() async { |
| 161 | final themeId = themeItem.id; | 162 | final themeId = themeItem.id; |
| 162 | if (themeId == null) { | 163 | if (themeId == null) { |
| 163 | - AppToast.show('主题信息不完整'); | 164 | + AppToast.show(l10n.watchThemeIncomplete); |
| 164 | return false; | 165 | return false; |
| 165 | } | 166 | } |
| 166 | 167 | ||
| @@ -168,7 +169,7 @@ class WatchThemePreviewController extends GetxController { | @@ -168,7 +169,7 @@ class WatchThemePreviewController extends GetxController { | ||
| 168 | final result = await _themeApi.applyTheme(themeId); | 169 | final result = await _themeApi.applyTheme(themeId); |
| 169 | if (result is! AppSuccess<void>) { | 170 | if (result is! AppSuccess<void>) { |
| 170 | isApplying.value = false; | 171 | isApplying.value = false; |
| 171 | - AppToast.show('应用主题失败'); | 172 | + AppToast.show(l10n.watchThemeApplyFailed); |
| 172 | return false; | 173 | return false; |
| 173 | } | 174 | } |
| 174 | 175 | ||
| @@ -185,7 +186,7 @@ class WatchThemePreviewController extends GetxController { | @@ -185,7 +186,7 @@ class WatchThemePreviewController extends GetxController { | ||
| 185 | } | 186 | } |
| 186 | isApplying.value = false; | 187 | isApplying.value = false; |
| 187 | if (!syncSuccess) { | 188 | if (!syncSuccess) { |
| 188 | - AppToast.show('表盘同步失败'); | 189 | + AppToast.show(l10n.watchThemeWatchSyncFailed); |
| 189 | } | 190 | } |
| 190 | return syncSuccess; | 191 | return syncSuccess; |
| 191 | } | 192 | } |
| 1 | import 'dart:ui'; | 1 | import 'dart:ui'; |
| 2 | 2 | ||
| 3 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 4 | + | ||
| 3 | import '../widgets/watch_theme_colors.dart'; | 5 | import '../widgets/watch_theme_colors.dart'; |
| 4 | 6 | ||
| 5 | class WatchThemeItem { | 7 | class WatchThemeItem { |
| @@ -46,18 +48,24 @@ class WatchThemeItem { | @@ -46,18 +48,24 @@ class WatchThemeItem { | ||
| 46 | id: _intFromJson(json['id']), | 48 | id: _intFromJson(json['id']), |
| 47 | userId: _intFromJson(json['user_id']), | 49 | userId: _intFromJson(json['user_id']), |
| 48 | status: _intFromJson(json['status']), | 50 | status: _intFromJson(json['status']), |
| 49 | - themeName: _stringFromJson(json['theme_name'], '自定义主题'), | ||
| 50 | - energeticDescription: | ||
| 51 | - _stringFromJson(json['energetic_description'], '状态优秀'), | 51 | + themeName: _stringFromJson( |
| 52 | + json['theme_name'], | ||
| 53 | + l10n.watchThemeCustomTheme, | ||
| 54 | + ), | ||
| 55 | + energeticDescription: _stringFromJson( | ||
| 56 | + json['energetic_description'], l10n.watchThemeExcellent), | ||
| 52 | energeticImage: _nullableStringFromJson(json['energetic_image']), | 57 | energeticImage: _nullableStringFromJson(json['energetic_image']), |
| 53 | - normalDescription: _stringFromJson(json['normal_description'], '状态正常'), | 58 | + normalDescription: |
| 59 | + _stringFromJson(json['normal_description'], l10n.watchThemeNormal), | ||
| 54 | normalImage: _nullableStringFromJson(json['normal_image']), | 60 | normalImage: _nullableStringFromJson(json['normal_image']), |
| 55 | - slightStressfulDescription: | ||
| 56 | - _stringFromJson(json['slight_stressful_description'], '注意压力'), | 61 | + slightStressfulDescription: _stringFromJson( |
| 62 | + json['slight_stressful_description'], | ||
| 63 | + l10n.watchThemeSlightStressful, | ||
| 64 | + ), | ||
| 57 | slightStressfulImage: | 65 | slightStressfulImage: |
| 58 | _nullableStringFromJson(json['slight_stressful_image']), | 66 | _nullableStringFromJson(json['slight_stressful_image']), |
| 59 | - stressfulDescription: | ||
| 60 | - _stringFromJson(json['stressful_description'], '压力过载'), | 67 | + stressfulDescription: _stringFromJson( |
| 68 | + json['stressful_description'], l10n.watchThemeStressful), | ||
| 61 | stressfulImage: _nullableStringFromJson(json['stressful_image']), | 69 | stressfulImage: _nullableStringFromJson(json['stressful_image']), |
| 62 | isOfficial: _intFromJson(json['is_official']) ?? 0, | 70 | isOfficial: _intFromJson(json['is_official']) ?? 0, |
| 63 | isDefaultTheme: _intFromJson(json['is_default_theme']) ?? 0, | 71 | isDefaultTheme: _intFromJson(json['is_default_theme']) ?? 0, |
| @@ -117,12 +125,12 @@ class WatchThemeItem { | @@ -117,12 +125,12 @@ class WatchThemeItem { | ||
| 117 | ]; | 125 | ]; |
| 118 | 126 | ||
| 119 | static WatchThemeItem empty() { | 127 | static WatchThemeItem empty() { |
| 120 | - return const WatchThemeItem( | ||
| 121 | - themeName: '自定义主题', | ||
| 122 | - energeticDescription: '状态优秀', | ||
| 123 | - normalDescription: '状态正常', | ||
| 124 | - slightStressfulDescription: '注意压力', | ||
| 125 | - stressfulDescription: '压力过载', | 128 | + return WatchThemeItem( |
| 129 | + themeName: l10n.watchThemeCustomTheme, | ||
| 130 | + energeticDescription: l10n.watchThemeExcellent, | ||
| 131 | + normalDescription: l10n.watchThemeNormal, | ||
| 132 | + slightStressfulDescription: l10n.watchThemeSlightStressful, | ||
| 133 | + stressfulDescription: l10n.watchThemeStressful, | ||
| 126 | ); | 134 | ); |
| 127 | } | 135 | } |
| 128 | 136 | ||
| @@ -226,12 +234,24 @@ class WatchThemeUpsertRequest { | @@ -226,12 +234,24 @@ class WatchThemeUpsertRequest { | ||
| 226 | } | 234 | } |
| 227 | } | 235 | } |
| 228 | 236 | ||
| 229 | -final defaultThemeTemplates = [ | ||
| 230 | - WatchThemeTemplateItem(title: '状态优秀', color: WatchThemeColors.excellent), | ||
| 231 | - WatchThemeTemplateItem(title: '状态正常', color: WatchThemeColors.normal), | ||
| 232 | - WatchThemeTemplateItem(title: '注意压力', color: WatchThemeColors.stress), | ||
| 233 | - WatchThemeTemplateItem(title: '压力过载', color: WatchThemeColors.overload), | ||
| 234 | -]; | 237 | +List<WatchThemeTemplateItem> get defaultThemeTemplates => [ |
| 238 | + WatchThemeTemplateItem( | ||
| 239 | + title: l10n.watchThemeExcellent, | ||
| 240 | + color: WatchThemeColors.excellent, | ||
| 241 | + ), | ||
| 242 | + WatchThemeTemplateItem( | ||
| 243 | + title: l10n.watchThemeNormal, | ||
| 244 | + color: WatchThemeColors.normal, | ||
| 245 | + ), | ||
| 246 | + WatchThemeTemplateItem( | ||
| 247 | + title: l10n.watchThemeSlightStressful, | ||
| 248 | + color: WatchThemeColors.stress, | ||
| 249 | + ), | ||
| 250 | + WatchThemeTemplateItem( | ||
| 251 | + title: l10n.watchThemeStressful, | ||
| 252 | + color: WatchThemeColors.overload, | ||
| 253 | + ), | ||
| 254 | + ]; | ||
| 235 | 255 | ||
| 236 | class WatchThemeTemplateItem { | 256 | class WatchThemeTemplateItem { |
| 237 | WatchThemeTemplateItem({required this.title, required this.color}); | 257 | WatchThemeTemplateItem({required this.title, required this.color}); |
| @@ -2,6 +2,7 @@ import 'dart:io'; | @@ -2,6 +2,7 @@ import 'dart:io'; | ||
| 2 | 2 | ||
| 3 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; |
| 4 | import 'package:get/get.dart'; | 4 | import 'package:get/get.dart'; |
| 5 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 5 | 6 | ||
| 6 | import '../controllers/create_watch_theme_controller.dart'; | 7 | import '../controllers/create_watch_theme_controller.dart'; |
| 7 | import '../widgets/watch_face_preview.dart'; | 8 | import '../widgets/watch_face_preview.dart'; |
| @@ -22,7 +23,7 @@ class CreateWatchThemeView extends GetView<CreateWatchThemeController> { | @@ -22,7 +23,7 @@ class CreateWatchThemeView extends GetView<CreateWatchThemeController> { | ||
| 22 | } | 23 | } |
| 23 | }, | 24 | }, |
| 24 | child: WatchThemeGradientScaffold( | 25 | child: WatchThemeGradientScaffold( |
| 25 | - title: '创作主题', | 26 | + title: context.l10n.watchThemeCreateTheme, |
| 26 | onBack: controller.handleCreateBack, | 27 | onBack: controller.handleCreateBack, |
| 27 | body: SingleChildScrollView( | 28 | body: SingleChildScrollView( |
| 28 | physics: const AlwaysScrollableScrollPhysics(), | 29 | physics: const AlwaysScrollableScrollPhysics(), |
| @@ -74,7 +75,7 @@ class _EditorCard extends StatelessWidget { | @@ -74,7 +75,7 @@ class _EditorCard extends StatelessWidget { | ||
| 74 | crossAxisAlignment: CrossAxisAlignment.start, | 75 | crossAxisAlignment: CrossAxisAlignment.start, |
| 75 | children: [ | 76 | children: [ |
| 76 | Text( | 77 | Text( |
| 77 | - '自定义主题', | 78 | + context.l10n.watchThemeCustomTheme, |
| 78 | style: TextStyle( | 79 | style: TextStyle( |
| 79 | color: WatchThemeColors.textPrimary, | 80 | color: WatchThemeColors.textPrimary, |
| 80 | fontSize: 16, | 81 | fontSize: 16, |
| @@ -83,7 +84,7 @@ class _EditorCard extends StatelessWidget { | @@ -83,7 +84,7 @@ class _EditorCard extends StatelessWidget { | ||
| 83 | ), | 84 | ), |
| 84 | SizedBox(height: 4), | 85 | SizedBox(height: 4), |
| 85 | Text( | 86 | Text( |
| 86 | - '仅支持上传图片', | 87 | + context.l10n.watchThemeImagesOnly, |
| 87 | style: TextStyle( | 88 | style: TextStyle( |
| 88 | color: WatchThemeColors.textSecondary, | 89 | color: WatchThemeColors.textSecondary, |
| 89 | fontSize: 12, | 90 | fontSize: 12, |
| @@ -116,7 +117,7 @@ class _EditorCard extends StatelessWidget { | @@ -116,7 +117,7 @@ class _EditorCard extends StatelessWidget { | ||
| 116 | ), | 117 | ), |
| 117 | SizedBox(height: 14), | 118 | SizedBox(height: 14), |
| 118 | Text( | 119 | Text( |
| 119 | - '主题名称', | 120 | + context.l10n.watchThemeName, |
| 120 | style: TextStyle( | 121 | style: TextStyle( |
| 121 | color: WatchThemeColors.textPrimary, | 122 | color: WatchThemeColors.textPrimary, |
| 122 | fontSize: 16, | 123 | fontSize: 16, |
| @@ -137,7 +138,7 @@ class _EditorCard extends StatelessWidget { | @@ -137,7 +138,7 @@ class _EditorCard extends StatelessWidget { | ||
| 137 | maxLength: 10, | 138 | maxLength: 10, |
| 138 | decoration: InputDecoration( | 139 | decoration: InputDecoration( |
| 139 | counterText: '', | 140 | counterText: '', |
| 140 | - hintText: '最多10个字符', | 141 | + hintText: context.l10n.watchThemeNameMaxLength, |
| 141 | hintStyle: TextStyle( | 142 | hintStyle: TextStyle( |
| 142 | color: WatchThemeColors.textTertiary, | 143 | color: WatchThemeColors.textTertiary, |
| 143 | fontSize: 14, | 144 | fontSize: 14, |
| @@ -251,7 +252,7 @@ class _AgreementRow extends StatelessWidget { | @@ -251,7 +252,7 @@ class _AgreementRow extends StatelessWidget { | ||
| 251 | ), | 252 | ), |
| 252 | SizedBox(width: 4), | 253 | SizedBox(width: 4), |
| 253 | Text( | 254 | Text( |
| 254 | - '我已阅读并同意用户投稿协议', | 255 | + context.l10n.watchThemeSubmissionAgreement, |
| 255 | style: TextStyle( | 256 | style: TextStyle( |
| 256 | color: WatchThemeColors.textSecondary, | 257 | color: WatchThemeColors.textSecondary, |
| 257 | fontSize: 12, | 258 | fontSize: 12, |
| @@ -287,7 +288,9 @@ class _SaveButton extends StatelessWidget { | @@ -287,7 +288,9 @@ class _SaveButton extends StatelessWidget { | ||
| 287 | borderRadius: BorderRadius.circular(24), | 288 | borderRadius: BorderRadius.circular(24), |
| 288 | ), | 289 | ), |
| 289 | child: Text( | 290 | child: Text( |
| 290 | - controller.isSaving.value ? '保存中' : '保存主题', | 291 | + controller.isSaving.value |
| 292 | + ? context.l10n.watchThemeSaving | ||
| 293 | + : context.l10n.watchThemeSaveTheme, | ||
| 291 | style: TextStyle( | 294 | style: TextStyle( |
| 292 | color: Colors.white, | 295 | color: Colors.white, |
| 293 | fontSize: 16, | 296 | fontSize: 16, |
| 1 | import 'package:doublefeel_flutter/app/modules/watch_theme/widgets/dial_preview_card.dart'; | 1 | import 'package:doublefeel_flutter/app/modules/watch_theme/widgets/dial_preview_card.dart'; |
| 2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
| 3 | import 'package:get/get.dart'; | 3 | import 'package:get/get.dart'; |
| 4 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 4 | 5 | ||
| 5 | import '../controllers/custom_watch_theme_preview_controller.dart'; | 6 | import '../controllers/custom_watch_theme_preview_controller.dart'; |
| 6 | import '../widgets/status_preview_card.dart'; | 7 | import '../widgets/status_preview_card.dart'; |
| @@ -16,13 +17,13 @@ class CustomWatchThemePreviewView | @@ -16,13 +17,13 @@ class CustomWatchThemePreviewView | ||
| 16 | Widget build(BuildContext context) { | 17 | Widget build(BuildContext context) { |
| 17 | final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight; | 18 | final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight; |
| 18 | return WatchThemeGradientScaffold( | 19 | return WatchThemeGradientScaffold( |
| 19 | - title: '预览', | 20 | + title: context.l10n.watchThemePreview, |
| 20 | onBack: controller.executeBackLogic, | 21 | onBack: controller.executeBackLogic, |
| 21 | trailing: GestureDetector( | 22 | trailing: GestureDetector( |
| 22 | onTap: controller.confirmDeleteCustomTheme, | 23 | onTap: controller.confirmDeleteCustomTheme, |
| 23 | - child: const Text( | ||
| 24 | - '删除', | ||
| 25 | - style: TextStyle( | 24 | + child: Text( |
| 25 | + context.l10n.watchThemeDelete, | ||
| 26 | + style: const TextStyle( | ||
| 26 | color: Color(0xFFFC4447), | 27 | color: Color(0xFFFC4447), |
| 27 | fontSize: 14, | 28 | fontSize: 14, |
| 28 | fontWeight: FontWeight.w600, | 29 | fontWeight: FontWeight.w600, |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:get/get.dart'; | 2 | import 'package:get/get.dart'; |
| 3 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 3 | 4 | ||
| 4 | import '../controllers/watch_theme_preview_controller.dart'; | 5 | import '../controllers/watch_theme_preview_controller.dart'; |
| 5 | import '../widgets/dial_preview_card.dart'; | 6 | import '../widgets/dial_preview_card.dart'; |
| @@ -15,7 +16,7 @@ class WatchThemePreviewView extends GetView<WatchThemePreviewController> { | @@ -15,7 +16,7 @@ class WatchThemePreviewView extends GetView<WatchThemePreviewController> { | ||
| 15 | Widget build(BuildContext context) { | 16 | Widget build(BuildContext context) { |
| 16 | final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight; | 17 | final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight; |
| 17 | return WatchThemeGradientScaffold( | 18 | return WatchThemeGradientScaffold( |
| 18 | - title: '预览', | 19 | + title: context.l10n.watchThemePreview, |
| 19 | onBack: controller.executeBackLogic, | 20 | onBack: controller.executeBackLogic, |
| 20 | body: SingleChildScrollView( | 21 | body: SingleChildScrollView( |
| 21 | physics: const AlwaysScrollableScrollPhysics(), | 22 | physics: const AlwaysScrollableScrollPhysics(), |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:get/get.dart'; | 2 | import 'package:get/get.dart'; |
| 3 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 3 | 4 | ||
| 4 | import '../controllers/watch_theme_controller.dart'; | 5 | import '../controllers/watch_theme_controller.dart'; |
| 5 | import '../widgets/custom_theme_card.dart'; | 6 | import '../widgets/custom_theme_card.dart'; |
| @@ -14,7 +15,7 @@ class WatchThemeView extends GetView<WatchThemeController> { | @@ -14,7 +15,7 @@ class WatchThemeView extends GetView<WatchThemeController> { | ||
| 14 | Widget build(BuildContext context) { | 15 | Widget build(BuildContext context) { |
| 15 | final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight; | 16 | final topPadding = MediaQuery.paddingOf(context).top + kToolbarHeight; |
| 16 | return WatchThemeGradientScaffold( | 17 | return WatchThemeGradientScaffold( |
| 17 | - title: 'Watch主题', | 18 | + title: context.l10n.watchThemePageTitle, |
| 18 | onBack: controller.executeBackLogic, | 19 | onBack: controller.executeBackLogic, |
| 19 | body: Obx( | 20 | body: Obx( |
| 20 | () => SingleChildScrollView( | 21 | () => SingleChildScrollView( |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:get/utils.dart'; | 2 | import 'package:get/utils.dart'; |
| 3 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 3 | 4 | ||
| 4 | import '../models/watch_theme_models.dart'; | 5 | import '../models/watch_theme_models.dart'; |
| 5 | import 'watch_theme_character_avatar.dart'; | 6 | import 'watch_theme_character_avatar.dart'; |
| @@ -31,12 +32,12 @@ class CustomThemeCard extends StatelessWidget { | @@ -31,12 +32,12 @@ class CustomThemeCard extends StatelessWidget { | ||
| 31 | crossAxisAlignment: CrossAxisAlignment.start, | 32 | crossAxisAlignment: CrossAxisAlignment.start, |
| 32 | children: [ | 33 | children: [ |
| 33 | WatchThemeSectionTitle( | 34 | WatchThemeSectionTitle( |
| 34 | - '自定义主题', | 35 | + context.l10n.watchThemeCustomTheme, |
| 35 | trailing: isPremium ? null : const WatchThemeProBadge(), | 36 | trailing: isPremium ? null : const WatchThemeProBadge(), |
| 36 | ), | 37 | ), |
| 37 | SizedBox(height: 4), | 38 | SizedBox(height: 4), |
| 38 | Text( | 39 | Text( |
| 39 | - '用创意记录每一次情绪波动,打造懂你的专属表盘吧~', | 40 | + context.l10n.watchThemeCustomDescription, |
| 40 | maxLines: 1, | 41 | maxLines: 1, |
| 41 | overflow: TextOverflow.ellipsis, | 42 | overflow: TextOverflow.ellipsis, |
| 42 | style: TextStyle( | 43 | style: TextStyle( |
| @@ -57,12 +58,12 @@ class CustomThemeCard extends StatelessWidget { | @@ -57,12 +58,12 @@ class CustomThemeCard extends StatelessWidget { | ||
| 57 | padding: EdgeInsets.zero, | 58 | padding: EdgeInsets.zero, |
| 58 | itemBuilder: (context, index) { | 59 | itemBuilder: (context, index) { |
| 59 | return _CustomThemeItem( | 60 | return _CustomThemeItem( |
| 60 | - item: customThemes[index], | ||
| 61 | - selected: customThemes[index].id != null && | ||
| 62 | - customThemes[index].id == activeThemeId, | ||
| 63 | - onTap: onThemeTap == null | ||
| 64 | - ? null | ||
| 65 | - : () => onThemeTap!(customThemes[index]), | 61 | + item: customThemes[index], |
| 62 | + selected: customThemes[index].id != null && | ||
| 63 | + customThemes[index].id == activeThemeId, | ||
| 64 | + onTap: onThemeTap == null | ||
| 65 | + ? null | ||
| 66 | + : () => onThemeTap!(customThemes[index]), | ||
| 66 | ); | 67 | ); |
| 67 | }, | 68 | }, |
| 68 | separatorBuilder: (context, index) { | 69 | separatorBuilder: (context, index) { |
| @@ -114,7 +115,7 @@ class _CreateThemeButton extends StatelessWidget { | @@ -114,7 +115,7 @@ class _CreateThemeButton extends StatelessWidget { | ||
| 114 | ), | 115 | ), |
| 115 | SizedBox(width: 8), | 116 | SizedBox(width: 8), |
| 116 | Text( | 117 | Text( |
| 117 | - '创作主题', | 118 | + context.l10n.watchThemeCreateTheme, |
| 118 | style: TextStyle( | 119 | style: TextStyle( |
| 119 | color: WatchThemeColors.textPrimary, | 120 | color: WatchThemeColors.textPrimary, |
| 120 | fontSize: 14, | 121 | fontSize: 14, |
| 1 | - | ||
| 2 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 3 | import 'package:get/get.dart'; | 2 | import 'package:get/get.dart'; |
| 3 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 4 | 4 | ||
| 5 | import 'watch_face_preview.dart'; | 5 | import 'watch_face_preview.dart'; |
| 6 | import 'watch_theme_section_card.dart'; | 6 | import 'watch_theme_section_card.dart'; |
| 7 | 7 | ||
| 8 | class DialPreviewCard extends StatelessWidget { | 8 | class DialPreviewCard extends StatelessWidget { |
| 9 | - bool showFriend; | 9 | + final bool showFriend; |
| 10 | final String? themeImageUrl; | 10 | final String? themeImageUrl; |
| 11 | final String? themeImageUrl2; | 11 | final String? themeImageUrl2; |
| 12 | final Function()? switchFriend; | 12 | final Function()? switchFriend; |
| 13 | - DialPreviewCard( | 13 | + const DialPreviewCard( |
| 14 | {super.key, | 14 | {super.key, |
| 15 | required this.showFriend, | 15 | required this.showFriend, |
| 16 | this.themeImageUrl, | 16 | this.themeImageUrl, |
| @@ -24,7 +24,8 @@ class DialPreviewCard extends StatelessWidget { | @@ -24,7 +24,8 @@ class DialPreviewCard extends StatelessWidget { | ||
| 24 | child: Column( | 24 | child: Column( |
| 25 | crossAxisAlignment: CrossAxisAlignment.start, | 25 | crossAxisAlignment: CrossAxisAlignment.start, |
| 26 | children: [ | 26 | children: [ |
| 27 | - const WatchThemeSectionTitle('表盘预览').paddingOnly(left: 20), | 27 | + WatchThemeSectionTitle(context.l10n.watchThemeDialPreview) |
| 28 | + .paddingOnly(left: 20), | ||
| 28 | SizedBox(height: 16), | 29 | SizedBox(height: 16), |
| 29 | SizedBox( | 30 | SizedBox( |
| 30 | height: showFriend ? 172 : 136, | 31 | height: showFriend ? 172 : 136, |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 2 | 3 | ||
| 3 | import '../models/watch_theme_models.dart'; | 4 | import '../models/watch_theme_models.dart'; |
| 4 | import 'watch_theme_character_avatar.dart'; | 5 | import 'watch_theme_character_avatar.dart'; |
| @@ -24,58 +25,58 @@ class OfficialThemeGrid extends StatelessWidget { | @@ -24,58 +25,58 @@ class OfficialThemeGrid extends StatelessWidget { | ||
| 24 | child: Column( | 25 | child: Column( |
| 25 | crossAxisAlignment: CrossAxisAlignment.start, | 26 | crossAxisAlignment: CrossAxisAlignment.start, |
| 26 | children: [ | 27 | children: [ |
| 27 | - const WatchThemeSectionTitle('官方主题'), | 28 | + WatchThemeSectionTitle(context.l10n.watchThemeOfficialTheme), |
| 28 | SizedBox(height: 22), | 29 | SizedBox(height: 22), |
| 29 | themes.isEmpty | 30 | themes.isEmpty |
| 30 | ? SizedBox( | 31 | ? SizedBox( |
| 31 | height: 114, | 32 | height: 114, |
| 32 | ) | 33 | ) |
| 33 | - : | ||
| 34 | - GridView.builder( | ||
| 35 | - shrinkWrap: true, | ||
| 36 | - padding: EdgeInsets.zero, | ||
| 37 | - physics: const NeverScrollableScrollPhysics(), | ||
| 38 | - itemCount: themes.length, | ||
| 39 | - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | ||
| 40 | - crossAxisCount: 3, | ||
| 41 | - mainAxisSpacing: 21, | ||
| 42 | - crossAxisSpacing: 19, | ||
| 43 | - mainAxisExtent: 114, | ||
| 44 | - ), | ||
| 45 | - itemBuilder: (context, index) { | ||
| 46 | - final theme = themes[index]; | ||
| 47 | - return GestureDetector( | ||
| 48 | - behavior: HitTestBehavior.opaque, | ||
| 49 | - onTap: () => onThemeTap(index), | ||
| 50 | - child: Column( | ||
| 51 | - children: [ | ||
| 52 | - WatchThemeSelectedView( | ||
| 53 | - selected: theme.id != null && theme.id == activeThemeId, | ||
| 54 | - size: 88, | ||
| 55 | - child: WatchThemeCharacterAvatar( | ||
| 56 | - size: 88, | ||
| 57 | - assetPath: theme.infoList.firstOrNull?.assetPath, | ||
| 58 | - imageUrl: theme.infoList.firstOrNull?.imgUrl, | 34 | + : GridView.builder( |
| 35 | + shrinkWrap: true, | ||
| 36 | + padding: EdgeInsets.zero, | ||
| 37 | + physics: const NeverScrollableScrollPhysics(), | ||
| 38 | + itemCount: themes.length, | ||
| 39 | + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( | ||
| 40 | + crossAxisCount: 3, | ||
| 41 | + mainAxisSpacing: 21, | ||
| 42 | + crossAxisSpacing: 19, | ||
| 43 | + mainAxisExtent: 114, | ||
| 44 | + ), | ||
| 45 | + itemBuilder: (context, index) { | ||
| 46 | + final theme = themes[index]; | ||
| 47 | + return GestureDetector( | ||
| 48 | + behavior: HitTestBehavior.opaque, | ||
| 49 | + onTap: () => onThemeTap(index), | ||
| 50 | + child: Column( | ||
| 51 | + children: [ | ||
| 52 | + WatchThemeSelectedView( | ||
| 53 | + selected: | ||
| 54 | + theme.id != null && theme.id == activeThemeId, | ||
| 55 | + size: 88, | ||
| 56 | + child: WatchThemeCharacterAvatar( | ||
| 57 | + size: 88, | ||
| 58 | + assetPath: theme.infoList.firstOrNull?.assetPath, | ||
| 59 | + imageUrl: theme.infoList.firstOrNull?.imgUrl, | ||
| 60 | + ), | ||
| 61 | + ), | ||
| 62 | + SizedBox(height: 8), | ||
| 63 | + Text( | ||
| 64 | + theme.title, | ||
| 65 | + textAlign: TextAlign.center, | ||
| 66 | + maxLines: 1, | ||
| 67 | + overflow: TextOverflow.ellipsis, | ||
| 68 | + style: TextStyle( | ||
| 69 | + color: WatchThemeColors.textPrimary, | ||
| 70 | + fontSize: 12, | ||
| 71 | + fontWeight: FontWeight.w400, | ||
| 72 | + height: 1.25, | ||
| 73 | + ), | ||
| 74 | + ), | ||
| 75 | + ], | ||
| 59 | ), | 76 | ), |
| 60 | - ), | ||
| 61 | - SizedBox(height: 8), | ||
| 62 | - Text( | ||
| 63 | - theme.title, | ||
| 64 | - textAlign: TextAlign.center, | ||
| 65 | - maxLines: 1, | ||
| 66 | - overflow: TextOverflow.ellipsis, | ||
| 67 | - style: TextStyle( | ||
| 68 | - color: WatchThemeColors.textPrimary, | ||
| 69 | - fontSize: 12, | ||
| 70 | - fontWeight: FontWeight.w400, | ||
| 71 | - height: 1.25, | ||
| 72 | - ), | ||
| 73 | - ), | ||
| 74 | - ], | 77 | + ); |
| 78 | + }, | ||
| 75 | ), | 79 | ), |
| 76 | - ); | ||
| 77 | - }, | ||
| 78 | - ), | ||
| 79 | ], | 80 | ], |
| 80 | ), | 81 | ), |
| 81 | ); | 82 | ); |
| 1 | import 'package:doublefeel_flutter/app/modules/watch_theme/models/watch_theme_models.dart'; | 1 | import 'package:doublefeel_flutter/app/modules/watch_theme/models/watch_theme_models.dart'; |
| 2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
| 3 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 3 | 4 | ||
| 4 | import 'watch_theme_character_avatar.dart'; | 5 | import 'watch_theme_character_avatar.dart'; |
| 5 | import 'watch_theme_section_card.dart'; | 6 | import 'watch_theme_section_card.dart'; |
| @@ -15,7 +16,7 @@ class StatusPreviewCard extends StatelessWidget { | @@ -15,7 +16,7 @@ class StatusPreviewCard extends StatelessWidget { | ||
| 15 | child: Column( | 16 | child: Column( |
| 16 | crossAxisAlignment: CrossAxisAlignment.start, | 17 | crossAxisAlignment: CrossAxisAlignment.start, |
| 17 | children: [ | 18 | children: [ |
| 18 | - const WatchThemeSectionTitle('状态预览'), | 19 | + WatchThemeSectionTitle(context.l10n.watchThemeStatusPreview), |
| 19 | const SizedBox(height: 24), | 20 | const SizedBox(height: 24), |
| 20 | Row( | 21 | Row( |
| 21 | mainAxisAlignment: MainAxisAlignment.spaceBetween, | 22 | mainAxisAlignment: MainAxisAlignment.spaceBetween, |
| @@ -3,6 +3,7 @@ import 'dart:io'; | @@ -3,6 +3,7 @@ import 'dart:io'; | ||
| 3 | import 'package:cached_network_image/cached_network_image.dart'; | 3 | import 'package:cached_network_image/cached_network_image.dart'; |
| 4 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; |
| 5 | import 'package:get/get.dart'; | 5 | import 'package:get/get.dart'; |
| 6 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 6 | 7 | ||
| 7 | enum WatchFacePreviewType { | 8 | enum WatchFacePreviewType { |
| 8 | surface, | 9 | surface, |
| @@ -64,17 +65,17 @@ class WatchFacePreview extends StatelessWidget { | @@ -64,17 +65,17 @@ class WatchFacePreview extends StatelessWidget { | ||
| 64 | children: [ | 65 | children: [ |
| 65 | Stack( | 66 | Stack( |
| 66 | alignment: Alignment.topCenter, | 67 | alignment: Alignment.topCenter, |
| 67 | - clipBehavior: Clip.none, | ||
| 68 | - children: [ | ||
| 69 | - Image( | ||
| 70 | - image: AssetImage(_backgroundAsset), | ||
| 71 | - width: size.width, | ||
| 72 | - height: size.height, | ||
| 73 | - fit: BoxFit.fitWidth, | 68 | + clipBehavior: Clip.none, |
| 69 | + children: [ | ||
| 70 | + Image( | ||
| 71 | + image: AssetImage(_backgroundAsset), | ||
| 72 | + width: size.width, | ||
| 73 | + height: size.height, | ||
| 74 | + fit: BoxFit.fitWidth, | ||
| 75 | + ), | ||
| 76 | + _buildThemeImages(), | ||
| 77 | + ], | ||
| 74 | ), | 78 | ), |
| 75 | - _buildThemeImages(), | ||
| 76 | - ], | ||
| 77 | - ), | ||
| 78 | type == WatchFacePreviewType.coupleSmall | 79 | type == WatchFacePreviewType.coupleSmall |
| 79 | ? GestureDetector( | 80 | ? GestureDetector( |
| 80 | onTap: switchFriend, | 81 | onTap: switchFriend, |
| @@ -86,7 +87,7 @@ class WatchFacePreview extends StatelessWidget { | @@ -86,7 +87,7 @@ class WatchFacePreview extends StatelessWidget { | ||
| 86 | border: Border.all(width: 1, color: Color(0xFFC3ADFF)), | 87 | border: Border.all(width: 1, color: Color(0xFFC3ADFF)), |
| 87 | borderRadius: BorderRadius.all(Radius.circular(12))), | 88 | borderRadius: BorderRadius.all(Radius.circular(12))), |
| 88 | child: Text( | 89 | child: Text( |
| 89 | - '切换好友', | 90 | + context.l10n.watchThemeSwitchFriend, |
| 90 | style: TextStyle( | 91 | style: TextStyle( |
| 91 | fontSize: 12, | 92 | fontSize: 12, |
| 92 | fontWeight: FontWeight.w600, | 93 | fontWeight: FontWeight.w600, |
| @@ -143,7 +144,7 @@ class WatchFacePreview extends StatelessWidget { | @@ -143,7 +144,7 @@ class WatchFacePreview extends StatelessWidget { | ||
| 143 | height: themeSize.height, | 144 | height: themeSize.height, |
| 144 | child: _buildFaceImage(themeImageUrl, | 145 | child: _buildFaceImage(themeImageUrl, |
| 145 | 'assets/images/watch_theme/official_default_green.png'), | 146 | 'assets/images/watch_theme/official_default_green.png'), |
| 146 | - ), | 147 | + ), |
| 147 | SizedBox( | 148 | SizedBox( |
| 148 | width: 12, | 149 | width: 12, |
| 149 | ), | 150 | ), |
| 1 | - | ||
| 2 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 3 | 3 | ||
| 4 | import 'watch_theme_colors.dart'; | 4 | import 'watch_theme_colors.dart'; |
| 5 | 5 | ||
| @@ -26,7 +26,7 @@ class WatchThemeBottomActions extends StatelessWidget { | @@ -26,7 +26,7 @@ class WatchThemeBottomActions extends StatelessWidget { | ||
| 26 | children: [ | 26 | children: [ |
| 27 | Expanded( | 27 | Expanded( |
| 28 | child: _ActionButton( | 28 | child: _ActionButton( |
| 29 | - label: '添加表盘', | 29 | + label: context.l10n.watchThemeAddWatchFace, |
| 30 | color: WatchThemeColors.brand, | 30 | color: WatchThemeColors.brand, |
| 31 | textColor: Colors.white, | 31 | textColor: Colors.white, |
| 32 | onTap: onAddTap, | 32 | onTap: onAddTap, |
| @@ -35,7 +35,9 @@ class WatchThemeBottomActions extends StatelessWidget { | @@ -35,7 +35,9 @@ class WatchThemeBottomActions extends StatelessWidget { | ||
| 35 | SizedBox(width: 12), | 35 | SizedBox(width: 12), |
| 36 | Expanded( | 36 | Expanded( |
| 37 | child: _ActionButton( | 37 | child: _ActionButton( |
| 38 | - label: isInUsage ? '正在使用' : '立即使用', | 38 | + label: isInUsage |
| 39 | + ? context.l10n.watchThemeInUse | ||
| 40 | + : context.l10n.watchThemeUseNow, | ||
| 39 | color: isInUsage | 41 | color: isInUsage |
| 40 | ? WatchThemeColors.brand.withValues(alpha: 0.4) | 42 | ? WatchThemeColors.brand.withValues(alpha: 0.4) |
| 41 | : WatchThemeColors.brand, | 43 | : WatchThemeColors.brand, |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:get/get.dart'; | 2 | import 'package:get/get.dart'; |
| 3 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 3 | 4 | ||
| 4 | class WatchThemeRenameDialog extends StatefulWidget { | 5 | class WatchThemeRenameDialog extends StatefulWidget { |
| 5 | const WatchThemeRenameDialog({super.key, required this.initialValue}); | 6 | const WatchThemeRenameDialog({super.key, required this.initialValue}); |
| @@ -40,9 +41,9 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> { | @@ -40,9 +41,9 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> { | ||
| 40 | child: Column( | 41 | child: Column( |
| 41 | mainAxisSize: MainAxisSize.min, | 42 | mainAxisSize: MainAxisSize.min, |
| 42 | children: [ | 43 | children: [ |
| 43 | - const Text( | ||
| 44 | - '修改状态名称', | ||
| 45 | - style: TextStyle( | 44 | + Text( |
| 45 | + context.l10n.watchThemeRenameStatus, | ||
| 46 | + style: const TextStyle( | ||
| 46 | color: Color(0xFF141414), | 47 | color: Color(0xFF141414), |
| 47 | fontSize: 18, | 48 | fontSize: 18, |
| 48 | fontWeight: FontWeight.w600, | 49 | fontWeight: FontWeight.w600, |
| @@ -66,10 +67,11 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> { | @@ -66,10 +67,11 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> { | ||
| 66 | child: TextField( | 67 | child: TextField( |
| 67 | controller: _controller, | 68 | controller: _controller, |
| 68 | maxLength: 4, | 69 | maxLength: 4, |
| 69 | - decoration: const InputDecoration( | 70 | + decoration: InputDecoration( |
| 70 | counterText: '', | 71 | counterText: '', |
| 71 | - hintText: '请输入昵称', | ||
| 72 | - hintStyle: TextStyle(color: Color(0xFFB0B0B6)), | 72 | + hintText: context.l10n.watchThemeEnterNickname, |
| 73 | + hintStyle: | ||
| 74 | + const TextStyle(color: Color(0xFFB0B0B6)), | ||
| 73 | border: InputBorder.none, | 75 | border: InputBorder.none, |
| 74 | isCollapsed: true, | 76 | isCollapsed: true, |
| 75 | ), | 77 | ), |
| @@ -105,9 +107,9 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> { | @@ -105,9 +107,9 @@ class _WatchThemeRenameDialogState extends State<WatchThemeRenameDialog> { | ||
| 105 | color: const Color(0xFF845EEE), | 107 | color: const Color(0xFF845EEE), |
| 106 | borderRadius: BorderRadius.circular(24), | 108 | borderRadius: BorderRadius.circular(24), |
| 107 | ), | 109 | ), |
| 108 | - child: const Text( | ||
| 109 | - '保存', | ||
| 110 | - style: TextStyle( | 110 | + child: Text( |
| 111 | + context.l10n.watchThemeSave, | ||
| 112 | + style: const TextStyle( | ||
| 111 | color: Colors.white, | 113 | color: Colors.white, |
| 112 | fontSize: 14, | 114 | fontSize: 14, |
| 113 | fontWeight: FontWeight.w500, | 115 | fontWeight: FontWeight.w500, |
| 1 | import 'package:doublefeel_flutter/core/util/size_extensions.dart'; | 1 | import 'package:doublefeel_flutter/core/util/size_extensions.dart'; |
| 2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
| 3 | import 'package:get/get.dart'; | 3 | import 'package:get/get.dart'; |
| 4 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 4 | 5 | ||
| 5 | import 'watch_theme_colors.dart'; | 6 | import 'watch_theme_colors.dart'; |
| 6 | 7 | ||
| @@ -37,7 +38,7 @@ class WatchThemeFriendPickerDialog extends StatelessWidget { | @@ -37,7 +38,7 @@ class WatchThemeFriendPickerDialog extends StatelessWidget { | ||
| 37 | alignment: Alignment.center, | 38 | alignment: Alignment.center, |
| 38 | children: [ | 39 | children: [ |
| 39 | Text( | 40 | Text( |
| 40 | - '选择好友', | 41 | + context.l10n.watchThemeSelectFriend, |
| 41 | style: TextStyle( | 42 | style: TextStyle( |
| 42 | color: WatchThemeColors.textPrimary, | 43 | color: WatchThemeColors.textPrimary, |
| 43 | fontSize: 16.dp, | 44 | fontSize: 16.dp, |
| @@ -90,7 +91,7 @@ class WatchThemeFriendPickerDialog extends StatelessWidget { | @@ -90,7 +91,7 @@ class WatchThemeFriendPickerDialog extends StatelessWidget { | ||
| 90 | borderRadius: BorderRadius.circular(24.dp), | 91 | borderRadius: BorderRadius.circular(24.dp), |
| 91 | ), | 92 | ), |
| 92 | child: Text( | 93 | child: Text( |
| 93 | - '选择并同步至表盘', | 94 | + context.l10n.watchThemeSelectAndSync, |
| 94 | style: TextStyle( | 95 | style: TextStyle( |
| 95 | color: Colors.white, | 96 | color: Colors.white, |
| 96 | fontSize: 16.dp, | 97 | fontSize: 16.dp, |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 2 | 3 | ||
| 3 | import 'watch_face_preview.dart'; | 4 | import 'watch_face_preview.dart'; |
| 4 | import 'watch_theme_colors.dart'; | 5 | import 'watch_theme_colors.dart'; |
| @@ -6,11 +7,11 @@ import 'watch_theme_colors.dart'; | @@ -6,11 +7,11 @@ import 'watch_theme_colors.dart'; | ||
| 6 | class WatchThemeHeader extends StatelessWidget { | 7 | class WatchThemeHeader extends StatelessWidget { |
| 7 | const WatchThemeHeader({ | 8 | const WatchThemeHeader({ |
| 8 | super.key, | 9 | super.key, |
| 9 | - this.title = '默认主题', | 10 | + this.title, |
| 10 | this.themeImageUrl, | 11 | this.themeImageUrl, |
| 11 | }); | 12 | }); |
| 12 | 13 | ||
| 13 | - final String title; | 14 | + final String? title; |
| 14 | final String? themeImageUrl; | 15 | final String? themeImageUrl; |
| 15 | 16 | ||
| 16 | @override | 17 | @override |
| @@ -26,7 +27,7 @@ class WatchThemeHeader extends StatelessWidget { | @@ -26,7 +27,7 @@ class WatchThemeHeader extends StatelessWidget { | ||
| 26 | ), | 27 | ), |
| 27 | SizedBox(height: 12), | 28 | SizedBox(height: 12), |
| 28 | Text( | 29 | Text( |
| 29 | - title, | 30 | + title ?? context.l10n.watchThemeDefaultTheme, |
| 30 | style: TextStyle( | 31 | style: TextStyle( |
| 31 | color: WatchThemeColors.textPrimary, | 32 | color: WatchThemeColors.textPrimary, |
| 32 | fontSize: 20, | 33 | fontSize: 20, |
| 1 | import 'package:doublefeel_flutter/core/util/size_extensions.dart'; | 1 | import 'package:doublefeel_flutter/core/util/size_extensions.dart'; |
| 2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
| 3 | import 'package:get/get.dart'; | 3 | import 'package:get/get.dart'; |
| 4 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 4 | 5 | ||
| 5 | import 'watch_theme_colors.dart'; | 6 | import 'watch_theme_colors.dart'; |
| 6 | 7 | ||
| @@ -23,7 +24,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget { | @@ -23,7 +24,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget { | ||
| 23 | mainAxisSize: MainAxisSize.min, | 24 | mainAxisSize: MainAxisSize.min, |
| 24 | children: [ | 25 | children: [ |
| 25 | Text( | 26 | Text( |
| 26 | - '未找到苹果手表', | 27 | + context.l10n.watchThemeNoWatchTitle, |
| 27 | textAlign: TextAlign.center, | 28 | textAlign: TextAlign.center, |
| 28 | style: TextStyle( | 29 | style: TextStyle( |
| 29 | color: const Color(0xFF141414), | 30 | color: const Color(0xFF141414), |
| @@ -33,7 +34,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget { | @@ -33,7 +34,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget { | ||
| 33 | ), | 34 | ), |
| 34 | SizedBox(height: 16.dp), | 35 | SizedBox(height: 16.dp), |
| 35 | Text( | 36 | Text( |
| 36 | - '请配对苹果手表后再尝试', | 37 | + context.l10n.watchThemeNoWatchMessage, |
| 37 | textAlign: TextAlign.center, | 38 | textAlign: TextAlign.center, |
| 38 | style: TextStyle( | 39 | style: TextStyle( |
| 39 | color: const Color(0xFF6E6D80), | 40 | color: const Color(0xFF6E6D80), |
| @@ -53,7 +54,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget { | @@ -53,7 +54,7 @@ class WatchThemeNoWatchDialog extends StatelessWidget { | ||
| 53 | borderRadius: BorderRadius.circular(24.dp), | 54 | borderRadius: BorderRadius.circular(24.dp), |
| 54 | ), | 55 | ), |
| 55 | child: Text( | 56 | child: Text( |
| 56 | - '好的', | 57 | + context.l10n.watchThemeOk, |
| 57 | style: TextStyle( | 58 | style: TextStyle( |
| 58 | color: Colors.white, | 59 | color: Colors.white, |
| 59 | fontSize: 14.dp, | 60 | fontSize: 14.dp, |
| 1 | import 'package:doublefeel_flutter/core/util/size_extensions.dart'; | 1 | import 'package:doublefeel_flutter/core/util/size_extensions.dart'; |
| 2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
| 3 | import 'package:get/get.dart'; | 3 | import 'package:get/get.dart'; |
| 4 | +import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | ||
| 4 | 5 | ||
| 5 | import 'watch_face_preview.dart'; | 6 | import 'watch_face_preview.dart'; |
| 6 | import 'watch_theme_colors.dart'; | 7 | import 'watch_theme_colors.dart'; |
| @@ -104,7 +105,7 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> { | @@ -104,7 +105,7 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> { | ||
| 104 | _WatchThemeSyncState.intro => Padding( | 105 | _WatchThemeSyncState.intro => Padding( |
| 105 | padding: EdgeInsets.symmetric(horizontal: 46.dp), | 106 | padding: EdgeInsets.symmetric(horizontal: 46.dp), |
| 106 | child: Text( | 107 | child: Text( |
| 107 | - '请先打开DoubleFeel手表端App,然后点击下方的“下一步”按钮', | 108 | + context.l10n.watchThemeSyncIntro, |
| 108 | textAlign: TextAlign.center, | 109 | textAlign: TextAlign.center, |
| 109 | style: TextStyle( | 110 | style: TextStyle( |
| 110 | color: WatchThemeColors.textPrimary, | 111 | color: WatchThemeColors.textPrimary, |
| @@ -114,7 +115,7 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> { | @@ -114,7 +115,7 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> { | ||
| 114 | ), | 115 | ), |
| 115 | ), | 116 | ), |
| 116 | _WatchThemeSyncState.syncing => Text( | 117 | _WatchThemeSyncState.syncing => Text( |
| 117 | - '请保持打开手表App,等待同步', | 118 | + context.l10n.watchThemeSyncWaiting, |
| 118 | textAlign: TextAlign.center, | 119 | textAlign: TextAlign.center, |
| 119 | style: TextStyle( | 120 | style: TextStyle( |
| 120 | color: WatchThemeColors.textPrimary, | 121 | color: WatchThemeColors.textPrimary, |
| @@ -141,7 +142,9 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> { | @@ -141,7 +142,9 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> { | ||
| 141 | ), | 142 | ), |
| 142 | SizedBox(width: 4.dp), | 143 | SizedBox(width: 4.dp), |
| 143 | Text( | 144 | Text( |
| 144 | - _success ? '同步完成' : '同步失败', | 145 | + _success |
| 146 | + ? context.l10n.watchThemeSyncComplete | ||
| 147 | + : context.l10n.watchThemeSyncFailed, | ||
| 145 | style: TextStyle( | 148 | style: TextStyle( |
| 146 | color: WatchThemeColors.textPrimary, | 149 | color: WatchThemeColors.textPrimary, |
| 147 | fontSize: 14.dp, | 150 | fontSize: 14.dp, |
| @@ -155,12 +158,12 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> { | @@ -155,12 +158,12 @@ class _WatchThemeSyncDialogState extends State<WatchThemeSyncDialog> { | ||
| 155 | Widget _buildAction() { | 158 | Widget _buildAction() { |
| 156 | return switch (_state) { | 159 | return switch (_state) { |
| 157 | _WatchThemeSyncState.intro => _PrimaryButton( | 160 | _WatchThemeSyncState.intro => _PrimaryButton( |
| 158 | - label: '下一步', | 161 | + label: context.l10n.watchThemeNext, |
| 159 | onTap: _startSync, | 162 | onTap: _startSync, |
| 160 | ), | 163 | ), |
| 161 | _WatchThemeSyncState.syncing => const _ProgressButton(progress: 0.85), | 164 | _WatchThemeSyncState.syncing => const _ProgressButton(progress: 0.85), |
| 162 | _WatchThemeSyncState.done => _PrimaryButton( | 165 | _WatchThemeSyncState.done => _PrimaryButton( |
| 163 | - label: '好的', | 166 | + label: context.l10n.watchThemeOk, |
| 164 | onTap: Get.back, | 167 | onTap: Get.back, |
| 165 | ), | 168 | ), |
| 166 | }; | 169 | }; |
| @@ -223,7 +226,9 @@ class _ProgressButton extends StatelessWidget { | @@ -223,7 +226,9 @@ class _ProgressButton extends StatelessWidget { | ||
| 223 | ), | 226 | ), |
| 224 | Center( | 227 | Center( |
| 225 | child: Text( | 228 | child: Text( |
| 226 | - '同步中 ${(progress * 100).round()}%', | 229 | + context.l10n.watchThemeSyncingProgress( |
| 230 | + (progress * 100).round(), | ||
| 231 | + ), | ||
| 227 | style: TextStyle( | 232 | style: TextStyle( |
| 228 | color: Colors.white, | 233 | color: Colors.white, |
| 229 | fontSize: 16.dp, | 234 | fontSize: 16.dp, |
| @@ -578,5 +578,66 @@ | @@ -578,5 +578,66 @@ | ||
| 578 | "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.", | 578 | "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.", |
| 579 | "noHealthDataError3Title": "Error 3: System Issue", | 579 | "noHealthDataError3Title": "Error 3: System Issue", |
| 580 | "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.", | 580 | "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.", |
| 581 | - "noHealthDataGoToSettings": "Go to Settings" | ||
| 582 | -} | ||
| 581 | + "noHealthDataGoToSettings": "Go to Settings", | ||
| 582 | + "watchThemeDefaultTheme": "Default Theme", | ||
| 583 | + "watchThemeNoWatchTitle": "Apple Watch Not Found", | ||
| 584 | + "watchThemeNoWatchMessage": "Pair an Apple Watch and try again", | ||
| 585 | + "watchThemeOk": "OK", | ||
| 586 | + "watchThemeSelectFriend": "Select Friend", | ||
| 587 | + "watchThemeSelectAndSync": "Select and Sync to Watch Face", | ||
| 588 | + "watchThemeCustomTheme": "Custom Themes", | ||
| 589 | + "watchThemeCustomDescription": "Capture every mood with your creativity and make a watch face that's uniquely yours.", | ||
| 590 | + "watchThemeCreateTheme": "Create Theme", | ||
| 591 | + "watchThemeOfficialTheme": "Official Themes", | ||
| 592 | + "watchThemeRenameStatus": "Rename Status", | ||
| 593 | + "watchThemeEnterNickname": "Enter a name", | ||
| 594 | + "watchThemeSave": "Save", | ||
| 595 | + "watchThemeDialPreview": "Watch Face Preview", | ||
| 596 | + "watchThemeSwitchFriend": "Switch Friend", | ||
| 597 | + "watchThemeStatusPreview": "Status Preview", | ||
| 598 | + "watchThemeAddWatchFace": "Add Watch Face", | ||
| 599 | + "watchThemeInUse": "In Use", | ||
| 600 | + "watchThemeUseNow": "Use Now", | ||
| 601 | + "watchThemeSyncIntro": "Open the DoubleFeel app on your Apple Watch, then tap Next below.", | ||
| 602 | + "watchThemeSyncWaiting": "Keep the Watch app open while syncing", | ||
| 603 | + "watchThemeSyncComplete": "Sync Complete", | ||
| 604 | + "watchThemeSyncFailed": "Sync Failed", | ||
| 605 | + "watchThemeNext": "Next", | ||
| 606 | + "watchThemeSyncingProgress": "Syncing {progress}%", | ||
| 607 | + "@watchThemeSyncingProgress": { | ||
| 608 | + "placeholders": { | ||
| 609 | + "progress": { | ||
| 610 | + "type": "int" | ||
| 611 | + } | ||
| 612 | + } | ||
| 613 | + }, | ||
| 614 | + "watchThemePreview": "Preview", | ||
| 615 | + "watchThemeDelete": "Delete", | ||
| 616 | + "watchThemePageTitle": "Watch Themes", | ||
| 617 | + "watchThemeImagesOnly": "Images only", | ||
| 618 | + "watchThemeName": "Theme Name", | ||
| 619 | + "watchThemeNameMaxLength": "Up to 10 characters", | ||
| 620 | + "watchThemeSubmissionAgreement": "I have read and agree to the User Submission Agreement", | ||
| 621 | + "watchThemeSaving": "Saving", | ||
| 622 | + "watchThemeSaveTheme": "Save Theme", | ||
| 623 | + "watchThemeExcellent": "Excellent", | ||
| 624 | + "watchThemeNormal": "Normal", | ||
| 625 | + "watchThemeSlightStressful": "Watch Your Stress", | ||
| 626 | + "watchThemeStressful": "Stress Overload", | ||
| 627 | + "watchThemeCropImage": "Crop Watch Face Image", | ||
| 628 | + "watchThemeImageProcessFailed": "Image processing failed. Please try again", | ||
| 629 | + "watchThemeAbandonEdit": "Discard Changes", | ||
| 630 | + "watchThemeAbandonMessage": "Your changes won't be saved if you close this page. Discard them?", | ||
| 631 | + "watchThemeContinueEditing": "Continue Editing", | ||
| 632 | + "watchThemeImageUploadFailed": "Image upload failed. Please try again", | ||
| 633 | + "watchThemeCreateFailed": "Failed to create watch face. Please try again", | ||
| 634 | + "watchThemeDeleteTheme": "Delete Theme", | ||
| 635 | + "watchThemeDeleteMessage": "Deleted themes cannot be restored. Delete this theme?", | ||
| 636 | + "watchThemeCancel": "Cancel", | ||
| 637 | + "watchThemeDeleteFailed": "Failed to delete theme", | ||
| 638 | + "watchThemeDeleted": "Theme deleted", | ||
| 639 | + "watchThemeIncomplete": "Theme information is incomplete", | ||
| 640 | + "watchThemeApplyFailed": "Failed to apply theme", | ||
| 641 | + "watchThemeWatchSyncFailed": "Watch face sync failed", | ||
| 642 | + "watchThemePurchaseChannel": "Watch Face Themes" | ||
| 643 | +} |
| @@ -866,5 +866,66 @@ | @@ -866,5 +866,66 @@ | ||
| 866 | "noHealthDataError2Body": "DoubleFeel 需要访问 Apple Health 数据的权限,以提供压力统计、提醒和建议。如果未授权,部分功能可能无法正常使用。\n\n请放心,所有健康数据仅存储在本地,不会上传。\n\n要启用权限,请按提示操作,并在 iOS 设置中选择 允许所有 → 健康 → DoubleFeel。", | 866 | "noHealthDataError2Body": "DoubleFeel 需要访问 Apple Health 数据的权限,以提供压力统计、提醒和建议。如果未授权,部分功能可能无法正常使用。\n\n请放心,所有健康数据仅存储在本地,不会上传。\n\n要启用权限,请按提示操作,并在 iOS 设置中选择 允许所有 → 健康 → DoubleFeel。", |
| 867 | "noHealthDataError3Title": "错误 3:系统问题", | 867 | "noHealthDataError3Title": "错误 3:系统问题", |
| 868 | "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。", | 868 | "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。", |
| 869 | - "noHealthDataGoToSettings": "前往开启" | ||
| 870 | -} | ||
| 869 | + "noHealthDataGoToSettings": "前往开启", | ||
| 870 | + "watchThemeDefaultTheme": "默认主题", | ||
| 871 | + "watchThemeNoWatchTitle": "未找到苹果手表", | ||
| 872 | + "watchThemeNoWatchMessage": "请配对苹果手表后再尝试", | ||
| 873 | + "watchThemeOk": "好的", | ||
| 874 | + "watchThemeSelectFriend": "选择好友", | ||
| 875 | + "watchThemeSelectAndSync": "选择并同步至表盘", | ||
| 876 | + "watchThemeCustomTheme": "自定义主题", | ||
| 877 | + "watchThemeCustomDescription": "用创意记录每一次情绪波动,打造懂你的专属表盘吧~", | ||
| 878 | + "watchThemeCreateTheme": "创作主题", | ||
| 879 | + "watchThemeOfficialTheme": "官方主题", | ||
| 880 | + "watchThemeRenameStatus": "修改状态名称", | ||
| 881 | + "watchThemeEnterNickname": "请输入昵称", | ||
| 882 | + "watchThemeSave": "保存", | ||
| 883 | + "watchThemeDialPreview": "表盘预览", | ||
| 884 | + "watchThemeSwitchFriend": "切换好友", | ||
| 885 | + "watchThemeStatusPreview": "状态预览", | ||
| 886 | + "watchThemeAddWatchFace": "添加表盘", | ||
| 887 | + "watchThemeInUse": "正在使用", | ||
| 888 | + "watchThemeUseNow": "立即使用", | ||
| 889 | + "watchThemeSyncIntro": "请先打开DoubleFeel手表端App,然后点击下方的“下一步”按钮", | ||
| 890 | + "watchThemeSyncWaiting": "请保持打开手表App,等待同步", | ||
| 891 | + "watchThemeSyncComplete": "同步完成", | ||
| 892 | + "watchThemeSyncFailed": "同步失败", | ||
| 893 | + "watchThemeNext": "下一步", | ||
| 894 | + "watchThemeSyncingProgress": "同步中 {progress}%", | ||
| 895 | + "@watchThemeSyncingProgress": { | ||
| 896 | + "placeholders": { | ||
| 897 | + "progress": { | ||
| 898 | + "type": "int" | ||
| 899 | + } | ||
| 900 | + } | ||
| 901 | + }, | ||
| 902 | + "watchThemePreview": "预览", | ||
| 903 | + "watchThemeDelete": "删除", | ||
| 904 | + "watchThemePageTitle": "Watch主题", | ||
| 905 | + "watchThemeImagesOnly": "仅支持上传图片", | ||
| 906 | + "watchThemeName": "主题名称", | ||
| 907 | + "watchThemeNameMaxLength": "最多10个字符", | ||
| 908 | + "watchThemeSubmissionAgreement": "我已阅读并同意用户投稿协议", | ||
| 909 | + "watchThemeSaving": "保存中", | ||
| 910 | + "watchThemeSaveTheme": "保存主题", | ||
| 911 | + "watchThemeExcellent": "状态优秀", | ||
| 912 | + "watchThemeNormal": "状态正常", | ||
| 913 | + "watchThemeSlightStressful": "注意压力", | ||
| 914 | + "watchThemeStressful": "压力过载", | ||
| 915 | + "watchThemeCropImage": "裁剪表盘图片", | ||
| 916 | + "watchThemeImageProcessFailed": "图片处理失败,请重试", | ||
| 917 | + "watchThemeAbandonEdit": "放弃编辑", | ||
| 918 | + "watchThemeAbandonMessage": "关闭此页面后,已编辑的内容不会保留,是否放弃编辑?", | ||
| 919 | + "watchThemeContinueEditing": "继续编辑", | ||
| 920 | + "watchThemeImageUploadFailed": "图片上传失败,请重试", | ||
| 921 | + "watchThemeCreateFailed": "创建表盘失败,请重试", | ||
| 922 | + "watchThemeDeleteTheme": "删除主题", | ||
| 923 | + "watchThemeDeleteMessage": "主题删除后无法恢复,确认删除该主题吗?", | ||
| 924 | + "watchThemeCancel": "取消", | ||
| 925 | + "watchThemeDeleteFailed": "删除主题失败", | ||
| 926 | + "watchThemeDeleted": "已删除主题", | ||
| 927 | + "watchThemeIncomplete": "主题信息不完整", | ||
| 928 | + "watchThemeApplyFailed": "应用主题失败", | ||
| 929 | + "watchThemeWatchSyncFailed": "表盘同步失败", | ||
| 930 | + "watchThemePurchaseChannel": "表盘主题" | ||
| 931 | +} |
| @@ -3428,6 +3428,330 @@ abstract class AppLocalizations { | @@ -3428,6 +3428,330 @@ abstract class AppLocalizations { | ||
| 3428 | /// In zh, this message translates to: | 3428 | /// In zh, this message translates to: |
| 3429 | /// **'前往开启'** | 3429 | /// **'前往开启'** |
| 3430 | String get noHealthDataGoToSettings; | 3430 | String get noHealthDataGoToSettings; |
| 3431 | + | ||
| 3432 | + /// No description provided for @watchThemeDefaultTheme. | ||
| 3433 | + /// | ||
| 3434 | + /// In zh, this message translates to: | ||
| 3435 | + /// **'默认主题'** | ||
| 3436 | + String get watchThemeDefaultTheme; | ||
| 3437 | + | ||
| 3438 | + /// No description provided for @watchThemeNoWatchTitle. | ||
| 3439 | + /// | ||
| 3440 | + /// In zh, this message translates to: | ||
| 3441 | + /// **'未找到苹果手表'** | ||
| 3442 | + String get watchThemeNoWatchTitle; | ||
| 3443 | + | ||
| 3444 | + /// No description provided for @watchThemeNoWatchMessage. | ||
| 3445 | + /// | ||
| 3446 | + /// In zh, this message translates to: | ||
| 3447 | + /// **'请配对苹果手表后再尝试'** | ||
| 3448 | + String get watchThemeNoWatchMessage; | ||
| 3449 | + | ||
| 3450 | + /// No description provided for @watchThemeOk. | ||
| 3451 | + /// | ||
| 3452 | + /// In zh, this message translates to: | ||
| 3453 | + /// **'好的'** | ||
| 3454 | + String get watchThemeOk; | ||
| 3455 | + | ||
| 3456 | + /// No description provided for @watchThemeSelectFriend. | ||
| 3457 | + /// | ||
| 3458 | + /// In zh, this message translates to: | ||
| 3459 | + /// **'选择好友'** | ||
| 3460 | + String get watchThemeSelectFriend; | ||
| 3461 | + | ||
| 3462 | + /// No description provided for @watchThemeSelectAndSync. | ||
| 3463 | + /// | ||
| 3464 | + /// In zh, this message translates to: | ||
| 3465 | + /// **'选择并同步至表盘'** | ||
| 3466 | + String get watchThemeSelectAndSync; | ||
| 3467 | + | ||
| 3468 | + /// No description provided for @watchThemeCustomTheme. | ||
| 3469 | + /// | ||
| 3470 | + /// In zh, this message translates to: | ||
| 3471 | + /// **'自定义主题'** | ||
| 3472 | + String get watchThemeCustomTheme; | ||
| 3473 | + | ||
| 3474 | + /// No description provided for @watchThemeCustomDescription. | ||
| 3475 | + /// | ||
| 3476 | + /// In zh, this message translates to: | ||
| 3477 | + /// **'用创意记录每一次情绪波动,打造懂你的专属表盘吧~'** | ||
| 3478 | + String get watchThemeCustomDescription; | ||
| 3479 | + | ||
| 3480 | + /// No description provided for @watchThemeCreateTheme. | ||
| 3481 | + /// | ||
| 3482 | + /// In zh, this message translates to: | ||
| 3483 | + /// **'创作主题'** | ||
| 3484 | + String get watchThemeCreateTheme; | ||
| 3485 | + | ||
| 3486 | + /// No description provided for @watchThemeOfficialTheme. | ||
| 3487 | + /// | ||
| 3488 | + /// In zh, this message translates to: | ||
| 3489 | + /// **'官方主题'** | ||
| 3490 | + String get watchThemeOfficialTheme; | ||
| 3491 | + | ||
| 3492 | + /// No description provided for @watchThemeRenameStatus. | ||
| 3493 | + /// | ||
| 3494 | + /// In zh, this message translates to: | ||
| 3495 | + /// **'修改状态名称'** | ||
| 3496 | + String get watchThemeRenameStatus; | ||
| 3497 | + | ||
| 3498 | + /// No description provided for @watchThemeEnterNickname. | ||
| 3499 | + /// | ||
| 3500 | + /// In zh, this message translates to: | ||
| 3501 | + /// **'请输入昵称'** | ||
| 3502 | + String get watchThemeEnterNickname; | ||
| 3503 | + | ||
| 3504 | + /// No description provided for @watchThemeSave. | ||
| 3505 | + /// | ||
| 3506 | + /// In zh, this message translates to: | ||
| 3507 | + /// **'保存'** | ||
| 3508 | + String get watchThemeSave; | ||
| 3509 | + | ||
| 3510 | + /// No description provided for @watchThemeDialPreview. | ||
| 3511 | + /// | ||
| 3512 | + /// In zh, this message translates to: | ||
| 3513 | + /// **'表盘预览'** | ||
| 3514 | + String get watchThemeDialPreview; | ||
| 3515 | + | ||
| 3516 | + /// No description provided for @watchThemeSwitchFriend. | ||
| 3517 | + /// | ||
| 3518 | + /// In zh, this message translates to: | ||
| 3519 | + /// **'切换好友'** | ||
| 3520 | + String get watchThemeSwitchFriend; | ||
| 3521 | + | ||
| 3522 | + /// No description provided for @watchThemeStatusPreview. | ||
| 3523 | + /// | ||
| 3524 | + /// In zh, this message translates to: | ||
| 3525 | + /// **'状态预览'** | ||
| 3526 | + String get watchThemeStatusPreview; | ||
| 3527 | + | ||
| 3528 | + /// No description provided for @watchThemeAddWatchFace. | ||
| 3529 | + /// | ||
| 3530 | + /// In zh, this message translates to: | ||
| 3531 | + /// **'添加表盘'** | ||
| 3532 | + String get watchThemeAddWatchFace; | ||
| 3533 | + | ||
| 3534 | + /// No description provided for @watchThemeInUse. | ||
| 3535 | + /// | ||
| 3536 | + /// In zh, this message translates to: | ||
| 3537 | + /// **'正在使用'** | ||
| 3538 | + String get watchThemeInUse; | ||
| 3539 | + | ||
| 3540 | + /// No description provided for @watchThemeUseNow. | ||
| 3541 | + /// | ||
| 3542 | + /// In zh, this message translates to: | ||
| 3543 | + /// **'立即使用'** | ||
| 3544 | + String get watchThemeUseNow; | ||
| 3545 | + | ||
| 3546 | + /// No description provided for @watchThemeSyncIntro. | ||
| 3547 | + /// | ||
| 3548 | + /// In zh, this message translates to: | ||
| 3549 | + /// **'请先打开DoubleFeel手表端App,然后点击下方的“下一步”按钮'** | ||
| 3550 | + String get watchThemeSyncIntro; | ||
| 3551 | + | ||
| 3552 | + /// No description provided for @watchThemeSyncWaiting. | ||
| 3553 | + /// | ||
| 3554 | + /// In zh, this message translates to: | ||
| 3555 | + /// **'请保持打开手表App,等待同步'** | ||
| 3556 | + String get watchThemeSyncWaiting; | ||
| 3557 | + | ||
| 3558 | + /// No description provided for @watchThemeSyncComplete. | ||
| 3559 | + /// | ||
| 3560 | + /// In zh, this message translates to: | ||
| 3561 | + /// **'同步完成'** | ||
| 3562 | + String get watchThemeSyncComplete; | ||
| 3563 | + | ||
| 3564 | + /// No description provided for @watchThemeSyncFailed. | ||
| 3565 | + /// | ||
| 3566 | + /// In zh, this message translates to: | ||
| 3567 | + /// **'同步失败'** | ||
| 3568 | + String get watchThemeSyncFailed; | ||
| 3569 | + | ||
| 3570 | + /// No description provided for @watchThemeNext. | ||
| 3571 | + /// | ||
| 3572 | + /// In zh, this message translates to: | ||
| 3573 | + /// **'下一步'** | ||
| 3574 | + String get watchThemeNext; | ||
| 3575 | + | ||
| 3576 | + /// No description provided for @watchThemeSyncingProgress. | ||
| 3577 | + /// | ||
| 3578 | + /// In zh, this message translates to: | ||
| 3579 | + /// **'同步中 {progress}%'** | ||
| 3580 | + String watchThemeSyncingProgress(int progress); | ||
| 3581 | + | ||
| 3582 | + /// No description provided for @watchThemePreview. | ||
| 3583 | + /// | ||
| 3584 | + /// In zh, this message translates to: | ||
| 3585 | + /// **'预览'** | ||
| 3586 | + String get watchThemePreview; | ||
| 3587 | + | ||
| 3588 | + /// No description provided for @watchThemeDelete. | ||
| 3589 | + /// | ||
| 3590 | + /// In zh, this message translates to: | ||
| 3591 | + /// **'删除'** | ||
| 3592 | + String get watchThemeDelete; | ||
| 3593 | + | ||
| 3594 | + /// No description provided for @watchThemePageTitle. | ||
| 3595 | + /// | ||
| 3596 | + /// In zh, this message translates to: | ||
| 3597 | + /// **'Watch主题'** | ||
| 3598 | + String get watchThemePageTitle; | ||
| 3599 | + | ||
| 3600 | + /// No description provided for @watchThemeImagesOnly. | ||
| 3601 | + /// | ||
| 3602 | + /// In zh, this message translates to: | ||
| 3603 | + /// **'仅支持上传图片'** | ||
| 3604 | + String get watchThemeImagesOnly; | ||
| 3605 | + | ||
| 3606 | + /// No description provided for @watchThemeName. | ||
| 3607 | + /// | ||
| 3608 | + /// In zh, this message translates to: | ||
| 3609 | + /// **'主题名称'** | ||
| 3610 | + String get watchThemeName; | ||
| 3611 | + | ||
| 3612 | + /// No description provided for @watchThemeNameMaxLength. | ||
| 3613 | + /// | ||
| 3614 | + /// In zh, this message translates to: | ||
| 3615 | + /// **'最多10个字符'** | ||
| 3616 | + String get watchThemeNameMaxLength; | ||
| 3617 | + | ||
| 3618 | + /// No description provided for @watchThemeSubmissionAgreement. | ||
| 3619 | + /// | ||
| 3620 | + /// In zh, this message translates to: | ||
| 3621 | + /// **'我已阅读并同意用户投稿协议'** | ||
| 3622 | + String get watchThemeSubmissionAgreement; | ||
| 3623 | + | ||
| 3624 | + /// No description provided for @watchThemeSaving. | ||
| 3625 | + /// | ||
| 3626 | + /// In zh, this message translates to: | ||
| 3627 | + /// **'保存中'** | ||
| 3628 | + String get watchThemeSaving; | ||
| 3629 | + | ||
| 3630 | + /// No description provided for @watchThemeSaveTheme. | ||
| 3631 | + /// | ||
| 3632 | + /// In zh, this message translates to: | ||
| 3633 | + /// **'保存主题'** | ||
| 3634 | + String get watchThemeSaveTheme; | ||
| 3635 | + | ||
| 3636 | + /// No description provided for @watchThemeExcellent. | ||
| 3637 | + /// | ||
| 3638 | + /// In zh, this message translates to: | ||
| 3639 | + /// **'状态优秀'** | ||
| 3640 | + String get watchThemeExcellent; | ||
| 3641 | + | ||
| 3642 | + /// No description provided for @watchThemeNormal. | ||
| 3643 | + /// | ||
| 3644 | + /// In zh, this message translates to: | ||
| 3645 | + /// **'状态正常'** | ||
| 3646 | + String get watchThemeNormal; | ||
| 3647 | + | ||
| 3648 | + /// No description provided for @watchThemeSlightStressful. | ||
| 3649 | + /// | ||
| 3650 | + /// In zh, this message translates to: | ||
| 3651 | + /// **'注意压力'** | ||
| 3652 | + String get watchThemeSlightStressful; | ||
| 3653 | + | ||
| 3654 | + /// No description provided for @watchThemeStressful. | ||
| 3655 | + /// | ||
| 3656 | + /// In zh, this message translates to: | ||
| 3657 | + /// **'压力过载'** | ||
| 3658 | + String get watchThemeStressful; | ||
| 3659 | + | ||
| 3660 | + /// No description provided for @watchThemeCropImage. | ||
| 3661 | + /// | ||
| 3662 | + /// In zh, this message translates to: | ||
| 3663 | + /// **'裁剪表盘图片'** | ||
| 3664 | + String get watchThemeCropImage; | ||
| 3665 | + | ||
| 3666 | + /// No description provided for @watchThemeImageProcessFailed. | ||
| 3667 | + /// | ||
| 3668 | + /// In zh, this message translates to: | ||
| 3669 | + /// **'图片处理失败,请重试'** | ||
| 3670 | + String get watchThemeImageProcessFailed; | ||
| 3671 | + | ||
| 3672 | + /// No description provided for @watchThemeAbandonEdit. | ||
| 3673 | + /// | ||
| 3674 | + /// In zh, this message translates to: | ||
| 3675 | + /// **'放弃编辑'** | ||
| 3676 | + String get watchThemeAbandonEdit; | ||
| 3677 | + | ||
| 3678 | + /// No description provided for @watchThemeAbandonMessage. | ||
| 3679 | + /// | ||
| 3680 | + /// In zh, this message translates to: | ||
| 3681 | + /// **'关闭此页面后,已编辑的内容不会保留,是否放弃编辑?'** | ||
| 3682 | + String get watchThemeAbandonMessage; | ||
| 3683 | + | ||
| 3684 | + /// No description provided for @watchThemeContinueEditing. | ||
| 3685 | + /// | ||
| 3686 | + /// In zh, this message translates to: | ||
| 3687 | + /// **'继续编辑'** | ||
| 3688 | + String get watchThemeContinueEditing; | ||
| 3689 | + | ||
| 3690 | + /// No description provided for @watchThemeImageUploadFailed. | ||
| 3691 | + /// | ||
| 3692 | + /// In zh, this message translates to: | ||
| 3693 | + /// **'图片上传失败,请重试'** | ||
| 3694 | + String get watchThemeImageUploadFailed; | ||
| 3695 | + | ||
| 3696 | + /// No description provided for @watchThemeCreateFailed. | ||
| 3697 | + /// | ||
| 3698 | + /// In zh, this message translates to: | ||
| 3699 | + /// **'创建表盘失败,请重试'** | ||
| 3700 | + String get watchThemeCreateFailed; | ||
| 3701 | + | ||
| 3702 | + /// No description provided for @watchThemeDeleteTheme. | ||
| 3703 | + /// | ||
| 3704 | + /// In zh, this message translates to: | ||
| 3705 | + /// **'删除主题'** | ||
| 3706 | + String get watchThemeDeleteTheme; | ||
| 3707 | + | ||
| 3708 | + /// No description provided for @watchThemeDeleteMessage. | ||
| 3709 | + /// | ||
| 3710 | + /// In zh, this message translates to: | ||
| 3711 | + /// **'主题删除后无法恢复,确认删除该主题吗?'** | ||
| 3712 | + String get watchThemeDeleteMessage; | ||
| 3713 | + | ||
| 3714 | + /// No description provided for @watchThemeCancel. | ||
| 3715 | + /// | ||
| 3716 | + /// In zh, this message translates to: | ||
| 3717 | + /// **'取消'** | ||
| 3718 | + String get watchThemeCancel; | ||
| 3719 | + | ||
| 3720 | + /// No description provided for @watchThemeDeleteFailed. | ||
| 3721 | + /// | ||
| 3722 | + /// In zh, this message translates to: | ||
| 3723 | + /// **'删除主题失败'** | ||
| 3724 | + String get watchThemeDeleteFailed; | ||
| 3725 | + | ||
| 3726 | + /// No description provided for @watchThemeDeleted. | ||
| 3727 | + /// | ||
| 3728 | + /// In zh, this message translates to: | ||
| 3729 | + /// **'已删除主题'** | ||
| 3730 | + String get watchThemeDeleted; | ||
| 3731 | + | ||
| 3732 | + /// No description provided for @watchThemeIncomplete. | ||
| 3733 | + /// | ||
| 3734 | + /// In zh, this message translates to: | ||
| 3735 | + /// **'主题信息不完整'** | ||
| 3736 | + String get watchThemeIncomplete; | ||
| 3737 | + | ||
| 3738 | + /// No description provided for @watchThemeApplyFailed. | ||
| 3739 | + /// | ||
| 3740 | + /// In zh, this message translates to: | ||
| 3741 | + /// **'应用主题失败'** | ||
| 3742 | + String get watchThemeApplyFailed; | ||
| 3743 | + | ||
| 3744 | + /// No description provided for @watchThemeWatchSyncFailed. | ||
| 3745 | + /// | ||
| 3746 | + /// In zh, this message translates to: | ||
| 3747 | + /// **'表盘同步失败'** | ||
| 3748 | + String get watchThemeWatchSyncFailed; | ||
| 3749 | + | ||
| 3750 | + /// No description provided for @watchThemePurchaseChannel. | ||
| 3751 | + /// | ||
| 3752 | + /// In zh, this message translates to: | ||
| 3753 | + /// **'表盘主题'** | ||
| 3754 | + String get watchThemePurchaseChannel; | ||
| 3431 | } | 3755 | } |
| 3432 | 3756 | ||
| 3433 | class _AppLocalizationsDelegate | 3757 | class _AppLocalizationsDelegate |
| @@ -1913,4 +1913,176 @@ class AppLocalizationsEn extends AppLocalizations { | @@ -1913,4 +1913,176 @@ class AppLocalizationsEn extends AppLocalizations { | ||
| 1913 | 1913 | ||
| 1914 | @override | 1914 | @override |
| 1915 | String get noHealthDataGoToSettings => 'Go to Settings'; | 1915 | String get noHealthDataGoToSettings => 'Go to Settings'; |
| 1916 | + | ||
| 1917 | + @override | ||
| 1918 | + String get watchThemeDefaultTheme => 'Default Theme'; | ||
| 1919 | + | ||
| 1920 | + @override | ||
| 1921 | + String get watchThemeNoWatchTitle => 'Apple Watch Not Found'; | ||
| 1922 | + | ||
| 1923 | + @override | ||
| 1924 | + String get watchThemeNoWatchMessage => 'Pair an Apple Watch and try again'; | ||
| 1925 | + | ||
| 1926 | + @override | ||
| 1927 | + String get watchThemeOk => 'OK'; | ||
| 1928 | + | ||
| 1929 | + @override | ||
| 1930 | + String get watchThemeSelectFriend => 'Select Friend'; | ||
| 1931 | + | ||
| 1932 | + @override | ||
| 1933 | + String get watchThemeSelectAndSync => 'Select and Sync to Watch Face'; | ||
| 1934 | + | ||
| 1935 | + @override | ||
| 1936 | + String get watchThemeCustomTheme => 'Custom Themes'; | ||
| 1937 | + | ||
| 1938 | + @override | ||
| 1939 | + String get watchThemeCustomDescription => | ||
| 1940 | + 'Capture every mood with your creativity and make a watch face that\'s uniquely yours.'; | ||
| 1941 | + | ||
| 1942 | + @override | ||
| 1943 | + String get watchThemeCreateTheme => 'Create Theme'; | ||
| 1944 | + | ||
| 1945 | + @override | ||
| 1946 | + String get watchThemeOfficialTheme => 'Official Themes'; | ||
| 1947 | + | ||
| 1948 | + @override | ||
| 1949 | + String get watchThemeRenameStatus => 'Rename Status'; | ||
| 1950 | + | ||
| 1951 | + @override | ||
| 1952 | + String get watchThemeEnterNickname => 'Enter a name'; | ||
| 1953 | + | ||
| 1954 | + @override | ||
| 1955 | + String get watchThemeSave => 'Save'; | ||
| 1956 | + | ||
| 1957 | + @override | ||
| 1958 | + String get watchThemeDialPreview => 'Watch Face Preview'; | ||
| 1959 | + | ||
| 1960 | + @override | ||
| 1961 | + String get watchThemeSwitchFriend => 'Switch Friend'; | ||
| 1962 | + | ||
| 1963 | + @override | ||
| 1964 | + String get watchThemeStatusPreview => 'Status Preview'; | ||
| 1965 | + | ||
| 1966 | + @override | ||
| 1967 | + String get watchThemeAddWatchFace => 'Add Watch Face'; | ||
| 1968 | + | ||
| 1969 | + @override | ||
| 1970 | + String get watchThemeInUse => 'In Use'; | ||
| 1971 | + | ||
| 1972 | + @override | ||
| 1973 | + String get watchThemeUseNow => 'Use Now'; | ||
| 1974 | + | ||
| 1975 | + @override | ||
| 1976 | + String get watchThemeSyncIntro => | ||
| 1977 | + 'Open the DoubleFeel app on your Apple Watch, then tap Next below.'; | ||
| 1978 | + | ||
| 1979 | + @override | ||
| 1980 | + String get watchThemeSyncWaiting => 'Keep the Watch app open while syncing'; | ||
| 1981 | + | ||
| 1982 | + @override | ||
| 1983 | + String get watchThemeSyncComplete => 'Sync Complete'; | ||
| 1984 | + | ||
| 1985 | + @override | ||
| 1986 | + String get watchThemeSyncFailed => 'Sync Failed'; | ||
| 1987 | + | ||
| 1988 | + @override | ||
| 1989 | + String get watchThemeNext => 'Next'; | ||
| 1990 | + | ||
| 1991 | + @override | ||
| 1992 | + String watchThemeSyncingProgress(int progress) { | ||
| 1993 | + return 'Syncing $progress%'; | ||
| 1994 | + } | ||
| 1995 | + | ||
| 1996 | + @override | ||
| 1997 | + String get watchThemePreview => 'Preview'; | ||
| 1998 | + | ||
| 1999 | + @override | ||
| 2000 | + String get watchThemeDelete => 'Delete'; | ||
| 2001 | + | ||
| 2002 | + @override | ||
| 2003 | + String get watchThemePageTitle => 'Watch Themes'; | ||
| 2004 | + | ||
| 2005 | + @override | ||
| 2006 | + String get watchThemeImagesOnly => 'Images only'; | ||
| 2007 | + | ||
| 2008 | + @override | ||
| 2009 | + String get watchThemeName => 'Theme Name'; | ||
| 2010 | + | ||
| 2011 | + @override | ||
| 2012 | + String get watchThemeNameMaxLength => 'Up to 10 characters'; | ||
| 2013 | + | ||
| 2014 | + @override | ||
| 2015 | + String get watchThemeSubmissionAgreement => | ||
| 2016 | + 'I have read and agree to the User Submission Agreement'; | ||
| 2017 | + | ||
| 2018 | + @override | ||
| 2019 | + String get watchThemeSaving => 'Saving'; | ||
| 2020 | + | ||
| 2021 | + @override | ||
| 2022 | + String get watchThemeSaveTheme => 'Save Theme'; | ||
| 2023 | + | ||
| 2024 | + @override | ||
| 2025 | + String get watchThemeExcellent => 'Excellent'; | ||
| 2026 | + | ||
| 2027 | + @override | ||
| 2028 | + String get watchThemeNormal => 'Normal'; | ||
| 2029 | + | ||
| 2030 | + @override | ||
| 2031 | + String get watchThemeSlightStressful => 'Watch Your Stress'; | ||
| 2032 | + | ||
| 2033 | + @override | ||
| 2034 | + String get watchThemeStressful => 'Stress Overload'; | ||
| 2035 | + | ||
| 2036 | + @override | ||
| 2037 | + String get watchThemeCropImage => 'Crop Watch Face Image'; | ||
| 2038 | + | ||
| 2039 | + @override | ||
| 2040 | + String get watchThemeImageProcessFailed => | ||
| 2041 | + 'Image processing failed. Please try again'; | ||
| 2042 | + | ||
| 2043 | + @override | ||
| 2044 | + String get watchThemeAbandonEdit => 'Discard Changes'; | ||
| 2045 | + | ||
| 2046 | + @override | ||
| 2047 | + String get watchThemeAbandonMessage => | ||
| 2048 | + 'Your changes won\'t be saved if you close this page. Discard them?'; | ||
| 2049 | + | ||
| 2050 | + @override | ||
| 2051 | + String get watchThemeContinueEditing => 'Continue Editing'; | ||
| 2052 | + | ||
| 2053 | + @override | ||
| 2054 | + String get watchThemeImageUploadFailed => | ||
| 2055 | + 'Image upload failed. Please try again'; | ||
| 2056 | + | ||
| 2057 | + @override | ||
| 2058 | + String get watchThemeCreateFailed => | ||
| 2059 | + 'Failed to create watch face. Please try again'; | ||
| 2060 | + | ||
| 2061 | + @override | ||
| 2062 | + String get watchThemeDeleteTheme => 'Delete Theme'; | ||
| 2063 | + | ||
| 2064 | + @override | ||
| 2065 | + String get watchThemeDeleteMessage => | ||
| 2066 | + 'Deleted themes cannot be restored. Delete this theme?'; | ||
| 2067 | + | ||
| 2068 | + @override | ||
| 2069 | + String get watchThemeCancel => 'Cancel'; | ||
| 2070 | + | ||
| 2071 | + @override | ||
| 2072 | + String get watchThemeDeleteFailed => 'Failed to delete theme'; | ||
| 2073 | + | ||
| 2074 | + @override | ||
| 2075 | + String get watchThemeDeleted => 'Theme deleted'; | ||
| 2076 | + | ||
| 2077 | + @override | ||
| 2078 | + String get watchThemeIncomplete => 'Theme information is incomplete'; | ||
| 2079 | + | ||
| 2080 | + @override | ||
| 2081 | + String get watchThemeApplyFailed => 'Failed to apply theme'; | ||
| 2082 | + | ||
| 2083 | + @override | ||
| 2084 | + String get watchThemeWatchSyncFailed => 'Watch face sync failed'; | ||
| 2085 | + | ||
| 2086 | + @override | ||
| 2087 | + String get watchThemePurchaseChannel => 'Watch Face Themes'; | ||
| 1916 | } | 2088 | } |
| @@ -1812,4 +1812,168 @@ class AppLocalizationsZh extends AppLocalizations { | @@ -1812,4 +1812,168 @@ class AppLocalizationsZh extends AppLocalizations { | ||
| 1812 | 1812 | ||
| 1813 | @override | 1813 | @override |
| 1814 | String get noHealthDataGoToSettings => '前往开启'; | 1814 | String get noHealthDataGoToSettings => '前往开启'; |
| 1815 | + | ||
| 1816 | + @override | ||
| 1817 | + String get watchThemeDefaultTheme => '默认主题'; | ||
| 1818 | + | ||
| 1819 | + @override | ||
| 1820 | + String get watchThemeNoWatchTitle => '未找到苹果手表'; | ||
| 1821 | + | ||
| 1822 | + @override | ||
| 1823 | + String get watchThemeNoWatchMessage => '请配对苹果手表后再尝试'; | ||
| 1824 | + | ||
| 1825 | + @override | ||
| 1826 | + String get watchThemeOk => '好的'; | ||
| 1827 | + | ||
| 1828 | + @override | ||
| 1829 | + String get watchThemeSelectFriend => '选择好友'; | ||
| 1830 | + | ||
| 1831 | + @override | ||
| 1832 | + String get watchThemeSelectAndSync => '选择并同步至表盘'; | ||
| 1833 | + | ||
| 1834 | + @override | ||
| 1835 | + String get watchThemeCustomTheme => '自定义主题'; | ||
| 1836 | + | ||
| 1837 | + @override | ||
| 1838 | + String get watchThemeCustomDescription => '用创意记录每一次情绪波动,打造懂你的专属表盘吧~'; | ||
| 1839 | + | ||
| 1840 | + @override | ||
| 1841 | + String get watchThemeCreateTheme => '创作主题'; | ||
| 1842 | + | ||
| 1843 | + @override | ||
| 1844 | + String get watchThemeOfficialTheme => '官方主题'; | ||
| 1845 | + | ||
| 1846 | + @override | ||
| 1847 | + String get watchThemeRenameStatus => '修改状态名称'; | ||
| 1848 | + | ||
| 1849 | + @override | ||
| 1850 | + String get watchThemeEnterNickname => '请输入昵称'; | ||
| 1851 | + | ||
| 1852 | + @override | ||
| 1853 | + String get watchThemeSave => '保存'; | ||
| 1854 | + | ||
| 1855 | + @override | ||
| 1856 | + String get watchThemeDialPreview => '表盘预览'; | ||
| 1857 | + | ||
| 1858 | + @override | ||
| 1859 | + String get watchThemeSwitchFriend => '切换好友'; | ||
| 1860 | + | ||
| 1861 | + @override | ||
| 1862 | + String get watchThemeStatusPreview => '状态预览'; | ||
| 1863 | + | ||
| 1864 | + @override | ||
| 1865 | + String get watchThemeAddWatchFace => '添加表盘'; | ||
| 1866 | + | ||
| 1867 | + @override | ||
| 1868 | + String get watchThemeInUse => '正在使用'; | ||
| 1869 | + | ||
| 1870 | + @override | ||
| 1871 | + String get watchThemeUseNow => '立即使用'; | ||
| 1872 | + | ||
| 1873 | + @override | ||
| 1874 | + String get watchThemeSyncIntro => '请先打开DoubleFeel手表端App,然后点击下方的“下一步”按钮'; | ||
| 1875 | + | ||
| 1876 | + @override | ||
| 1877 | + String get watchThemeSyncWaiting => '请保持打开手表App,等待同步'; | ||
| 1878 | + | ||
| 1879 | + @override | ||
| 1880 | + String get watchThemeSyncComplete => '同步完成'; | ||
| 1881 | + | ||
| 1882 | + @override | ||
| 1883 | + String get watchThemeSyncFailed => '同步失败'; | ||
| 1884 | + | ||
| 1885 | + @override | ||
| 1886 | + String get watchThemeNext => '下一步'; | ||
| 1887 | + | ||
| 1888 | + @override | ||
| 1889 | + String watchThemeSyncingProgress(int progress) { | ||
| 1890 | + return '同步中 $progress%'; | ||
| 1891 | + } | ||
| 1892 | + | ||
| 1893 | + @override | ||
| 1894 | + String get watchThemePreview => '预览'; | ||
| 1895 | + | ||
| 1896 | + @override | ||
| 1897 | + String get watchThemeDelete => '删除'; | ||
| 1898 | + | ||
| 1899 | + @override | ||
| 1900 | + String get watchThemePageTitle => 'Watch主题'; | ||
| 1901 | + | ||
| 1902 | + @override | ||
| 1903 | + String get watchThemeImagesOnly => '仅支持上传图片'; | ||
| 1904 | + | ||
| 1905 | + @override | ||
| 1906 | + String get watchThemeName => '主题名称'; | ||
| 1907 | + | ||
| 1908 | + @override | ||
| 1909 | + String get watchThemeNameMaxLength => '最多10个字符'; | ||
| 1910 | + | ||
| 1911 | + @override | ||
| 1912 | + String get watchThemeSubmissionAgreement => '我已阅读并同意用户投稿协议'; | ||
| 1913 | + | ||
| 1914 | + @override | ||
| 1915 | + String get watchThemeSaving => '保存中'; | ||
| 1916 | + | ||
| 1917 | + @override | ||
| 1918 | + String get watchThemeSaveTheme => '保存主题'; | ||
| 1919 | + | ||
| 1920 | + @override | ||
| 1921 | + String get watchThemeExcellent => '状态优秀'; | ||
| 1922 | + | ||
| 1923 | + @override | ||
| 1924 | + String get watchThemeNormal => '状态正常'; | ||
| 1925 | + | ||
| 1926 | + @override | ||
| 1927 | + String get watchThemeSlightStressful => '注意压力'; | ||
| 1928 | + | ||
| 1929 | + @override | ||
| 1930 | + String get watchThemeStressful => '压力过载'; | ||
| 1931 | + | ||
| 1932 | + @override | ||
| 1933 | + String get watchThemeCropImage => '裁剪表盘图片'; | ||
| 1934 | + | ||
| 1935 | + @override | ||
| 1936 | + String get watchThemeImageProcessFailed => '图片处理失败,请重试'; | ||
| 1937 | + | ||
| 1938 | + @override | ||
| 1939 | + String get watchThemeAbandonEdit => '放弃编辑'; | ||
| 1940 | + | ||
| 1941 | + @override | ||
| 1942 | + String get watchThemeAbandonMessage => '关闭此页面后,已编辑的内容不会保留,是否放弃编辑?'; | ||
| 1943 | + | ||
| 1944 | + @override | ||
| 1945 | + String get watchThemeContinueEditing => '继续编辑'; | ||
| 1946 | + | ||
| 1947 | + @override | ||
| 1948 | + String get watchThemeImageUploadFailed => '图片上传失败,请重试'; | ||
| 1949 | + | ||
| 1950 | + @override | ||
| 1951 | + String get watchThemeCreateFailed => '创建表盘失败,请重试'; | ||
| 1952 | + | ||
| 1953 | + @override | ||
| 1954 | + String get watchThemeDeleteTheme => '删除主题'; | ||
| 1955 | + | ||
| 1956 | + @override | ||
| 1957 | + String get watchThemeDeleteMessage => '主题删除后无法恢复,确认删除该主题吗?'; | ||
| 1958 | + | ||
| 1959 | + @override | ||
| 1960 | + String get watchThemeCancel => '取消'; | ||
| 1961 | + | ||
| 1962 | + @override | ||
| 1963 | + String get watchThemeDeleteFailed => '删除主题失败'; | ||
| 1964 | + | ||
| 1965 | + @override | ||
| 1966 | + String get watchThemeDeleted => '已删除主题'; | ||
| 1967 | + | ||
| 1968 | + @override | ||
| 1969 | + String get watchThemeIncomplete => '主题信息不完整'; | ||
| 1970 | + | ||
| 1971 | + @override | ||
| 1972 | + String get watchThemeApplyFailed => '应用主题失败'; | ||
| 1973 | + | ||
| 1974 | + @override | ||
| 1975 | + String get watchThemeWatchSyncFailed => '表盘同步失败'; | ||
| 1976 | + | ||
| 1977 | + @override | ||
| 1978 | + String get watchThemePurchaseChannel => '表盘主题'; | ||
| 1815 | } | 1979 | } |
-
Please register or login to post a comment