You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 20:20:26