diff --git a/i18n/en.json b/i18n/en.json index 415052717a..5112166056 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -502,7 +502,7 @@ "advanced_settings_readonly_mode_subtitle": "Enables the read-only mode where the photos can be only viewed, things like selecting multiple images, sharing, casting, delete are all disabled. Enable/Disable read-only via user avatar from the main screen", "advanced_settings_readonly_mode_title": "Read-only mode", "advanced_settings_review_remote_deletions_subtitle": "Manually review cloud trash changes.", - "advanced_settings_review_remote_deletions_subtitle_android": "Restorations are applied automatically when Media Management Access is allowed.", + "advanced_settings_review_remote_deletions_subtitle_android": "Manually review cloud trash changes. Restorations are applied automatically when Media Management Access is allowed.", "advanced_settings_review_remote_deletions_title": "Review remote deletions", "advanced_settings_sync_remote_deletions_off_subtitle": "Cloud trash changes are ignored", "advanced_settings_sync_remote_deletions_selector_title": "Sync remote deletions [EXPERIMENTAL]", @@ -593,11 +593,6 @@ "asset_not_found_on_icloud": "Asset not found on iCloud. the asset may be inaccessible due to bad file stored on iCloud", "asset_offline": "Asset Offline", "asset_offline_description": "This external asset is no longer found on disk. Please contact your Immich administrator for help.", - "asset_out_of_sync_title": "Out-of-sync assets list", - "asset_out_of_sync_trash_confirmation_text": "Move {count, plural, one {asset} other {# assets}} to your device trash?", - "asset_out_of_sync_trash_confirmation_title": "Sync trash change", - "asset_out_of_sync_trash_subtitle": "Assets moved to the Immich cloud trash: choose to move them to local trash or keep them on this device.", - "asset_out_of_sync_trash_subtitle_result": "Nothing left to review — all decisions applied.", "asset_skipped": "Skipped", "asset_skipped_in_trash": "In trash", "asset_troubleshoot": "Asset Troubleshoot", @@ -612,7 +607,7 @@ "assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} cannot be added to the album", "assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} cannot be added to any of the albums", "assets_count": "{count, plural, one {# asset} other {# assets}}", - "assets_denied_to_moved_to_trash_count": "Keeping local copies of {count, plural, one {# asset} other {# assets}}", + "assets_kept_on_device_count": "Keeping local copies of {count, plural, one {# asset} other {# assets}}", "assets_moved_to_trash_count": "Moved {count, plural, one {# asset} other {# assets}} to trash", "assets_permanently_deleted_count": "Permanently deleted {count, plural, one {# asset} other {# assets}}", "assets_removed_count": "Removed {count, plural, one {# asset} other {# assets}}", @@ -1804,7 +1799,6 @@ "resume_paused_jobs": "Resume {count, plural, one {# paused job} other {# paused jobs}}", "review_duplicates": "Review duplicates", "review_large_files": "Review large files", - "review_out_of_sync_changes": "Review out-of-sync changes", "role": "Role", "role_editor": "Editor", "role_viewer": "Viewer", @@ -2148,6 +2142,12 @@ "trash_no_results_message": "Trashed photos and videos will show up here.", "trash_page_delete_all": "Delete All", "trash_page_info": "Trashed items will be permanently deleted after {days} days", + "trash_review_banner_title": "Review out-of-sync changes", + "trash_review_confirmation_text": "Move {count, plural, one {asset} other {# assets}} to your device trash?", + "trash_review_confirmation_title": "Sync trash change", + "trash_review_empty_subtitle": "Nothing left to review — all decisions applied.", + "trash_review_subtitle": "Assets moved to the Immich cloud trash: choose to move them to local trash or keep them on this device.", + "trash_review_title": "Out-of-sync assets list", "trashed_items_will_be_permanently_deleted_after": "Trashed items will be permanently deleted after {days, plural, one {# day} other {# days}}.", "trigger": "Trigger", "trigger_asset_metadata_extraction": "Asset Metadata Extraction", diff --git a/mobile/lib/presentation/pages/drift_trash_review.page.dart b/mobile/lib/presentation/pages/drift_trash_review.page.dart index 22f369b737..3a25c85f11 100644 --- a/mobile/lib/presentation/pages/drift_trash_review.page.dart +++ b/mobile/lib/presentation/pages/drift_trash_review.page.dart @@ -1,5 +1,4 @@ import 'package:auto_route/auto_route.dart'; -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; @@ -34,7 +33,7 @@ class DriftTrashReviewPage extends ConsumerWidget { ], child: Timeline( appBar: SliverAppBar( - title: Text('asset_out_of_sync_title'.tr()), + title: Text(context.t.trash_review_title), floating: true, snap: true, pinned: true, @@ -52,10 +51,8 @@ class DriftTrashReviewPage extends ConsumerWidget { builder: (context, ref, _) { final outOfSyncCount = ref.watch(pendingTrashReviewCountProvider).value ?? 0; return outOfSyncCount > 0 - ? const Text('asset_out_of_sync_trash_subtitle').tr() - : Center( - child: Text('asset_out_of_sync_trash_subtitle_result', style: context.textTheme.bodyLarge).tr(), - ); + ? Text(context.t.trash_review_subtitle) + : Center(child: Text(context.t.trash_review_empty_subtitle, style: context.textTheme.bodyLarge)); }, ), ), @@ -82,8 +79,8 @@ class _TrashReviewKebabMenu extends ConsumerWidget { await showDialog( context: context, builder: (_) => ConfirmDialog( - title: context.t.asset_out_of_sync_trash_confirmation_title, - content: context.t.asset_out_of_sync_trash_confirmation_text(count: count), + title: context.t.trash_review_confirmation_title, + content: context.t.trash_review_confirmation_text(count: count), onOk: () async { final result = await ref.read(actionProvider.notifier).resolveAllRemoteTrash(keep: false); if (!context.mounted) { diff --git a/mobile/lib/presentation/widgets/action_buttons/keep_on_device_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/keep_on_device_action_button.widget.dart index 639c91c59f..64e34cc8cc 100644 --- a/mobile/lib/presentation/widgets/action_buttons/keep_on_device_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/keep_on_device_action_button.widget.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; -import 'package:immich_mobile/extensions/translate_extensions.dart'; +import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; @@ -14,8 +14,8 @@ void showKeepResultToast(BuildContext context, ActionResult result) { return; } final message = result.success - ? 'assets_denied_to_moved_to_trash_count'.t(args: {'count': '${result.count}'}) - : 'scaffold_body_error_occurred'.t(); + ? context.t.assets_kept_on_device_count(count: result.count) + : context.t.scaffold_body_error_occurred; ImmichToast.show( context: context, msg: message, @@ -49,12 +49,12 @@ class KeepOnDeviceActionButton extends ConsumerWidget { ? BaseActionButton( maxWidth: 110.0, iconData: iconData, - label: 'keep'.t(), + label: context.t.keep, onPressed: () => _onTap(context, ref), ) : TextButton.icon( icon: const Icon(iconData), - label: Text('keep_on_device'.t(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)), + label: Text(context.t.keep_on_device, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)), onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/move_to_trash_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/move_to_trash_action_button.widget.dart index 1b3882db47..983e2af35e 100644 --- a/mobile/lib/presentation/widgets/action_buttons/move_to_trash_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/move_to_trash_action_button.widget.dart @@ -1,10 +1,9 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/extensions/platform_extensions.dart'; -import 'package:immich_mobile/extensions/translate_extensions.dart'; +import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; @@ -17,8 +16,8 @@ void showTrashResultToast(BuildContext context, ActionResult result) { return; } final message = result.success - ? 'assets_moved_to_trash_count'.t(args: {'count': '${result.count}'}) - : 'errors.something_went_wrong'.t(); + ? context.t.assets_moved_to_trash_count(count: result.count) + : context.t.errors.something_went_wrong; ImmichToast.show( context: context, msg: message, @@ -56,14 +55,14 @@ class MoveToTrashActionButton extends ConsumerWidget { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text('asset_out_of_sync_trash_confirmation_title'.tr()), - content: Text('asset_out_of_sync_trash_confirmation_text'.t(args: {'count': '$selectedCount'})), + title: Text(context.t.trash_review_confirmation_title), + content: Text(context.t.trash_review_confirmation_text(count: selectedCount)), actions: [ - TextButton(onPressed: () => Navigator.of(context).pop(false), child: Text('cancel'.tr())), + TextButton(onPressed: () => Navigator.of(context).pop(false), child: Text(context.t.cancel)), TextButton( onPressed: () => Navigator.of(context).pop(true), style: TextButton.styleFrom(foregroundColor: Theme.of(context).colorScheme.error), - child: Text('control_bottom_app_bar_trash_from_immich'.tr()), + child: Text(context.t.control_bottom_app_bar_trash_from_immich), ), ], ); @@ -91,13 +90,13 @@ class MoveToTrashActionButton extends ConsumerWidget { ? BaseActionButton( maxWidth: 100.0, iconData: iconData, - label: 'delete'.tr(), + label: context.t.delete, onPressed: () => _onTap(context, ref), ) : TextButton.icon( icon: Icon(iconData, color: Colors.red[400]), label: Text( - 'control_bottom_app_bar_trash_from_immich'.tr(), + context.t.control_bottom_app_bar_trash_from_immich, style: TextStyle(fontSize: 14, color: Colors.red[400], fontWeight: FontWeight.bold), ), onPressed: () => _onTap(context, ref), diff --git a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart index 1535dfa58e..69f67a6559 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/extensions/translate_extensions.dart'; +import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/models/server_info/server_disk_info.model.dart'; import 'package:immich_mobile/pages/common/settings.page.dart'; import 'package:immich_mobile/providers/auth.provider.dart'; @@ -121,7 +121,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { contentPadding: const EdgeInsets.only(left: 18, right: 18), minLeadingWidth: 40, leading: Icon(Icons.warning_amber_rounded, color: textColor, size: 20), - title: Text('review_out_of_sync_changes'.t(), style: textStyle), + title: Text(context.t.trash_review_banner_title, style: textStyle), onTap: () => context.pushRoute(const DriftTrashReviewRoute()), trailing: Text('($outOfSyncCount)', style: textStyle), ), diff --git a/mobile/lib/widgets/settings/advanced_settings.dart b/mobile/lib/widgets/settings/advanced_settings.dart index 0cb4132eed..8c75f2e4dc 100644 --- a/mobile/lib/widgets/settings/advanced_settings.dart +++ b/mobile/lib/widgets/settings/advanced_settings.dart @@ -8,6 +8,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/services/log.service.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; @@ -160,10 +161,9 @@ class _TrashSyncModeSelector extends HookConsumerWidget { final manageMediaAndroidPermission = ref.watch(_manageMediaPermissionProvider); final manageMediaAndroidPermissionValue = manageMediaAndroidPermission.valueOrNull; final isTrashSyncEnabled = selectedTrashSyncMode != TrashSyncMode.off; - final reviewRemoteDeletionsSubtitle = [ - "advanced_settings_review_remote_deletions_subtitle".tr(), - if (Platform.isAndroid) "advanced_settings_review_remote_deletions_subtitle_android".tr(), - ].join(' '); + final reviewRemoteDeletionsSubtitle = Platform.isAndroid + ? context.t.advanced_settings_review_remote_deletions_subtitle_android + : context.t.advanced_settings_review_remote_deletions_subtitle; void showManageMediaRequiredSnackBar() { if (!context.mounted) { @@ -172,7 +172,7 @@ class _TrashSyncModeSelector extends HookConsumerWidget { context.scaffoldMessenger.showSnackBar( SnackBar( content: Text( - "manage_media_access_review_rationale".tr(), + context.t.manage_media_access_review_rationale, style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), ), ), @@ -224,7 +224,7 @@ class _TrashSyncModeSelector extends HookConsumerWidget { Padding( padding: const EdgeInsets.only(left: 20), child: Text( - "advanced_settings_sync_remote_deletions_selector_title".tr(), + context.t.advanced_settings_sync_remote_deletions_selector_title, style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500, height: 1.5), ), ), @@ -233,18 +233,18 @@ class _TrashSyncModeSelector extends HookConsumerWidget { child: SettingsRadioListTile( groups: [ SettingsRadioGroup( - title: 'off'.tr(), - subtitle: 'advanced_settings_sync_remote_deletions_off_subtitle'.tr(), + title: context.t.off, + subtitle: context.t.advanced_settings_sync_remote_deletions_off_subtitle, value: TrashSyncMode.off, ), if (!Platform.isIOS) SettingsRadioGroup( - title: 'advanced_settings_sync_remote_deletions_title'.tr(), - subtitle: 'advanced_settings_sync_remote_deletions_subtitle'.tr(), + title: context.t.advanced_settings_sync_remote_deletions_title, + subtitle: context.t.advanced_settings_sync_remote_deletions_subtitle, value: TrashSyncMode.autoSync, ), SettingsRadioGroup( - title: 'advanced_settings_review_remote_deletions_title'.tr(), + title: context.t.advanced_settings_review_remote_deletions_title, subtitle: reviewRemoteDeletionsSubtitle, value: TrashSyncMode.review, ), @@ -255,13 +255,13 @@ class _TrashSyncModeSelector extends HookConsumerWidget { ), if (Platform.isAndroid) SettingsActionTile( - title: "manage_media_access_title".tr(), + title: context.t.manage_media_access_title, statusText: manageMediaAndroidPermissionValue == null ? null : manageMediaAndroidPermissionValue == true - ? "allowed".tr() - : "not_allowed".tr(), - subtitle: "manage_media_access_rationale".tr(), + ? context.t.allowed + : context.t.not_allowed, + subtitle: context.t.manage_media_access_rationale, statusColor: manageMediaAndroidPermissionValue == false && isTrashSyncEnabled ? const Color.fromARGB(255, 243, 188, 106) : null,