Files
photo-live/apps/mobile/lib/l10n/app_localizations_en.dart
T
浅念 33f347cdea feat(app): P0 batch 3 — offline detection with engine pause/resume + UI banner
P0-4 离线感知:
  - connectivity_plus → NetworkAvailability(online/offline/unknown)
  - engine_scope 三重绑定:有账号+有网 → start;任一失去 → stop(在途不中断)
  - 网络恢复 → start + onNetworkRestored(waitingNetwork 即时重试)
  - HomePage 顶部离线黄条(wifi_off + i18n 双语)

P0-5 更正:EXIF 方向已由服务端 sharp .rotate() 自动转正——v2 分析误报

397/397 全绿、analyze 0

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-28 11:23:51 +08:00

1042 lines
23 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String get appName => 'Photo Live';
@override
String get login => 'Sign in';
@override
String get logout => 'Sign out';
@override
String get username => 'Account';
@override
String get password => 'Password';
@override
String get albums => 'Albums';
@override
String get albumDetail => 'Album details';
@override
String get queue => 'Uploads';
@override
String get settings => 'Settings';
@override
String get language => 'Language';
@override
String get settingsSectionAccount => 'Account';
@override
String get settingsSectionLanguage => 'Language';
@override
String get settingsSectionSecurity => 'Security';
@override
String get settingsSectionUploadHelp => 'Upload help';
@override
String get settingsSectionAbout => 'About';
@override
String get settingsSignedInAccount => 'Currently signed-in account';
@override
String get settingsVersion => 'Version';
@override
String get settingsUploadHelpTitle => 'How background uploads work';
@override
String get settingsUploadHelpBody =>
'While the app stays in the background, the system keeps uploads running within its battery limits. If you force quit the app or the system stops it, unfinished tasks pause and resume the next time you open the app. Tasks waiting for the network start automatically once a connection is available — no manual retry needed.';
@override
String get logoutConfirmTitle => 'Sign out?';
@override
String get logoutConfirmBody =>
'Local upload tasks are preserved on this device and will resume when you sign back in.';
@override
String get localeFollowSystem => 'Follow system';
@override
String get localeChinese => '中文';
@override
String get localeEnglish => 'English';
@override
String get retry => 'Retry';
@override
String get cancel => 'Cancel';
@override
String get errorGeneric => 'Something went wrong, please retry';
@override
String get ok => 'OK';
@override
String get navAlbums => 'Albums';
@override
String get navUploads => 'Uploads';
@override
String get navSettings => 'Settings';
@override
String badgeUploading(int count) {
return '$count tasks';
}
@override
String get albumUploadsOn => 'Uploads on';
@override
String get albumUploadsOff => 'Uploads off';
@override
String get albumPublicOff => 'Not public';
@override
String get loginHint => 'Sign in with your staff account';
@override
String get loginTitle => 'Your event. In focus.';
@override
String get loginSubtitle => 'Sign in to manage albums and photos';
@override
String get loginAskAdmin => 'Ask admin for account';
@override
String get loginShowPassword => 'Show password';
@override
String get loginHidePassword => 'Hide password';
@override
String get languageDone => 'Done';
@override
String get passwordSecurityHint =>
'Choose a new password with at least 8 characters.';
@override
String get passwordSave => 'Save password';
@override
String get settingsSectionGeneral => 'General';
@override
String get logoutConfirmBodyIdle => 'You will be signed out on this device.';
@override
String get fieldRequired => 'This field is required';
@override
String get passwordChangeTitle => 'Change password';
@override
String get currentPassword => 'Current password';
@override
String get newPassword => 'New password';
@override
String get confirmNewPassword => 'Confirm new password';
@override
String get passwordMinLength => 'New password must be at least 8 characters';
@override
String get passwordMismatch => 'New passwords do not match';
@override
String get passwordChangeSuccess => 'Password changed';
@override
String get errorAuthInvalidCredentials => 'Incorrect account or password';
@override
String get errorOldPasswordIncorrect => 'Current password is incorrect';
@override
String get errorAuthRateLimited =>
'Too many attempts. Please try again later';
@override
String get errorAuthTokenExpired => 'Session expired. Please sign in again';
@override
String get errorValidation => 'Invalid input. Please check and retry';
@override
String get errorNetwork => 'Network error. Check your connection and retry';
@override
String get errorNetworkTimeout => 'Network timed out. Please retry';
@override
String get errorInternal =>
'Service temporarily unavailable. Please retry later';
@override
String get albumsEmpty =>
'No albums yet. Tap \"Create album\" to get started';
@override
String get loadMoreFailed => 'Failed to load more. Tap to retry';
@override
String get albumCreate => 'Create album';
@override
String get albumTitle => 'Title';
@override
String get albumDescription => 'Description';
@override
String get albumVenue => 'Venue';
@override
String get albumAddress => 'Address';
@override
String get albumStartAt => 'Start time';
@override
String get albumEndAtOptional => 'End time (optional)';
@override
String get clearEndAt => 'Clear end time';
@override
String get albumTimezone => 'Timezone';
@override
String get albumTimezoneInvalid => 'Invalid IANA timezone name';
@override
String get formStartAtRequired => 'Pick a start time';
@override
String get formDefaultLocaleMissing => 'Default locale must have a title';
@override
String get formTitleRequiredWithFields =>
'Title is required when description, venue or address is filled';
@override
String get formEndAtNotAfterStartAt => 'End time must be after start time';
@override
String get formEventDetails => 'Event details';
@override
String get coverPicker => 'Album cover';
@override
String get coverPickerHint => 'Tap to select a cover image (optional)';
@override
String get coverSelected => 'Cover selected, will upload on save';
@override
String get coverUploadFailed =>
'Cover upload failed, you can retry from album detail later';
@override
String get formDescriptionLanguages => 'Description & languages';
@override
String get formDefaultLanguage => 'Default language';
@override
String get formDetailsTab => 'Details';
@override
String get formAccessTab => 'Access';
@override
String get formAllowUploads => 'Allow uploads';
@override
String get formAllowUploadsDesc =>
'Allow staff to upload photos to this album';
@override
String get formPublicAccess => 'Public access';
@override
String get formPublicAccessDesc => 'Anyone with the link can view photos';
@override
String get formAllowDownloads => 'Allow downloads';
@override
String get formAllowDownloadsDesc =>
'Viewers can download browse-quality photos';
@override
String get formOriginalDownloads => 'Original downloads';
@override
String get formOriginalDownloadsDesc =>
'Viewers can download original photos';
@override
String get createAlbumTitle => 'Create album';
@override
String get createAlbumSubmit => 'Create album';
@override
String get editAlbumTitle => 'Edit album';
@override
String get saveChanges => 'Save changes';
@override
String get unsavedChangesTitle => 'Discard changes?';
@override
String get unsavedChangesBody =>
'Your edits are not saved yet. Leaving now will discard them.';
@override
String get discardChanges => 'Discard';
@override
String get keepEditing => 'Keep editing';
@override
String get create => 'Create';
@override
String get save => 'Save';
@override
String get albumStatusActive => 'Active';
@override
String get albumStatusOffline => 'Offline';
@override
String get tagUpload => 'Upload';
@override
String get tagPublic => 'Public';
@override
String get tagDownload => 'Download';
@override
String get tagOriginal => 'Original';
@override
String get notSet => 'Not set';
@override
String get actionEdit => 'Edit';
@override
String get membersTitle => 'Members';
@override
String membersTitleCount(int count) {
return 'Members ($count)';
}
@override
String get ownerGroup => 'Owner';
@override
String get collaboratorsGroup => 'Collaborators';
@override
String get noCollaborators => 'No collaborators yet';
@override
String get inviteColleague => 'Invite colleague';
@override
String get alreadyAdded => 'Already added';
@override
String get add => 'Add';
@override
String get categoriesTitle => 'Categories';
@override
String get newCategory => 'New category';
@override
String get editCategory => 'Edit category';
@override
String deleteCategoryConfirm(String name) {
return 'Delete \"$name\"? Its photos will become uncategorized.';
}
@override
String get noCategories => 'No categories yet';
@override
String get albumCategories => 'Categories';
@override
String get shareQrTitle => 'Share QR code';
@override
String get albumPhotos => 'Photos';
@override
String get delete => 'Delete';
@override
String get categoryNameZh => 'Chinese name';
@override
String get categoryNameEn => 'English name';
@override
String get categorySortOrder => 'Sort order';
@override
String get categoryNameRequired => 'At least one language name is required';
@override
String get categorySortOrderInvalid => 'Sort order must be an integer';
@override
String get inviteSearchHint =>
'Search by account prefix to invite (at least 2 characters)';
@override
String get inviteNoResults => 'No matching users';
@override
String get memberInvited => 'Invited';
@override
String get removeMember => 'Remove member';
@override
String removeMemberConfirm(String name) {
return 'Remove $name from this album?';
}
@override
String get roleOwner => 'Owner';
@override
String get roleCollaborator => 'Collaborator';
@override
String get selfMarker => ' (you)';
@override
String get errorMemberConflict => 'User is already a member';
@override
String get qrHint => 'Scan the code or open the link to view';
@override
String get copyLink => 'Copy link';
@override
String get copiedToClipboard => 'Copied';
@override
String get openInBrowser => 'Open in browser';
@override
String get photosTask9Placeholder =>
'Photo management is a placeholder; the full experience ships in Task 9';
@override
String get albumPhotosEmpty => 'No photos yet';
@override
String get visibilityPublished => 'Published';
@override
String get visibilityUnpublished => 'Unpublished';
@override
String get visibilityHidden => 'Hidden';
@override
String get visibilityDeleted => 'Deleted';
@override
String get procPendingUpload => 'Pending upload';
@override
String get procUploaded => 'Uploaded';
@override
String get procProcessing => 'Processing';
@override
String get procReady => 'Ready';
@override
String get procProcessingFailed => 'Processing failed';
@override
String get queueStubHint =>
'Local upload queue and continuous capture arrive in Task 9';
@override
String get serverHistoryEntry => 'Server history';
@override
String get serverHistoryTitle => 'Server history (cross-device)';
@override
String get serverHistoryBanner =>
'Upload records from all of your devices. The local queue is on the Uploads tab.';
@override
String get serverHistoryEmpty => 'No upload sessions yet';
@override
String get uploadStatePending => 'Pending';
@override
String get uploadStateConfirmed => 'Confirmed';
@override
String get uploadStateCancelled => 'Cancelled';
@override
String get uploadStateExpired => 'Expired';
@override
String get thisDevice => 'This device';
@override
String get queueAlbumFilterAll => 'All albums';
@override
String get queueStateAll => 'All';
@override
String get queueStateInProgress => 'In progress';
@override
String get queueStateNeedsAttention => 'Needs attention';
@override
String get queueStateCompleted => 'Completed';
@override
String get queueSummaryCompleted => 'completed';
@override
String get queueSummaryUploading => 'uploading';
@override
String get queueSummaryWaiting => 'waiting';
@override
String get queueSummaryNeedAttention => 'need attention';
@override
String queueRowUploadingPercent(int percent) {
return 'Uploading $percent%';
}
@override
String get queueRowConfirming => 'Confirming upload';
@override
String get queueRowWaitingUpload => 'Waiting to upload';
@override
String get queueRowPreparing => 'Preparing photo';
@override
String get queueWaitingNetworkHint =>
'Resumes automatically when the network recovers';
@override
String get queueRowFileUnavailable => 'File unavailable';
@override
String get queueActionSelectAgain => 'Select again';
@override
String get queueActionRemoveRecord => 'Remove record';
@override
String get queueRemoveRecordTitle => 'Remove this record?';
@override
String get queueRemoveRecordBody =>
'This only removes the local task record. Photos already uploaded are not deleted from the cloud.';
@override
String get queueRemoveRecordConfirm => 'Remove';
@override
String get queueRetryAllScope =>
'Only failed uploads on this device are retried. Tasks waiting for the network recover automatically.';
@override
String get queueTimeAll => 'Any time';
@override
String get queueTimeToday => 'Today';
@override
String get queueTimeLast7Days => 'Last 7 days';
@override
String get queueTimeLast30Days => 'Last 30 days';
@override
String get queueEmpty => 'No upload tasks';
@override
String get queueRetryAllFailed => 'Retry all failed';
@override
String queueAttemptCount(int count) {
return '$count attempt(s)';
}
@override
String captureQueued(int count) {
return '$count queued';
}
@override
String get captureFlipCamera => 'Switch camera';
@override
String get captureFlash => 'Flash';
@override
String get uploadsHistory => 'History';
@override
String get uploadsToday => 'Today';
@override
String get uploadsThisDevice => 'This device';
@override
String get uploadsCompleted => 'completed';
@override
String get uploadsUploading => 'uploading';
@override
String get uploadsWaiting => 'waiting';
@override
String get uploadsNeedsAttention => 'Needs attention';
@override
String get uploadsAll => 'All';
@override
String get uploadsActive => 'Active';
@override
String get uploadsConfirming => 'Confirming…';
@override
String get uploadsWaitingUpload => 'Waiting to upload';
@override
String get uploadsWaitingNetwork => 'Waiting for network';
@override
String get uploadsFileUnavailable => 'File unavailable';
@override
String get uploadsSelectAgain => 'Select again';
@override
String get uploadsRemoveRecord => 'Remove record';
@override
String get uploadsRemoveRecordConfirm => 'Remove';
@override
String get uploadsRetryEligible => 'Retry eligible';
@override
String get uploadsRetryEligibleScope =>
'Retries failed uploads that can recover on their own. Files marked unavailable need to be selected again.';
@override
String get uploadsNoNeedsAttention => 'No tasks need attention';
@override
String get uploadsShowingNeedsAttention =>
'Showing tasks that need your attention';
@override
String get uploadsFilters => 'Filters';
@override
String get serverRecords => 'Server records';
@override
String get serverSubtitle => 'All devices · Your account';
@override
String get serverConfirmed => 'Confirmed';
@override
String get serverReady => 'Ready';
@override
String get serverProcessing => 'Processing';
@override
String get serverDeviceUnknown => 'Unknown device';
@override
String get taskStatePreparing => 'Preparing';
@override
String get taskStatePreparationFailed => 'Preparation failed';
@override
String get taskStateQueued => 'Queued';
@override
String get taskStateUploading => 'Uploading';
@override
String get taskStateUploadedConfirming => 'Confirming';
@override
String get taskStateCompleted => 'Completed';
@override
String get taskStateWaitingNetwork => 'Waiting for network';
@override
String get taskStateRetryableFailed => 'Upload failed';
@override
String get taskStateCancelled => 'Cancelled';
@override
String get errorPrepSourceUnreadable =>
'Could not read the selected photo. Please reselect';
@override
String get errorPrepUnsupportedType =>
'Only JPG, PNG and HEIC images are supported';
@override
String get errorPrepTooLarge => 'Photo exceeds the 50MB limit';
@override
String get errorPrepCopyFailed => 'Failed to copy the photo. Please retry';
@override
String get errorUploadSourceMissing =>
'Source file is missing. Please reselect';
@override
String get errorAlbumUploadDisabled => 'Album uploads are disabled';
@override
String get errorUploadSessionConflict =>
'Upload session conflict. Please retry';
@override
String get errorUploadVerifyFailed =>
'Upload verification failed. Will retry';
@override
String get captureTitle => 'Continuous capture';
@override
String get captureCategoryDefault => 'Default category';
@override
String get captureSwitchHint =>
'Switching only affects photos captured afterwards';
@override
String capturePendingBadge(int count) {
return 'Pending $count';
}
@override
String captureFailedBadge(int count) {
return 'Failed $count';
}
@override
String get capturePickFromGallery => 'Pick from gallery';
@override
String get captureShutter => 'Capture';
@override
String captureQueuedBadge(int count) {
return 'Queued $count';
}
@override
String get captureEnqueuedFeedback => 'Added to queue';
@override
String get captureExitTitle => 'Leave shooting?';
@override
String captureExitBody(int count) {
return '$count photo(s) are still uploading. Tasks will continue in the background after you leave.';
}
@override
String get captureKeepShooting => 'Keep shooting';
@override
String get captureExitConfirm => 'Leave';
@override
String get cameraPermissionDenied =>
'Camera unavailable. Allow camera access in system settings';
@override
String get cameraInitFailed => 'Camera failed to initialize';
@override
String get uploadActionCapture => 'Capture and upload';
@override
String get uploadActionPick => 'Pick from gallery';
@override
String get uploadAction => 'Upload';
@override
String uploadEnqueuedCount(int count) {
return 'Added $count photo(s) to the upload queue';
}
@override
String get uploadPickNone => 'No photos selected';
@override
String get albumManagePhotos => 'Manage photos';
@override
String get albumTakeFirstPhoto => 'Take the first photo';
@override
String get albumUploadDisabledHint =>
'Uploads are off for this album. New photos cannot be added right now';
@override
String get albumRecentPhotos => 'Recent uploads';
@override
String get photoFilterAll => 'All';
@override
String get photoFilterFailed => 'Failed';
@override
String get photosScopeOwnHint =>
'Collaborator view: only photos you uploaded are shown';
@override
String get photosEmptyFiltered => 'No photos match this filter';
@override
String get photoHide => 'Hide';
@override
String get photoUnhide => 'Unhide';
@override
String get photoDeleteConfirmTitle => 'Delete this photo?';
@override
String get photoDeleteConfirmBody =>
'This will soft-delete the photo. It can be managed by admins. Cloud storage is not immediately purged.';
@override
String get photoHiddenToast => 'Hidden';
@override
String get photoUnhiddenToast => 'Unhidden';
@override
String get photoDeletedToast => 'Deleted';
@override
String get photoReload => 'Reload';
@override
String get photoPreviewUnavailable => 'Image unavailable';
@override
String get albumsSubtitle => 'Organize and manage event photos';
@override
String get actionPhotos => 'Photos';
@override
String get actionMembers => 'Members';
@override
String get actionCategories => 'Categories';
@override
String get actionShare => 'Share';
@override
String get recentPhotos => 'Recent photos';
@override
String get seeAllPhotos => 'See all';
@override
String get editAlbum => 'Edit album';
@override
String get manageMembers => 'Manage members';
@override
String get shareAlbum => 'Share album';
@override
String get emptyAlbumTitle => 'Ready for your first photo';
@override
String get emptyAlbumSubtitle => 'Photos you take or pick will appear here';
@override
String get processingPhotos => 'Processing...';
@override
String get readonlyMember => 'You can browse photos shared by others';
@override
String get moreActions => 'More actions';
@override
String photosTitle(int count) {
return '$count photos';
}
@override
String photoUploadedBy(String name) {
return 'Uploaded by $name';
}
@override
String photoDimensions(int width, int height) {
return '$width×$height';
}
@override
String get photoStatus => 'Status';
@override
String get photoHideAction => 'Hide photo';
@override
String get photoPublishAction => 'Publish again';
@override
String get shareScanHint => 'Scan to view photos';
@override
String get shareNotPublic => 'This link is not publicly accessible yet';
@override
String get hidePhotoTitle => 'Hide this photo?';
@override
String get hidePhotoBody =>
'Viewers will no longer see this photo. Authorized album managers can publish it again.';
@override
String get deleteAlbum => 'Delete album';
@override
String get deleteAlbumConfirmTitle => 'Delete this album?';
@override
String get deleteAlbumConfirmBody =>
'The album becomes invisible immediately and cannot be restored. Data is retained; recovery requires operations.';
@override
String get albumDeleted => 'Album deleted';
@override
String get bannerPicker => 'Banner';
@override
String get bannerPickerHint =>
'Tap to pick a banner image (shown atop the viewer page)';
@override
String get bannerSelected => 'Banner selected — will upload on save';
@override
String get bannerUploadFailed => 'Banner upload failed';
@override
String get shareCardMode => 'Share to...';
@override
String get sharePosterMode => 'Generate QR poster';
@override
String get posterDownload => 'Download poster image';
@override
String get posterSaved => 'Poster saved to gallery';
@override
String get posterSaveFailed => 'Failed to save poster';
@override
String get close => 'Close';
@override
String get albumUploadDisabled => 'Upload is disabled for this album';
@override
String get networkOfflineBanner =>
'No network. Photos will upload automatically when reconnected.';
}