Files
photo-live/apps/mobile/lib/l10n/app_localizations_en.dart
T
浅念 955f9b13c1 feat(mobile): upload queue ui and continuous capture page
Task 9 (P3 plan): queue tab replaces the stub, continuous capture page
enqueues per shot, album detail gains an upload FAB, and the upload
engine lifecycle is now bound to the login session.

- Engine scope: session account drives UploadEngine start/stop; wired
  from app boot, login success, logout, and 401 eviction. Tasks stay in
  the store across logout (accountId hard isolation).
- Queue tab: album x state x time filter bar, task rows with thumbnail,
  state chip, localized error copy, attempt count, per-row progress via
  a broadcast progress hub, state-dependent actions (re-pick retry,
  retryNow, cancel, delete), batch retry bar, 200ms-debounced live
  refresh from drift table updates.
- Capture page: camera preview via injected CaptureSource, one enqueue
  per shutter press, persistent album/category/badges overlay with a
  switch-only-affects-new-shots hint, gallery multi-pick, exit confirm
  while uploads are pending, permission-denied and init-failure views.
- POST_NOTIFICATIONS runtime permission via a small MethodChannel
  (photolive/permissions) + PermissionPlugin.kt: single runtime
  permission need, avoids permission_handler dependency; requested once
  on first enqueue, silent degradation when denied or unavailable.
- Album detail FAB: capture-and-upload / pick-from-gallery sheet.
- l10n: ~50 new keys in zh/en arbs; tests: +45 (filter matrix, engine
  scope lifecycle, permission gate, queue tab, capture page, FAB entry);
  existing page tests updated to inject session/task-store fakes.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 04:47:31 +08:00

541 lines
12 KiB
Dart

// 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 => 'Upload queue';
@override
String get settings => 'Settings';
@override
String get language => 'Language';
@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 homeTabAlbums => 'Albums';
@override
String get homeTabQueue => 'Queue';
@override
String get homeTabSettings => 'Settings';
@override
String get loginHint => 'Sign in with your staff account';
@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 albumEdit => 'Edit album';
@override
String get albumTitle => 'Title';
@override
String get albumDescription => 'Description';
@override
String get albumVenue => 'Venue';
@override
String get albumAddress => 'Address';
@override
String get albumDefaultLocale => 'Default locale';
@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 switchUpload => 'Allow uploads';
@override
String get switchPublic => 'Publicly visible';
@override
String get switchDownload => 'Allow downloads';
@override
String get switchOriginalDownload => 'Allow original downloads';
@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 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 albumMembers => 'Members';
@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 deleteConfirmCategory =>
'Delete this category? Its photos will become uncategorized.';
@override
String get categoryEmpty => 'No categories yet. Tap + to add one';
@override
String get categoryAdd => 'Add category';
@override
String get categoryEdit => 'Edit category';
@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 albumMembersEmpty => 'No members yet';
@override
String get inviteSearchHint =>
'Search by account prefix to invite (at least 2 characters)';
@override
String get inviteNoResults => 'No matching users';
@override
String get invite => 'Invite';
@override
String get memberInvited => 'Invited';
@override
String get removeMember => 'Remove member';
@override
String get removeMemberConfirm => 'Remove this member?';
@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 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 => 'View server upload history';
@override
String get serverHistoryTitle => 'Server upload history';
@override
String get serverHistoryBanner =>
'Server-side history (cross-device) — for this device\'s pending uploads see the Queue 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 queueStatePreparing => 'Preparing';
@override
String get queueStateQueued => 'Queued';
@override
String get queueStateUploading => 'Uploading';
@override
String get queueStateWaitingNetwork => 'Waiting for network';
@override
String get queueStateFailed => 'Failed';
@override
String get queueStateCompleted => 'Done';
@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 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 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';
}