From ece977d9ca96a713ee417ffd1a8173a984553ef7 Mon Sep 17 00:00:00 2001 From: shenlong <139912620+shenlong-tanwen@users.noreply.github.com> Date: Tue, 6 May 2025 18:51:05 +0530 Subject: [PATCH] fix(mobile): empty translation placeholders (#18063) * fix: empty placeholders * fix: use namedArgs --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> --- i18n/en.json | 122 +++++++++--------- .../album/album_asset_selection.page.dart | 4 +- mobile/lib/pages/albums/albums.page.dart | 12 +- .../backup/backup_album_selection.page.dart | 6 +- mobile/lib/pages/editing/edit.page.dart | 16 +-- mobile/lib/pages/library/archive.page.dart | 2 +- .../pages/library/partner/partner.page.dart | 3 +- .../shared_link/shared_link_edit.page.dart | 24 ++-- mobile/lib/pages/library/trash.page.dart | 20 +-- .../pages/share_intent/share_intent.page.dart | 12 +- .../backup/manual_upload.provider.dart | 20 +-- mobile/lib/services/background.service.dart | 4 +- mobile/lib/services/memory.service.dart | 3 +- .../widgets/album/album_thumbnail_card.dart | 8 +- .../album/album_thumbnail_listtile.dart | 4 +- .../widgets/asset_grid/multiselect_grid.dart | 36 +++--- .../detail_panel/people_info.dart | 12 +- .../lib/widgets/backup/asset_info_table.dart | 21 +-- .../lib/widgets/backup/error_chip_text.dart | 4 +- .../common/app_bar_dialog/app_bar_dialog.dart | 16 +-- mobile/lib/widgets/map/map_asset_grid.dart | 14 +- .../map_settings_time_dropdown.dart | 7 +- .../widgets/settings/advanced_settings.dart | 3 +- .../asset_list_layout_settings.dart | 4 +- .../backup_settings/background_settings.dart | 16 ++- .../settings/local_storage_settings.dart | 6 +- .../settings/notification_setting.dart | 13 +- .../widgets/shared_link/shared_link_item.dart | 19 +-- 28 files changed, 228 insertions(+), 203 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index 8f190f2c09..80381dcff9 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -369,7 +369,7 @@ "advanced": "Advanced", "advanced_settings_enable_alternate_media_filter_subtitle": "Use this option to filter media during sync based on alternate criteria. Only try this if you have issues with the app detecting all albums.", "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Use alternate device album sync filter", - "advanced_settings_log_level_title": "Log level: {}", + "advanced_settings_log_level_title": "Log level: {level}", "advanced_settings_prefer_remote_subtitle": "Some devices are painfully slow to load thumbnails from assets on the device. Activate this setting to load remote images instead.", "advanced_settings_prefer_remote_title": "Prefer remote images", "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", @@ -400,9 +400,9 @@ "album_remove_user_confirmation": "Are you sure you want to remove {user}?", "album_share_no_users": "Looks like you have shared this album with all users or you don't have any user to share with.", "album_thumbnail_card_item": "1 item", - "album_thumbnail_card_items": "{} items", + "album_thumbnail_card_items": "{count} items", "album_thumbnail_card_shared": " · Shared", - "album_thumbnail_shared_by": "Shared by {}", + "album_thumbnail_shared_by": "Shared by {user}", "album_updated": "Album updated", "album_updated_setting_description": "Receive an email notification when a shared album has new assets", "album_user_left": "Left {album}", @@ -440,7 +440,7 @@ "archive": "Archive", "archive_or_unarchive_photo": "Archive or unarchive photo", "archive_page_no_archived_assets": "No archived assets found", - "archive_page_title": "Archive ({})", + "archive_page_title": "Archive ({count})", "archive_size": "Archive size", "archive_size_description": "Configure the archive size for downloads (in GiB)", "archived": "Archived", @@ -477,18 +477,18 @@ "assets_added_to_album_count": "Added {count, plural, one {# asset} other {# assets}} to the album", "assets_added_to_name_count": "Added {count, plural, one {# asset} other {# assets}} to {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, one {# asset} other {# assets}}", - "assets_deleted_permanently": "{} asset(s) deleted permanently", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", + "assets_deleted_permanently": "{count} asset(s) deleted permanently", + "assets_deleted_permanently_from_server": "{count} asset(s) deleted permanently from the Immich server", "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}}", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", + "assets_removed_permanently_from_device": "{count} asset(s) removed permanently from your device", "assets_restore_confirmation": "Are you sure you want to restore all your trashed assets? You cannot undo this action! Note that any offline assets cannot be restored this way.", "assets_restored_count": "Restored {count, plural, one {# asset} other {# assets}}", - "assets_restored_successfully": "{} asset(s) restored successfully", - "assets_trashed": "{} asset(s) trashed", + "assets_restored_successfully": "{count} asset(s) restored successfully", + "assets_trashed": "{count} asset(s) trashed", "assets_trashed_count": "Trashed {count, plural, one {# asset} other {# assets}}", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "assets_trashed_from_server": "{count} asset(s) trashed from the Immich server", "assets_were_part_of_album_count": "{count, plural, one {Asset was} other {Assets were}} already part of the album", "authorized_devices": "Authorized Devices", "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", @@ -497,7 +497,7 @@ "back_close_deselect": "Back, close, or deselect", "background_location_permission": "Background location permission", "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", - "backup_album_selection_page_albums_device": "Albums on device ({})", + "backup_album_selection_page_albums_device": "Albums on device ({count})", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", "backup_album_selection_page_select_albums": "Select albums", @@ -506,11 +506,11 @@ "backup_all": "All", "backup_background_service_backup_failed_message": "Failed to backup assets. Retrying…", "backup_background_service_connection_failed_message": "Failed to connect to the server. Retrying…", - "backup_background_service_current_upload_notification": "Uploading {}", + "backup_background_service_current_upload_notification": "Uploading {filename}", "backup_background_service_default_notification": "Checking for new assets…", "backup_background_service_error_title": "Backup error", "backup_background_service_in_progress_notification": "Backing up your assets…", - "backup_background_service_upload_failure_notification": "Failed to upload {}", + "backup_background_service_upload_failure_notification": "Failed to upload {filename}", "backup_controller_page_albums": "Backup Albums", "backup_controller_page_background_app_refresh_disabled_content": "Enable background app refresh in Settings > General > Background App Refresh in order to use background backup.", "backup_controller_page_background_app_refresh_disabled_title": "Background app refresh disabled", @@ -521,7 +521,7 @@ "backup_controller_page_background_battery_info_title": "Battery optimizations", "backup_controller_page_background_charging": "Only while charging", "backup_controller_page_background_configure_error": "Failed to configure the background service", - "backup_controller_page_background_delay": "Delay new assets backup: {}", + "backup_controller_page_background_delay": "Delay new assets backup: {duration}", "backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app", "backup_controller_page_background_is_off": "Automatic background backup is off", "backup_controller_page_background_is_on": "Automatic background backup is on", @@ -531,12 +531,12 @@ "backup_controller_page_backup": "Backup", "backup_controller_page_backup_selected": "Selected: ", "backup_controller_page_backup_sub": "Backed up photos and videos", - "backup_controller_page_created": "Created on: {}", + "backup_controller_page_created": "Created on: {date}", "backup_controller_page_desc_backup": "Turn on foreground backup to automatically upload new assets to the server when opening the app.", "backup_controller_page_excluded": "Excluded: ", - "backup_controller_page_failed": "Failed ({})", - "backup_controller_page_filename": "File name: {} [{}]", - "backup_controller_page_id": "ID: {}", + "backup_controller_page_failed": "Failed ({count})", + "backup_controller_page_filename": "File name: {filename} [{size}]", + "backup_controller_page_id": "ID: {id}", "backup_controller_page_info": "Backup Information", "backup_controller_page_none_selected": "None selected", "backup_controller_page_remainder": "Remainder", @@ -545,7 +545,7 @@ "backup_controller_page_start_backup": "Start Backup", "backup_controller_page_status_off": "Automatic foreground backup is off", "backup_controller_page_status_on": "Automatic foreground backup is on", - "backup_controller_page_storage_format": "{} of {} used", + "backup_controller_page_storage_format": "{used} of {total} used", "backup_controller_page_to_backup": "Albums to be backed up", "backup_controller_page_total_sub": "All unique photos and videos from selected albums", "backup_controller_page_turn_off": "Turn off foreground backup", @@ -570,21 +570,21 @@ "bulk_keep_duplicates_confirmation": "Are you sure you want to keep {count, plural, one {# duplicate asset} other {# duplicate assets}}? This will resolve all duplicate groups without deleting anything.", "bulk_trash_duplicates_confirmation": "Are you sure you want to bulk trash {count, plural, one {# duplicate asset} other {# duplicate assets}}? This will keep the largest asset of each group and trash all other duplicates.", "buy": "Purchase Immich", - "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", + "cache_settings_album_thumbnails": "Library page thumbnails ({count} assets)", "cache_settings_clear_cache_button": "Clear cache", "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", "cache_settings_duplicated_assets_clear_button": "CLEAR", "cache_settings_duplicated_assets_subtitle": "Photos and videos that are black listed by the app", - "cache_settings_duplicated_assets_title": "Duplicated Assets ({})", - "cache_settings_image_cache_size": "Image cache size ({} assets)", + "cache_settings_duplicated_assets_title": "Duplicated Assets ({count})", + "cache_settings_image_cache_size": "Image cache size ({count} assets)", "cache_settings_statistics_album": "Library thumbnails", - "cache_settings_statistics_assets": "{} assets ({})", + "cache_settings_statistics_assets": "{count} assets ({size})", "cache_settings_statistics_full": "Full images", "cache_settings_statistics_shared": "Shared album thumbnails", "cache_settings_statistics_thumbnail": "Thumbnails", "cache_settings_statistics_title": "Cache usage", "cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application", - "cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)", + "cache_settings_thumbnail_size": "Thumbnail cache size ({count} assets)", "cache_settings_tile_subtitle": "Control the local storage behaviour", "cache_settings_tile_title": "Local Storage", "cache_settings_title": "Caching Settings", @@ -654,7 +654,7 @@ "contain": "Contain", "context": "Context", "continue": "Continue", - "control_bottom_app_bar_album_info_shared": "{} items · Shared", + "control_bottom_app_bar_album_info_shared": "{count} items · Shared", "control_bottom_app_bar_create_new_album": "Create new album", "control_bottom_app_bar_delete_from_immich": "Delete from Immich", "control_bottom_app_bar_delete_from_local": "Delete from device", @@ -763,7 +763,7 @@ "download_enqueue": "Download enqueued", "download_error": "Download Error", "download_failed": "Download failed", - "download_filename": "file: {}", + "download_filename": "file: {filename}", "download_finished": "Download finished", "download_include_embedded_motion_videos": "Embedded videos", "download_include_embedded_motion_videos_description": "Include videos embedded in motion photos as a separate file", @@ -819,7 +819,7 @@ "error_change_sort_album": "Failed to change album sort order", "error_delete_face": "Error deleting face from asset", "error_loading_image": "Error loading image", - "error_saving_image": "Error: {}", + "error_saving_image": "Error: {error}", "error_title": "Error - Something went wrong", "errors": { "cannot_navigate_next_asset": "Cannot navigate to the next asset", @@ -955,10 +955,10 @@ "exif_bottom_sheet_location": "LOCATION", "exif_bottom_sheet_people": "PEOPLE", "exif_bottom_sheet_person_add_person": "Add name", - "exif_bottom_sheet_person_age": "Age {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age": "Age {age}", + "exif_bottom_sheet_person_age_months": "Age {months} months", + "exif_bottom_sheet_person_age_year_months": "Age 1 year, {months} months", + "exif_bottom_sheet_person_age_years": "Age {years}", "exit_slideshow": "Exit Slideshow", "expand_all": "Expand all", "experimental_settings_new_asset_list_subtitle": "Work in progress", @@ -1173,8 +1173,8 @@ "manage_your_devices": "Manage your logged-in devices", "manage_your_oauth_connection": "Manage your OAuth connection", "map": "Map", - "map_assets_in_bound": "{} photo", - "map_assets_in_bounds": "{} photos", + "map_assets_in_bound": "{count} photo", + "map_assets_in_bounds": "{count} photos", "map_cannot_get_user_location": "Cannot get user's location", "map_location_dialog_yes": "Yes", "map_location_picker_page_use_location": "Use this location", @@ -1188,9 +1188,9 @@ "map_settings": "Map settings", "map_settings_dark_mode": "Dark mode", "map_settings_date_range_option_day": "Past 24 hours", - "map_settings_date_range_option_days": "Past {} days", + "map_settings_date_range_option_days": "Past {days} days", "map_settings_date_range_option_year": "Past year", - "map_settings_date_range_option_years": "Past {} years", + "map_settings_date_range_option_years": "Past {years} years", "map_settings_dialog_title": "Map Settings", "map_settings_include_show_archived": "Include Archived", "map_settings_include_show_partners": "Include Partners", @@ -1209,7 +1209,7 @@ "memories_start_over": "Start Over", "memories_swipe_to_close": "Swipe up to close", "memories_year_ago": "A year ago", - "memories_years_ago": "{} years ago", + "memories_years_ago": "{years} years ago", "memory": "Memory", "memory_lane_title": "Memory Lane {title}", "menu": "Menu", @@ -1316,7 +1316,7 @@ "partner_page_partner_add_failed": "Failed to add partner", "partner_page_select_partner": "Select partner", "partner_page_shared_to_title": "Shared to", - "partner_page_stop_sharing_content": "{} will no longer be able to access your photos.", + "partner_page_stop_sharing_content": "{partner} will no longer be able to access your photos.", "partner_sharing": "Partner Sharing", "partners": "Partners", "password": "Password", @@ -1604,12 +1604,12 @@ "setting_languages_apply": "Apply", "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "Languages", - "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", - "setting_notifications_notify_hours": "{} hours", + "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {duration}", + "setting_notifications_notify_hours": "{count} hours", "setting_notifications_notify_immediately": "immediately", - "setting_notifications_notify_minutes": "{} minutes", + "setting_notifications_notify_minutes": "{count} minutes", "setting_notifications_notify_never": "never", - "setting_notifications_notify_seconds": "{} seconds", + "setting_notifications_notify_seconds": "{count} seconds", "setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset", "setting_notifications_single_progress_title": "Show background backup detail progress", "setting_notifications_subtitle": "Adjust your notification preferences", @@ -1623,7 +1623,7 @@ "settings_saved": "Settings saved", "share": "Share", "share_add_photos": "Add photos", - "share_assets_selected": "{} selected", + "share_assets_selected": "{count} selected", "share_dialog_preparing": "Preparing...", "shared": "Shared", "shared_album_activities_input_disable": "Comment is disabled", @@ -1637,32 +1637,32 @@ "shared_by_user": "Shared by {user}", "shared_by_you": "Shared by you", "shared_from_partner": "Photos from {partner}", - "shared_intent_upload_button_progress_text": "{} / {} Uploaded", + "shared_intent_upload_button_progress_text": "{current} / {total} Uploaded", "shared_link_app_bar_title": "Shared Links", "shared_link_clipboard_copied_massage": "Copied to clipboard", - "shared_link_clipboard_text": "Link: {}\nPassword: {}", + "shared_link_clipboard_text": "Link: {link}\nPassword: {password}", "shared_link_create_error": "Error while creating shared link", "shared_link_edit_description_hint": "Enter the share description", "shared_link_edit_expire_after_option_day": "1 day", - "shared_link_edit_expire_after_option_days": "{} days", + "shared_link_edit_expire_after_option_days": "{count} days", "shared_link_edit_expire_after_option_hour": "1 hour", - "shared_link_edit_expire_after_option_hours": "{} hours", + "shared_link_edit_expire_after_option_hours": "{count} hours", "shared_link_edit_expire_after_option_minute": "1 minute", - "shared_link_edit_expire_after_option_minutes": "{} minutes", - "shared_link_edit_expire_after_option_months": "{} months", - "shared_link_edit_expire_after_option_year": "{} year", + "shared_link_edit_expire_after_option_minutes": "{count} minutes", + "shared_link_edit_expire_after_option_months": "{count} months", + "shared_link_edit_expire_after_option_year": "{count} year", "shared_link_edit_password_hint": "Enter the share password", "shared_link_edit_submit_button": "Update link", "shared_link_error_server_url_fetch": "Cannot fetch the server url", - "shared_link_expires_day": "Expires in {} day", - "shared_link_expires_days": "Expires in {} days", - "shared_link_expires_hour": "Expires in {} hour", - "shared_link_expires_hours": "Expires in {} hours", - "shared_link_expires_minute": "Expires in {} minute", - "shared_link_expires_minutes": "Expires in {} minutes", + "shared_link_expires_day": "Expires in {count} day", + "shared_link_expires_days": "Expires in {count} days", + "shared_link_expires_hour": "Expires in {count} hour", + "shared_link_expires_hours": "Expires in {count} hours", + "shared_link_expires_minute": "Expires in {count} minute", + "shared_link_expires_minutes": "Expires in {count} minutes", "shared_link_expires_never": "Expires ∞", - "shared_link_expires_second": "Expires in {} second", - "shared_link_expires_seconds": "Expires in {} seconds", + "shared_link_expires_second": "Expires in {count} second", + "shared_link_expires_seconds": "Expires in {count} seconds", "shared_link_individual_shared": "Individual shared", "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "Manage Shared links", @@ -1763,7 +1763,7 @@ "theme_selection": "Theme selection", "theme_selection_description": "Automatically set the theme to light or dark based on your browser's system preference", "theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles", - "theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})", + "theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({count})", "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", "theme_setting_colorful_interface_title": "Colorful interface", "theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer", @@ -1798,11 +1798,11 @@ "trash_no_results_message": "Trashed photos and videos will show up here.", "trash_page_delete_all": "Delete All", "trash_page_empty_trash_dialog_content": "Do you want to empty your trashed assets? These items will be permanently removed from Immich", - "trash_page_info": "Trashed items will be permanently deleted after {} days", + "trash_page_info": "Trashed items will be permanently deleted after {days} days", "trash_page_no_assets": "No trashed assets", "trash_page_restore_all": "Restore All", "trash_page_select_assets_btn": "Select assets", - "trash_page_title": "Trash ({})", + "trash_page_title": "Trash ({count})", "trashed_items_will_be_permanently_deleted_after": "Trashed items will be permanently deleted after {days, plural, one {# day} other {# days}}.", "type": "Type", "unarchive": "Unarchive", @@ -1840,7 +1840,7 @@ "upload_status_errors": "Errors", "upload_status_uploaded": "Uploaded", "upload_success": "Upload success, refresh the page to see new upload assets.", - "upload_to_immich": "Upload to Immich ({})", + "upload_to_immich": "Upload to Immich ({count})", "uploading": "Uploading", "url": "URL", "usage": "Usage", diff --git a/mobile/lib/pages/album/album_asset_selection.page.dart b/mobile/lib/pages/album/album_asset_selection.page.dart index 617fbfee11..7b0ce8cdc4 100644 --- a/mobile/lib/pages/album/album_asset_selection.page.dart +++ b/mobile/lib/pages/album/album_asset_selection.page.dart @@ -3,13 +3,13 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/extensions/asyncvalue_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/models/albums/asset_selection_page_result.model.dart'; import 'package:immich_mobile/providers/timeline.provider.dart'; import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart'; import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; -import 'package:immich_mobile/entities/asset.entity.dart'; @RoutePage() class AlbumAssetSelectionPage extends HookConsumerWidget { @@ -59,7 +59,7 @@ class AlbumAssetSelectionPage extends HookConsumerWidget { : const Text( 'share_assets_selected', style: TextStyle(fontSize: 18), - ).tr(args: [selected.value.length.toString()]), + ).tr(namedArgs: {'count': selected.value.length.toString()}), centerTitle: false, actions: [ if (selected.value.isNotEmpty || canDeselect) diff --git a/mobile/lib/pages/albums/albums.page.dart b/mobile/lib/pages/albums/albums.page.dart index 1269fe0a8e..f09cd5a408 100644 --- a/mobile/lib/pages/albums/albums.page.dart +++ b/mobile/lib/pages/albums/albums.page.dart @@ -229,11 +229,13 @@ class AlbumsPage extends HookConsumerWidget { ), subtitle: sorted[index].ownerId != null ? Text( - '${(sorted[index].assetCount == 1 ? 'album_thumbnail_card_item'.tr( - args: ['${sorted[index].assetCount}'], - ) : 'album_thumbnail_card_items'.tr( - args: ['${sorted[index].assetCount}'], - ))} • ${sorted[index].ownerId != userId ? 'album_thumbnail_shared_by'.tr(args: [sorted[index].ownerName!]) : 'owned'.tr()}', + '${(sorted[index].assetCount == 1 ? 'album_thumbnail_card_item'.tr() : 'album_thumbnail_card_items'.tr( + namedArgs: { + 'count': sorted[index] + .assetCount + .toString(), + }, + ))} • ${sorted[index].ownerId != userId ? 'album_thumbnail_shared_by'.tr(namedArgs: {'user': sorted[index].ownerName!}) : 'owned'.tr()}', overflow: TextOverflow.ellipsis, style: context.textTheme.bodyMedium?.copyWith( diff --git a/mobile/lib/pages/backup/backup_album_selection.page.dart b/mobile/lib/pages/backup/backup_album_selection.page.dart index 671a9bfe16..c4124efb52 100644 --- a/mobile/lib/pages/backup/backup_album_selection.page.dart +++ b/mobile/lib/pages/backup/backup_album_selection.page.dart @@ -214,13 +214,13 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ListTile( title: Text( "backup_album_selection_page_albums_device".tr( - args: [ - ref + namedArgs: { + 'count': ref .watch(backupProvider) .availableAlbums .length .toString(), - ], + }, ), style: context.textTheme.titleSmall, ), diff --git a/mobile/lib/pages/editing/edit.page.dart b/mobile/lib/pages/editing/edit.page.dart index bfa60eae00..39524df024 100644 --- a/mobile/lib/pages/editing/edit.page.dart +++ b/mobile/lib/pages/editing/edit.page.dart @@ -1,18 +1,18 @@ -import 'dart:typed_data'; import 'dart:async'; +import 'dart:typed_data'; import 'dart:ui'; +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:fluttertoast/fluttertoast.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/repositories/file_media.repository.dart'; -import 'package:immich_mobile/widgets/common/immich_toast.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; -import 'package:easy_localization/easy_localization.dart'; +import 'package:immich_mobile/repositories/file_media.repository.dart'; +import 'package:immich_mobile/routing/router.dart'; +import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:path/path.dart' as p; /// A stateless widget that provides functionality for editing an image. @@ -81,7 +81,7 @@ class EditImagePage extends ConsumerWidget { ImmichToast.show( durationInSecond: 6, context: context, - msg: "error_saving_image".tr(args: [e.toString()]), + msg: "error_saving_image".tr(namedArgs: {'error': e.toString()}), gravity: ToastGravity.CENTER, ); } diff --git a/mobile/lib/pages/library/archive.page.dart b/mobile/lib/pages/library/archive.page.dart index a13adc21f2..2b4aa64f3b 100644 --- a/mobile/lib/pages/library/archive.page.dart +++ b/mobile/lib/pages/library/archive.page.dart @@ -24,7 +24,7 @@ class ArchivePage extends HookConsumerWidget { automaticallyImplyLeading: false, title: const Text( 'archive_page_title', - ).tr(args: [count]), + ).tr(namedArgs: {'count': count}), ); } diff --git a/mobile/lib/pages/library/partner/partner.page.dart b/mobile/lib/pages/library/partner/partner.page.dart index 90a6a7f04e..91b661e7ce 100644 --- a/mobile/lib/pages/library/partner/partner.page.dart +++ b/mobile/lib/pages/library/partner/partner.page.dart @@ -73,7 +73,8 @@ class PartnerPage extends HookConsumerWidget { builder: (BuildContext context) { return ConfirmDialog( title: "stop_photo_sharing", - content: "partner_page_stop_sharing_content".tr(args: [u.name]), + content: "partner_page_stop_sharing_content" + .tr(namedArgs: {'partner': u.name}), onOk: () => ref.read(partnerServiceProvider).removePartner(u), ); }, diff --git a/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart b/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart index e4bf1ebe9b..6c18841089 100644 --- a/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart +++ b/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart @@ -7,11 +7,11 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/models/shared_link/shared_link.model.dart'; +import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/shared_link.provider.dart'; import 'package:immich_mobile/services/shared_link.service.dart'; -import 'package:immich_mobile/providers/server_info.provider.dart'; -import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/utils/url_helper.dart'; +import 'package:immich_mobile/widgets/common/immich_toast.dart'; @RoutePage() class SharedLinkEditPage extends HookConsumerWidget { @@ -241,8 +241,8 @@ class SharedLinkEditPage extends HookConsumerWidget { ), DropdownMenuEntry( value: 30, - label: - "shared_link_edit_expire_after_option_minutes".tr(args: ["30"]), + label: "shared_link_edit_expire_after_option_minutes" + .tr(namedArgs: {'count': "30"}), ), DropdownMenuEntry( value: 60, @@ -250,7 +250,8 @@ class SharedLinkEditPage extends HookConsumerWidget { ), DropdownMenuEntry( value: 60 * 6, - label: "shared_link_edit_expire_after_option_hours".tr(args: ["6"]), + label: "shared_link_edit_expire_after_option_hours" + .tr(namedArgs: {'count': "6"}), ), DropdownMenuEntry( value: 60 * 24, @@ -258,20 +259,23 @@ class SharedLinkEditPage extends HookConsumerWidget { ), DropdownMenuEntry( value: 60 * 24 * 7, - label: "shared_link_edit_expire_after_option_days".tr(args: ["7"]), + label: "shared_link_edit_expire_after_option_days" + .tr(namedArgs: {'count': "7"}), ), DropdownMenuEntry( value: 60 * 24 * 30, - label: "shared_link_edit_expire_after_option_days".tr(args: ["30"]), + label: "shared_link_edit_expire_after_option_days" + .tr(namedArgs: {'count': "30"}), ), DropdownMenuEntry( value: 60 * 24 * 30 * 3, - label: - "shared_link_edit_expire_after_option_months".tr(args: ["3"]), + label: "shared_link_edit_expire_after_option_months" + .tr(namedArgs: {'count': "3"}), ), DropdownMenuEntry( value: 60 * 24 * 30 * 12, - label: "shared_link_edit_expire_after_option_year".tr(args: ["1"]), + label: "shared_link_edit_expire_after_option_year" + .tr(namedArgs: {'count': "1"}), ), ], ); diff --git a/mobile/lib/pages/library/trash.page.dart b/mobile/lib/pages/library/trash.page.dart index f8a1d7605d..c645719974 100644 --- a/mobile/lib/pages/library/trash.page.dart +++ b/mobile/lib/pages/library/trash.page.dart @@ -4,18 +4,18 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/extensions/asyncvalue_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/asset.provider.dart'; -import 'package:immich_mobile/providers/timeline.provider.dart'; -import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; -import 'package:immich_mobile/widgets/asset_grid/delete_dialog.dart'; -import 'package:immich_mobile/providers/trash.provider.dart'; -import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; +import 'package:immich_mobile/providers/timeline.provider.dart'; +import 'package:immich_mobile/providers/trash.provider.dart'; +import 'package:immich_mobile/utils/immich_loading_overlay.dart'; +import 'package:immich_mobile/widgets/asset_grid/delete_dialog.dart'; +import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/widgets/common/confirm_dialog.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; -import 'package:immich_mobile/utils/immich_loading_overlay.dart'; @RoutePage() class TrashPage extends HookConsumerWidget { @@ -77,7 +77,7 @@ class TrashPage extends HookConsumerWidget { ImmichToast.show( context: context, msg: 'assets_deleted_permanently' - .tr(args: ["${selection.value.length}"]), + .tr(namedArgs: {'count': "${selection.value.length}"}), gravity: ToastGravity.BOTTOM, ); } @@ -118,7 +118,7 @@ class TrashPage extends HookConsumerWidget { ImmichToast.show( context: context, msg: 'assets_restored_successfully' - .tr(args: ["${selection.value.length}"]), + .tr(namedArgs: {'count': "${selection.value.length}"}), gravity: ToastGravity.BOTTOM, ); } @@ -135,7 +135,7 @@ class TrashPage extends HookConsumerWidget { ? "${selection.value.length}" : "trash_page_select_assets_btn".tr(); } - return 'trash_page_title'.tr(args: [count]); + return 'trash_page_title'.tr(namedArgs: {'count': count}); } AppBar buildAppBar(String count) { @@ -260,7 +260,7 @@ class TrashPage extends HookConsumerWidget { ), child: const Text( "trash_page_info", - ).tr(args: ["$trashDays"]), + ).tr(namedArgs: {"days": "$trashDays"}), ), ), ), diff --git a/mobile/lib/pages/share_intent/share_intent.page.dart b/mobile/lib/pages/share_intent/share_intent.page.dart index 4e19fda373..ff137ce0aa 100644 --- a/mobile/lib/pages/share_intent/share_intent.page.dart +++ b/mobile/lib/pages/share_intent/share_intent.page.dart @@ -56,9 +56,7 @@ class ShareIntentPage extends HookConsumerWidget { title: Column( children: [ const Text('upload_to_immich').tr( - args: [ - candidates.length.toString(), - ], + namedArgs: {'count': candidates.length.toString()}, ), Text( currentEndpoint, @@ -176,8 +174,12 @@ class UploadingText extends StatelessWidget { return element.status == UploadStatus.complete; }).length; - return const Text("shared_intent_upload_button_progress_text") - .tr(args: [uploadedCount.toString(), candidates.length.toString()]); + return const Text("shared_intent_upload_button_progress_text").tr( + namedArgs: { + 'current': uploadedCount.toString(), + 'total': candidates.length.toString(), + }, + ); } } diff --git a/mobile/lib/providers/backup/manual_upload.provider.dart b/mobile/lib/providers/backup/manual_upload.provider.dart index fc7e4d866c..646a03cebc 100644 --- a/mobile/lib/providers/backup/manual_upload.provider.dart +++ b/mobile/lib/providers/backup/manual_upload.provider.dart @@ -6,27 +6,27 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/widgets.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/entities/backup_album.entity.dart'; import 'package:immich_mobile/models/backup/backup_candidate.model.dart'; -import 'package:immich_mobile/models/backup/success_upload_asset.model.dart'; -import 'package:immich_mobile/repositories/file_media.repository.dart'; -import 'package:immich_mobile/services/background.service.dart'; import 'package:immich_mobile/models/backup/backup_state.model.dart'; import 'package:immich_mobile/models/backup/current_upload_asset.model.dart'; import 'package:immich_mobile/models/backup/error_upload_asset.model.dart'; import 'package:immich_mobile/models/backup/manual_upload_state.model.dart'; +import 'package:immich_mobile/models/backup/success_upload_asset.model.dart'; +import 'package:immich_mobile/providers/app_life_cycle.provider.dart'; +import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; import 'package:immich_mobile/providers/backup/error_backup_list.provider.dart'; -import 'package:immich_mobile/services/backup.service.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; -import 'package:immich_mobile/providers/app_settings.provider.dart'; +import 'package:immich_mobile/repositories/file_media.repository.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; -import 'package:immich_mobile/entities/asset.entity.dart'; -import 'package:immich_mobile/providers/app_life_cycle.provider.dart'; +import 'package:immich_mobile/services/background.service.dart'; +import 'package:immich_mobile/services/backup.service.dart'; import 'package:immich_mobile/services/backup_album.service.dart'; import 'package:immich_mobile/services/local_notification.service.dart'; -import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/utils/backup_progress.dart'; +import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:logging/logging.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:photo_manager/photo_manager.dart' show PMProgressHandler; @@ -170,7 +170,7 @@ class ManualUploadNotifier extends StateNotifier { if (state.showDetailedNotification) { final title = "backup_background_service_current_upload_notification" - .tr(args: [state.currentUploadAsset.fileName]); + .tr(namedArgs: {'filename': state.currentUploadAsset.fileName}); _throttledDetailNotify(title: title, progress: sent, total: total); } } @@ -186,7 +186,7 @@ class ManualUploadNotifier extends StateNotifier { if (state.showDetailedNotification) { _throttledDetailNotify.title = "backup_background_service_current_upload_notification" - .tr(args: [currentUploadAsset.fileName]); + .tr(namedArgs: {'filename': currentUploadAsset.fileName}); _throttledDetailNotify.progress = 0; _throttledDetailNotify.total = 0; } diff --git a/mobile/lib/services/background.service.dart b/mobile/lib/services/background.service.dart index 2d63e1fc18..84cbaae6ed 100644 --- a/mobile/lib/services/background.service.dart +++ b/mobile/lib/services/background.service.dart @@ -562,7 +562,7 @@ class BackgroundService { void _onBackupError(ErrorUploadAsset errorAssetInfo) { _showErrorNotification( title: "backup_background_service_upload_failure_notification" - .tr(args: [errorAssetInfo.fileName]), + .tr(namedArgs: {'filename': errorAssetInfo.fileName}), individualTag: errorAssetInfo.id, ); } @@ -577,7 +577,7 @@ class BackgroundService { _throttledDetailNotify.title = "backup_background_service_current_upload_notification" - .tr(args: [currentUploadAsset.fileName]); + .tr(namedArgs: {'filename': currentUploadAsset.fileName}); _throttledDetailNotify.progress = 0; _throttledDetailNotify.total = 0; } diff --git a/mobile/lib/services/memory.service.dart b/mobile/lib/services/memory.service.dart index 6ae8e1d0bb..efd38f1140 100644 --- a/mobile/lib/services/memory.service.dart +++ b/mobile/lib/services/memory.service.dart @@ -42,7 +42,8 @@ class MemoryService { if (dbAssets.isNotEmpty) { final String title = yearsAgo <= 1 ? 'memories_year_ago'.tr() - : 'memories_years_ago'.tr(args: [yearsAgo.toString()]); + : 'memories_years_ago' + .tr(namedArgs: {'years': yearsAgo.toString()}); memories.add( Memory( title: title, diff --git a/mobile/lib/widgets/album/album_thumbnail_card.dart b/mobile/lib/widgets/album/album_thumbnail_card.dart index f6f834e00d..79944ef15f 100644 --- a/mobile/lib/widgets/album/album_thumbnail_card.dart +++ b/mobile/lib/widgets/album/album_thumbnail_card.dart @@ -61,7 +61,8 @@ class AlbumThumbnailCard extends ConsumerWidget { if (album.ownerId == ref.read(currentUserProvider)?.id) { owner = 'owned'.tr(); } else if (album.ownerName != null) { - owner = 'album_thumbnail_shared_by'.tr(args: [album.ownerName!]); + owner = 'album_thumbnail_shared_by' + .tr(namedArgs: {'user': album.ownerName!}); } } @@ -74,10 +75,9 @@ class AlbumThumbnailCard extends ConsumerWidget { children: [ TextSpan( text: album.assetCount == 1 - ? 'album_thumbnail_card_item' - .tr(args: ['${album.assetCount}']) + ? 'album_thumbnail_card_item'.tr() : 'album_thumbnail_card_items' - .tr(args: ['${album.assetCount}']), + .tr(namedArgs: {'count': '${album.assetCount}'}), ), if (owner != null) const TextSpan(text: ' • '), if (owner != null) TextSpan(text: owner), diff --git a/mobile/lib/widgets/album/album_thumbnail_listtile.dart b/mobile/lib/widgets/album/album_thumbnail_listtile.dart index 3c1e3a8ee0..17c2a6bd12 100644 --- a/mobile/lib/widgets/album/album_thumbnail_listtile.dart +++ b/mobile/lib/widgets/album/album_thumbnail_listtile.dart @@ -2,9 +2,9 @@ import 'package:auto_route/auto_route.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/services/api.service.dart'; import 'package:immich_mobile/utils/image_url_builder.dart'; import 'package:openapi/api.dart'; @@ -96,7 +96,7 @@ class AlbumThumbnailListTile extends StatelessWidget { style: const TextStyle( fontSize: 12, ), - ).tr(args: ['${album.assetCount}']), + ).tr(namedArgs: {'count': '${album.assetCount}'}), if (album.shared) const Text( 'album_thumbnail_card_shared', diff --git a/mobile/lib/widgets/asset_grid/multiselect_grid.dart b/mobile/lib/widgets/asset_grid/multiselect_grid.dart index 5ec59e3eeb..ceaee581d2 100644 --- a/mobile/lib/widgets/asset_grid/multiselect_grid.dart +++ b/mobile/lib/widgets/asset_grid/multiselect_grid.dart @@ -7,24 +7,24 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/extensions/collection_extensions.dart'; -import 'package:immich_mobile/providers/album/album.provider.dart'; -import 'package:immich_mobile/services/album.service.dart'; -import 'package:immich_mobile/services/stack.service.dart'; -import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; -import 'package:immich_mobile/models/asset_selection_state.dart'; -import 'package:immich_mobile/providers/multiselect.provider.dart'; -import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart'; -import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; -import 'package:immich_mobile/widgets/asset_grid/control_bottom_app_bar.dart'; -import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; +import 'package:immich_mobile/extensions/collection_extensions.dart'; +import 'package:immich_mobile/models/asset_selection_state.dart'; +import 'package:immich_mobile/providers/album/album.provider.dart'; import 'package:immich_mobile/providers/asset.provider.dart'; +import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; +import 'package:immich_mobile/providers/multiselect.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; -import 'package:immich_mobile/widgets/common/immich_toast.dart'; +import 'package:immich_mobile/routing/router.dart'; +import 'package:immich_mobile/services/album.service.dart'; +import 'package:immich_mobile/services/stack.service.dart'; import 'package:immich_mobile/utils/immich_loading_overlay.dart'; import 'package:immich_mobile/utils/selection_handlers.dart'; +import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart'; +import 'package:immich_mobile/widgets/asset_grid/control_bottom_app_bar.dart'; +import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; +import 'package:immich_mobile/widgets/common/immich_toast.dart'; class MultiselectGrid extends HookConsumerWidget { const MultiselectGrid({ @@ -190,8 +190,9 @@ class MultiselectGrid extends HookConsumerWidget { context: context, msg: force ? 'assets_deleted_permanently' - .tr(args: ["${selection.value.length}"]) - : 'assets_trashed'.tr(args: ["${selection.value.length}"]), + .tr(namedArgs: {'count': "${selection.value.length}"}) + : 'assets_trashed' + .tr(namedArgs: {'count': "${selection.value.length}"}), gravity: ToastGravity.BOTTOM, ); selectionEnabledHook.value = false; @@ -225,7 +226,7 @@ class MultiselectGrid extends HookConsumerWidget { ImmichToast.show( context: context, msg: 'assets_removed_permanently_from_device' - .tr(args: ["$deletedCount"]), + .tr(namedArgs: {'count': "$deletedCount"}), gravity: ToastGravity.BOTTOM, ); @@ -254,8 +255,9 @@ class MultiselectGrid extends HookConsumerWidget { context: context, msg: shouldDeletePermanently ? 'assets_deleted_permanently_from_server' - .tr(args: ["${toDelete.length}"]) - : 'assets_trashed_from_server'.tr(args: ["${toDelete.length}"]), + .tr(namedArgs: {'count': "${toDelete.length}"}) + : 'assets_trashed_from_server' + .tr(namedArgs: {'count': "${toDelete.length}"}), gravity: ToastGravity.BOTTOM, ); } diff --git a/mobile/lib/widgets/asset_viewer/detail_panel/people_info.dart b/mobile/lib/widgets/asset_viewer/detail_panel/people_info.dart index 712e939ad5..8d2a38c700 100644 --- a/mobile/lib/widgets/asset_viewer/detail_panel/people_info.dart +++ b/mobile/lib/widgets/asset_viewer/detail_panel/people_info.dart @@ -2,13 +2,13 @@ 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/entities/asset.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/providers/asset_viewer/asset_people.provider.dart'; import 'package:immich_mobile/models/search/search_curated_content.model.dart'; +import 'package:immich_mobile/providers/asset_viewer/asset_people.provider.dart'; +import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/widgets/search/curated_people_row.dart'; import 'package:immich_mobile/widgets/search/person_name_edit_form.dart'; -import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/entities/asset.entity.dart'; class PeopleInfo extends ConsumerWidget { final Asset asset; @@ -109,13 +109,13 @@ class PeopleInfo extends ConsumerWidget { if (ageInMonths <= 11) { return "exif_bottom_sheet_person_age_months" - .tr(args: [ageInMonths.toString()]); + .tr(namedArgs: {'months': ageInMonths.toString()}); } else if (ageInMonths > 12 && ageInMonths <= 23) { return "exif_bottom_sheet_person_age_year_months" - .tr(args: [(ageInMonths - 12).toString()]); + .tr(namedArgs: {'months': (ageInMonths - 12).toString()}); } else { return "exif_bottom_sheet_person_age_years" - .tr(args: [ageInYears.toString()]); + .tr(namedArgs: {'years': ageInYears.toString()}); } } diff --git a/mobile/lib/widgets/backup/asset_info_table.dart b/mobile/lib/widgets/backup/asset_info_table.dart index 222e516cf7..98bcc2b3da 100644 --- a/mobile/lib/widgets/backup/asset_info_table.dart +++ b/mobile/lib/widgets/backup/asset_info_table.dart @@ -56,9 +56,12 @@ class BackupAssetInfoTable extends ConsumerWidget { fontSize: 10.0, ), ).tr( - args: isUploadInProgress - ? [asset.fileName, asset.fileType.toLowerCase()] - : ["-", "-"], + namedArgs: isUploadInProgress + ? { + 'filename': asset.fileName, + 'size': asset.fileType.toLowerCase(), + } + : {'filename': "-", 'size': "-"}, ), ), ), @@ -78,9 +81,11 @@ class BackupAssetInfoTable extends ConsumerWidget { fontSize: 10.0, ), ).tr( - args: [ - isUploadInProgress ? _getAssetCreationDate(asset) : "-", - ], + namedArgs: { + 'date': isUploadInProgress + ? _getAssetCreationDate(asset) + : "-", + }, ), ), ), @@ -99,9 +104,7 @@ class BackupAssetInfoTable extends ConsumerWidget { fontSize: 10.0, ), ).tr( - args: [ - isUploadInProgress ? asset.id : "-", - ], + namedArgs: {'id': isUploadInProgress ? asset.id : "-"}, ), ), ), diff --git a/mobile/lib/widgets/backup/error_chip_text.dart b/mobile/lib/widgets/backup/error_chip_text.dart index 540e136722..38c527ccfa 100644 --- a/mobile/lib/widgets/backup/error_chip_text.dart +++ b/mobile/lib/widgets/backup/error_chip_text.dart @@ -21,8 +21,6 @@ class BackupErrorChipText extends ConsumerWidget { fontWeight: FontWeight.bold, fontSize: 11, ), - ).tr( - args: [count.toString()], - ); + ).tr(namedArgs: {'count': count.toString()}); } } 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 da863ef142..b2b24bd01c 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 @@ -5,17 +5,17 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/models/backup/backup_state.model.dart'; +import 'package:immich_mobile/providers/asset.provider.dart'; +import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; -import 'package:immich_mobile/providers/auth.provider.dart'; -import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/providers/asset.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/providers/websocket.provider.dart'; +import 'package:immich_mobile/routing/router.dart'; +import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:immich_mobile/widgets/common/app_bar_dialog/app_bar_profile_info.dart'; import 'package:immich_mobile/widgets/common/app_bar_dialog/app_bar_server_info.dart'; import 'package:immich_mobile/widgets/common/confirm_dialog.dart'; -import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:url_launcher/url_launcher.dart'; class ImmichAppBarDialog extends HookConsumerWidget { @@ -200,10 +200,10 @@ class ImmichAppBarDialog extends HookConsumerWidget { padding: const EdgeInsets.only(top: 12.0), child: const Text('backup_controller_page_storage_format').tr( - args: [ - usedDiskSpace, - totalDiskSpace, - ], + namedArgs: { + 'used': usedDiskSpace, + 'total': totalDiskSpace, + }, ), ), ], diff --git a/mobile/lib/widgets/map/map_asset_grid.dart b/mobile/lib/widgets/map/map_asset_grid.dart index a9ddc86df9..4a3bb69cc0 100644 --- a/mobile/lib/widgets/map/map_asset_grid.dart +++ b/mobile/lib/widgets/map/map_asset_grid.dart @@ -1,20 +1,21 @@ import 'dart:math' as math; + import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/collection_extensions.dart'; -import 'package:immich_mobile/providers/timeline.provider.dart'; -import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart'; -import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/models/map/map_event.model.dart'; -import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/providers/db.provider.dart'; -import 'package:immich_mobile/widgets/common/drag_sheet.dart'; +import 'package:immich_mobile/providers/timeline.provider.dart'; import 'package:immich_mobile/utils/color_filter_generator.dart'; import 'package:immich_mobile/utils/throttle.dart'; +import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart'; +import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; +import 'package:immich_mobile/widgets/common/drag_sheet.dart'; import 'package:logging/logging.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; @@ -252,7 +253,8 @@ class _MapSheetDragRegion extends StatelessWidget { @override Widget build(BuildContext context) { final assetsInBoundsText = assetsInBoundCount > 0 - ? "map_assets_in_bounds".tr(args: [assetsInBoundCount.toString()]) + ? "map_assets_in_bounds" + .tr(namedArgs: {'count': assetsInBoundCount.toString()}) : "map_no_assets_in_bounds".tr(); return SingleChildScrollView( diff --git a/mobile/lib/widgets/map/map_settings/map_settings_time_dropdown.dart b/mobile/lib/widgets/map/map_settings/map_settings_time_dropdown.dart index c613029886..e23716af95 100644 --- a/mobile/lib/widgets/map/map_settings/map_settings_time_dropdown.dart +++ b/mobile/lib/widgets/map/map_settings/map_settings_time_dropdown.dart @@ -44,13 +44,13 @@ class MapTimeDropDown extends StatelessWidget { DropdownMenuEntry( value: 7, label: "map_settings_date_range_option_days".tr( - args: ["7"], + namedArgs: {'days': "7"}, ), ), DropdownMenuEntry( value: 30, label: "map_settings_date_range_option_days".tr( - args: ["30"], + namedArgs: {'days': "30"}, ), ), DropdownMenuEntry( @@ -81,7 +81,8 @@ class MapTimeDropDown extends StatelessWidget { ), ) .inDays, - label: "map_settings_date_range_option_years".tr(args: ["3"]), + label: "map_settings_date_range_option_years" + .tr(namedArgs: {'years': "3"}), ), ], ), diff --git a/mobile/lib/widgets/settings/advanced_settings.dart b/mobile/lib/widgets/settings/advanced_settings.dart index d65186a191..6a67992712 100644 --- a/mobile/lib/widgets/settings/advanced_settings.dart +++ b/mobile/lib/widgets/settings/advanced_settings.dart @@ -85,7 +85,8 @@ class AdvancedSettings extends HookConsumerWidget { }, ), SettingsSliderListTile( - text: "advanced_settings_log_level_title".tr(args: [logLevel]), + text: "advanced_settings_log_level_title" + .tr(namedArgs: {'level': logLevel}), valueNotifier: levelId, maxValue: 8, minValue: 1, diff --git a/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart b/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart index 4584b7e688..72402c8d55 100644 --- a/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart +++ b/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart @@ -3,10 +3,10 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; +import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; import 'package:immich_mobile/widgets/settings/settings_slider_list_tile.dart'; import 'package:immich_mobile/widgets/settings/settings_sub_title.dart'; import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; -import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; class LayoutSettings extends HookConsumerWidget { const LayoutSettings({ @@ -30,7 +30,7 @@ class LayoutSettings extends HookConsumerWidget { SettingsSliderListTile( valueNotifier: tilesPerRow, text: 'theme_setting_asset_list_tiles_per_row_title' - .tr(args: ["${tilesPerRow.value}"]), + .tr(namedArgs: {'count': "${tilesPerRow.value}"}), label: "${tilesPerRow.value}", maxValue: 6, minValue: 2, diff --git a/mobile/lib/widgets/settings/backup_settings/background_settings.dart b/mobile/lib/widgets/settings/backup_settings/background_settings.dart index 4cdeb501c1..d628309050 100644 --- a/mobile/lib/widgets/settings/backup_settings/background_settings.dart +++ b/mobile/lib/widgets/settings/backup_settings/background_settings.dart @@ -164,10 +164,14 @@ class _BackgroundSettingsEnabled extends HookConsumerWidget { switch (v) { 0 => 5000, 1 => 30000, 2 => 120000, _ => 600000 }; String formatBackupDelaySliderValue(int v) => switch (v) { - 0 => 'setting_notifications_notify_seconds'.tr(args: const ['5']), - 1 => 'setting_notifications_notify_seconds'.tr(args: const ['30']), - 2 => 'setting_notifications_notify_minutes'.tr(args: const ['2']), - _ => 'setting_notifications_notify_minutes'.tr(args: const ['10']), + 0 => 'setting_notifications_notify_seconds' + .tr(namedArgs: {'count': '5'}), + 1 => 'setting_notifications_notify_seconds' + .tr(namedArgs: {'count': '30'}), + 2 => 'setting_notifications_notify_minutes' + .tr(namedArgs: {'count': '2'}), + _ => 'setting_notifications_notify_minutes' + .tr(namedArgs: {'count': '10'}), }; final backupTriggerDelay = @@ -221,7 +225,9 @@ class _BackgroundSettingsEnabled extends HookConsumerWidget { SettingsSliderListTile( valueNotifier: triggerDelay, text: 'backup_controller_page_background_delay'.tr( - args: [formatBackupDelaySliderValue(triggerDelay.value)], + namedArgs: { + 'duration': formatBackupDelaySliderValue(triggerDelay.value), + }, ), maxValue: 3.0, noDivisons: 3, diff --git a/mobile/lib/widgets/settings/local_storage_settings.dart b/mobile/lib/widgets/settings/local_storage_settings.dart index 5b21d9bd4d..06db78cb97 100644 --- a/mobile/lib/widgets/settings/local_storage_settings.dart +++ b/mobile/lib/widgets/settings/local_storage_settings.dart @@ -1,9 +1,9 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' show useEffect, useState; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/entities/duplicated_asset.entity.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/duplicated_asset.entity.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/providers/db.provider.dart'; @@ -35,7 +35,7 @@ class LocalStorageSettings extends HookConsumerWidget { style: context.textTheme.bodyLarge?.copyWith( fontWeight: FontWeight.w500, ), - ).tr(args: ["${cacheItemCount.value}"]), + ).tr(namedArgs: {'count': "${cacheItemCount.value}"}), subtitle: Text( "cache_settings_duplicated_assets_subtitle", style: context.textTheme.bodyMedium?.copyWith( diff --git a/mobile/lib/widgets/settings/notification_setting.dart b/mobile/lib/widgets/settings/notification_setting.dart index 6aef8f29b0..cf6745199e 100644 --- a/mobile/lib/widgets/settings/notification_setting.dart +++ b/mobile/lib/widgets/settings/notification_setting.dart @@ -4,11 +4,11 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/notification_permission.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; +import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; import 'package:immich_mobile/widgets/settings/settings_button_list_tile.dart'; import 'package:immich_mobile/widgets/settings/settings_slider_list_tile.dart'; import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; -import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; import 'package:permission_handler/permission_handler.dart'; class NotificationSetting extends HookConsumerWidget { @@ -90,7 +90,7 @@ class NotificationSetting extends HookConsumerWidget { enabled: hasPermission, valueNotifier: sliderValue, text: 'setting_notifications_notify_failures_grace_period' - .tr(args: [formattedValue]), + .tr(namedArgs: {'duration': formattedValue}), maxValue: 5.0, noDivisons: 5, label: formattedValue, @@ -105,13 +105,14 @@ String _formatSliderValue(double v) { if (v == 0.0) { return 'setting_notifications_notify_immediately'.tr(); } else if (v == 1.0) { - return 'setting_notifications_notify_minutes'.tr(args: const ['30']); + return 'setting_notifications_notify_minutes' + .tr(namedArgs: {'count': '30'}); } else if (v == 2.0) { - return 'setting_notifications_notify_hours'.tr(args: const ['2']); + return 'setting_notifications_notify_hours'.tr(namedArgs: {'count': '2'}); } else if (v == 3.0) { - return 'setting_notifications_notify_hours'.tr(args: const ['8']); + return 'setting_notifications_notify_hours'.tr(namedArgs: {'count': '8'}); } else if (v == 4.0) { - return 'setting_notifications_notify_hours'.tr(args: const ['24']); + return 'setting_notifications_notify_hours'.tr(namedArgs: {'count': '24'}); } else { return 'setting_notifications_notify_never'.tr(); } diff --git a/mobile/lib/widgets/shared_link/shared_link_item.dart b/mobile/lib/widgets/shared_link/shared_link_item.dart index 5fdffa0537..69e763ea09 100644 --- a/mobile/lib/widgets/shared_link/shared_link_item.dart +++ b/mobile/lib/widgets/shared_link/shared_link_item.dart @@ -1,4 +1,5 @@ import 'dart:math' as math; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -6,15 +7,15 @@ import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/widgets/search/thumbnail_with_info.dart'; import 'package:immich_mobile/models/shared_link/shared_link.model.dart'; +import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/shared_link.provider.dart'; import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/providers/server_info.provider.dart'; -import 'package:immich_mobile/widgets/common/confirm_dialog.dart'; -import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/utils/image_url_builder.dart'; import 'package:immich_mobile/utils/url_helper.dart'; +import 'package:immich_mobile/widgets/common/confirm_dialog.dart'; +import 'package:immich_mobile/widgets/common/immich_toast.dart'; +import 'package:immich_mobile/widgets/search/thumbnail_with_info.dart'; class SharedLinkItem extends ConsumerWidget { final SharedLink sharedLink; @@ -44,17 +45,17 @@ class SharedLinkItem extends ConsumerWidget { if (difference.inHours % 24 > 12) { dayDifference += 1; } - expiresText = - "shared_link_expires_days".tr(args: [dayDifference.toString()]); + expiresText = "shared_link_expires_days" + .tr(namedArgs: {'count': dayDifference.toString()}); } else if (difference.inHours > 0) { expiresText = "shared_link_expires_hours" - .tr(args: [difference.inHours.toString()]); + .tr(namedArgs: {'count': difference.inHours.toString()}); } else if (difference.inMinutes > 0) { expiresText = "shared_link_expires_minutes" - .tr(args: [difference.inMinutes.toString()]); + .tr(namedArgs: {'count': difference.inMinutes.toString()}); } else if (difference.inSeconds > 0) { expiresText = "shared_link_expires_seconds" - .tr(args: [difference.inSeconds.toString()]); + .tr(namedArgs: {'count': difference.inSeconds.toString()}); } } return Text(