SwiftUI本地化问题:表单错误信息无法切换为西班牙语
问题描述
在SwiftUI中实现本地化功能,已创建包含多条目的Localizable文件,并定义了实现LocalizedError协议的NewDriverLicenseFormError枚举:
enum NewDriverLicenseFormError: LocalizedError, Identifiable { var id: UUID { UUID() } case firstName var errorDescription: String? { switch self { case .firstName: return NSLocalizedString("First name cannot be empty.", comment: "") } } }
将预览区域设置切换为西班牙语:
#Preview("NewDriverLicenseScreen Spanish") { NewDriverLicenseScreen() .environment(\.locale, Locale(identifier: "es")) }
运行NewDriverLicenseScreen视图时,“First name”已显示为西班牙语,但ValidationSummaryView中展示的错误信息未切换为西班牙语。相关视图代码如下:
struct NewDriverLicenseScreen: View { @State private var newDriverLicenseForm = NewDriverLicenseForm() var body: some View { Form { TextField("First name", text: $newDriverLicenseForm.firstName) Button("Submit") { if newDriverLicenseForm.validate() { } } ValidationSummaryView(errorMessages: newDriverLicenseForm.errorMessages) } } } struct ValidationSummaryView: View { let errorMessages: [NewDriverLicenseFormError] var body: some View { ForEach(errorMessages) { errorMessage in Text(errorMessage.localizedDescription) } } }
请问该如何解决这一问题?
解决方案
问题核心是NSLocalizedString默认使用系统区域设置,不会读取你通过.environment(\.locale)注入的自定义Locale,而TextField能正常切换是因为它接收LocalizedStringKey参数,会自动响应环境Locale。以下是两种可行的修复方案:
方案1:改用LocalizedStringKey让SwiftUI自动处理本地化
修改错误枚举,返回本地化键而非直接解析字符串:
enum NewDriverLicenseFormError: Identifiable { var id: UUID { UUID() } case firstName var localizedKey: LocalizedStringKey { switch self { case .firstName: return "First name cannot be empty." } } }
然后更新ValidationSummaryView,直接用Text加载本地化键:
struct ValidationSummaryView: View { let errorMessages: [NewDriverLicenseFormError] var body: some View { ForEach(errorMessages) { errorMessage in Text(errorMessage.localizedKey) } } }
方案2:保留LocalizedError协议,手动关联环境Locale
如果需要保留LocalizedError的实现,可在视图中手动传入环境Locale解析字符串:
// 修改枚举,拆分键和默认解析逻辑 enum NewDriverLicenseFormError: LocalizedError, Identifiable { var id: UUID { UUID() } case firstName var errorKey: String { switch self { case .firstName: return "First name cannot be empty." } } // 保留默认实现,供非SwiftUI场景使用 var errorDescription: String? { NSLocalizedString(errorKey, comment: "") } } // 更新ValidationSummaryView,读取环境Locale struct ValidationSummaryView: View { let errorMessages: [NewDriverLicenseFormError] @Environment(\.locale) private var locale var body: some View { ForEach(errorMessages) { errorMessage in Text(NSLocalizedString( errorMessage.errorKey, tableName: nil, bundle: .main, value: "", comment: "", locale: locale )) } } }
内容的提问来源于stack exchange,提问作者john doe
相关产品推荐
相关产品推荐

