/// 任务状态/上传域错误码 → 本地化文案(P3 计划 Task 9)。 /// /// 队列/连拍页专用扩展:契约错误码复用 core/error_l10n 的映射,此处 /// 补齐上传域客户端伪码(准备阶段 [PrepErrorCodes]、引擎源缺失伪码) /// 与队列高频契约码(ALBUM_UPLOAD_DISABLED 等)。 library; import '../../core/error_codes.dart'; import '../../core/error_l10n.dart'; import '../../l10n/app_localizations.dart'; import '../albums/models.dart'; import 'preparer.dart'; import 'task_state.dart'; import 'upload_engine.dart'; extension AppLocalizationsUploadX on AppLocalizations { /// 任务状态标签(chip/文案)。 String labelForTaskState(UploadTaskState state) => switch (state) { UploadTaskState.preparing => taskStatePreparing, UploadTaskState.preparationFailed => taskStatePreparationFailed, UploadTaskState.queued => taskStateQueued, UploadTaskState.uploading => taskStateUploading, UploadTaskState.uploadedConfirming => taskStateUploadedConfirming, UploadTaskState.completed => taskStateCompleted, UploadTaskState.waitingNetwork => taskStateWaitingNetwork, UploadTaskState.retryableFailed => taskStateRetryableFailed, UploadTaskState.cancelled => taskStateCancelled, }; /// 任务 lastError → 展示文案(上传域伪码 + 契约码;未映射回退 /// error_l10n 的通用解析)。 String messageForTaskError(String code) { switch (code) { case PrepErrorCodes.sourceUnreadable: return errorPrepSourceUnreadable; case PrepErrorCodes.unsupportedType: return errorPrepUnsupportedType; case PrepErrorCodes.tooLarge: return errorPrepTooLarge; case PrepErrorCodes.copyFailed: return errorPrepCopyFailed; case UploadEngine.sourceMissingCode: return errorUploadSourceMissing; case ErrorCodes.albumUploadDisabled: return errorAlbumUploadDisabled; case ErrorCodes.uploadSessionConflict: return errorUploadSessionConflict; case ErrorCodes.uploadVerifyFailed: return errorUploadVerifyFailed; default: return messageForErrorCode(code); } } } /// 相册展示标题解析:当前 locale → 相册默认语言 → 首条 → 相册 ID。 /// /// locale 匹配按语言前缀(App locale `zh`/`en` vs 契约 `zh-CN`/`en`)。 String albumDisplayTitle(AlbumSummary album, String localeName) { final lang = localeName.split('-').first.toLowerCase(); AlbumTranslation? match; for (final t in album.translations) { if (t.locale.toLowerCase() == localeName.toLowerCase() || t.locale.toLowerCase().split('-').first == lang) { match = t; break; } } if (match != null) return match.title; for (final t in album.translations) { if (t.locale == album.defaultLocale) return t.title; } if (album.translations.isNotEmpty) return album.translations.first.title; return album.id; }