From 6e60bea509431b7b3247cfe38b192b01850a12f7 Mon Sep 17 00:00:00 2001 From: empty Date: Sat, 3 Jan 2026 22:23:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20SettingsView=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 所有文本改用 String(localized:) - 添加应用内语言切换 Picker - 支持简体中文、繁体中文、英文 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../to-live-photo/Views/SettingsView.swift | 82 +++++++++++-------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/to-live-photo/to-live-photo/Views/SettingsView.swift b/to-live-photo/to-live-photo/Views/SettingsView.swift index 8693c9c..f9c367d 100644 --- a/to-live-photo/to-live-photo/Views/SettingsView.swift +++ b/to-live-photo/to-live-photo/Views/SettingsView.swift @@ -10,7 +10,7 @@ import Photos struct SettingsView: View { @State private var photoLibraryStatus: PHAuthorizationStatus = .notDetermined - @State private var cacheSize: String = "计算中..." + @State private var cacheSize: String = String(localized: "common.calculating") @State private var showingClearCacheAlert = false @State private var showingClearRecentWorksAlert = false @State private var feedbackPackageURL: URL? @@ -21,7 +21,7 @@ struct SettingsView: View { // 权限状态 Section { HStack { - Label("相册权限", systemImage: "photo.on.rectangle") + Label(String(localized: "settings.photoPermission"), systemImage: "photo.on.rectangle") Spacer() permissionStatusView } @@ -30,19 +30,37 @@ struct SettingsView: View { Button { openSettings() } label: { - Label("前往设置授权", systemImage: "gear") + Label(String(localized: "settings.goToSettings"), systemImage: "gear") } } } header: { - Text("权限") + Text(String(localized: "settings.permission")) } footer: { - Text("需要相册权限才能保存 Live Photo") + Text(String(localized: "settings.permissionFooter")) + } + + // 语言设置 + Section { + Picker(selection: Binding( + get: { LanguageManager.shared.current }, + set: { LanguageManager.shared.current = $0 } + )) { + ForEach(LanguageManager.Language.allCases) { language in + Text(language.displayName).tag(language) + } + } label: { + Label(String(localized: "settings.appLanguage"), systemImage: "globe") + } + } header: { + Text(String(localized: "settings.language")) + } footer: { + Text(String(localized: "settings.languageChangeHint")) } // 存储 Section { HStack { - Label("缓存大小", systemImage: "internaldrive") + Label(String(localized: "settings.cacheSize"), systemImage: "internaldrive") Spacer() Text(cacheSize) .foregroundStyle(.secondary) @@ -51,18 +69,18 @@ struct SettingsView: View { Button(role: .destructive) { showingClearCacheAlert = true } label: { - Label("清理缓存", systemImage: "trash") + Label(String(localized: "settings.clearCache"), systemImage: "trash") } Button(role: .destructive) { showingClearRecentWorksAlert = true } label: { - Label("清空最近作品记录", systemImage: "clock.arrow.circlepath") + Label(String(localized: "settings.clearRecentWorks"), systemImage: "clock.arrow.circlepath") } } header: { - Text("存储") + Text(String(localized: "settings.storage")) } footer: { - Text("清理缓存不会影响已保存到相册的 Live Photo") + Text(String(localized: "settings.storageFooter")) } // 反馈 @@ -70,27 +88,27 @@ struct SettingsView: View { Button { exportFeedbackPackage() } label: { - Label("导出诊断报告", systemImage: "doc.text") + Label(String(localized: "settings.exportDiagnostics"), systemImage: "doc.text") } Link(destination: URL(string: "mailto:support@let5see.xyz")!) { - Label("反馈问题", systemImage: "envelope") + Label(String(localized: "settings.contactUs"), systemImage: "envelope") } // TODO: App Store 上架后替换为实际的 App ID Link(destination: URL(string: "https://apps.apple.com/app/id000000000")!) { - Label("App Store 评分", systemImage: "star") + Label(String(localized: "settings.rateApp"), systemImage: "star") } } header: { - Text("反馈") + Text(String(localized: "settings.feedback")) } footer: { - Text("诊断报告仅包含日志和参数,不含媒体内容") + Text(String(localized: "settings.feedbackFooter")) } // 关于 Section { HStack { - Label("版本", systemImage: "info.circle") + Label(String(localized: "settings.version"), systemImage: "info.circle") Spacer() Text(appVersion) .foregroundStyle(.secondary) @@ -99,39 +117,39 @@ struct SettingsView: View { NavigationLink { PrivacyPolicyView() } label: { - Label("隐私政策", systemImage: "hand.raised") + Label(String(localized: "settings.privacyPolicy"), systemImage: "hand.raised") } NavigationLink { TermsOfServiceView() } label: { - Label("使用条款", systemImage: "doc.text") + Label(String(localized: "settings.termsOfService"), systemImage: "doc.text") } } header: { - Text("关于") + Text(String(localized: "settings.about")) } } - .navigationTitle("设置") + .navigationTitle(String(localized: "settings.title")) .navigationBarTitleDisplayMode(.inline) .onAppear { checkPermissionStatus() calculateCacheSize() } - .alert("清理缓存", isPresented: $showingClearCacheAlert) { - Button("取消", role: .cancel) {} - Button("清理", role: .destructive) { + .alert(String(localized: "settings.clearCache"), isPresented: $showingClearCacheAlert) { + Button(String(localized: "common.cancel"), role: .cancel) {} + Button(String(localized: "settings.clear"), role: .destructive) { clearCache() } } message: { - Text("确定要清理所有缓存文件吗?") + Text(String(localized: "settings.clearCacheConfirm")) } - .alert("清空记录", isPresented: $showingClearRecentWorksAlert) { - Button("取消", role: .cancel) {} - Button("清空", role: .destructive) { + .alert(String(localized: "settings.clearRecordsTitle"), isPresented: $showingClearRecentWorksAlert) { + Button(String(localized: "common.cancel"), role: .cancel) {} + Button(String(localized: "settings.clear"), role: .destructive) { clearRecentWorks() } } message: { - Text("确定要清空最近作品记录吗?这不会删除相册中的 Live Photo。") + Text(String(localized: "settings.clearRecordsConfirm")) } .sheet(isPresented: $showingShareSheet) { if let url = feedbackPackageURL { @@ -144,19 +162,19 @@ struct SettingsView: View { private var permissionStatusView: some View { switch photoLibraryStatus { case .authorized: - Label("已授权", systemImage: "checkmark.circle.fill") + Label(String(localized: "settings.authorized"), systemImage: "checkmark.circle.fill") .foregroundStyle(.green) .labelStyle(.iconOnly) case .limited: - Label("部分授权", systemImage: "exclamationmark.circle.fill") + Label(String(localized: "settings.limited"), systemImage: "exclamationmark.circle.fill") .foregroundStyle(.orange) .labelStyle(.iconOnly) case .denied, .restricted: - Label("未授权", systemImage: "xmark.circle.fill") + Label(String(localized: "settings.denied"), systemImage: "xmark.circle.fill") .foregroundStyle(.red) .labelStyle(.iconOnly) case .notDetermined: - Label("未确定", systemImage: "questionmark.circle.fill") + Label(String(localized: "settings.notDetermined"), systemImage: "questionmark.circle.fill") .foregroundStyle(.secondary) .labelStyle(.iconOnly) @unknown default: