
- 在AppSettingFeature中新增登出确认和关于我们弹窗的状态和Action。 - 更新AppSettingView以支持登出确认和关于我们弹窗的逻辑。 - 替换多个视图中的NSLocalizedString为LocalizedString,提升本地化一致性。 - 在Localizable.strings中新增相关本地化文本,确保多语言支持。
190 lines
6.3 KiB
Swift
190 lines
6.3 KiB
Swift
import Foundation
|
||
import SwiftUI
|
||
|
||
/// 多语言管理工具类
|
||
/// 提供便捷的本地化字符串获取和语言切换功能
|
||
///
|
||
/// 默认语言策略:
|
||
/// - 应用全局默认语言为英文,不依赖系统语言设置
|
||
/// - 用户可通过语言设置界面手动切换到其他支持的语言
|
||
/// - 用户的语言选择会保存在UserDefaults中,下次启动时保持
|
||
@MainActor
|
||
class LocalizationManager: ObservableObject {
|
||
|
||
// MARK: - 单例
|
||
static let shared = LocalizationManager()
|
||
|
||
// MARK: - 支持的语言
|
||
enum SupportedLanguage: String, CaseIterable {
|
||
case english = "en"
|
||
case chineseSimplified = "zh-Hans"
|
||
|
||
var displayName: String {
|
||
switch self {
|
||
case .english:
|
||
return "English"
|
||
case .chineseSimplified:
|
||
return "简体中文"
|
||
}
|
||
}
|
||
|
||
var localizedDisplayName: String {
|
||
switch self {
|
||
case .english:
|
||
return "English"
|
||
case .chineseSimplified:
|
||
return "简体中文"
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - 当前语言
|
||
@Published var currentLanguage: SupportedLanguage {
|
||
didSet {
|
||
do {
|
||
try KeychainManager.shared.storeString(currentLanguage.rawValue, forKey: "AppLanguage")
|
||
} catch {
|
||
debugErrorSync("❌ 保存语言设置失败: \(error)")
|
||
}
|
||
// 同时更新 UserDefaults 供同步版本使用
|
||
UserDefaults.standard.set(currentLanguage.rawValue, forKey: "AppLanguage")
|
||
// 通知视图更新
|
||
objectWillChange.send()
|
||
}
|
||
}
|
||
|
||
private init() {
|
||
// 从 Keychain 读取保存的语言设置
|
||
let savedLanguage: String?
|
||
do {
|
||
savedLanguage = try KeychainManager.shared.retrieveString(forKey: "AppLanguage")
|
||
} catch {
|
||
debugErrorSync("❌ 读取语言设置失败: \(error)")
|
||
savedLanguage = nil
|
||
}
|
||
|
||
if let language = savedLanguage, let supportedLanguage = SupportedLanguage(rawValue: language) {
|
||
self.currentLanguage = supportedLanguage
|
||
} else {
|
||
// 如果没有保存过语言设置,使用系统首选语言
|
||
self.currentLanguage = Self.getSystemPreferredLanguage()
|
||
}
|
||
|
||
// 确保 UserDefaults 也同步了当前语言设置
|
||
UserDefaults.standard.set(self.currentLanguage.rawValue, forKey: "AppLanguage")
|
||
}
|
||
|
||
// MARK: - 本地化方法
|
||
|
||
/// 获取本地化字符串
|
||
/// - Parameters:
|
||
/// - key: 本地化 key
|
||
/// - arguments: 格式化参数
|
||
/// - Returns: 本地化后的字符串
|
||
func localizedString(_ key: String, arguments: CVarArg...) -> String {
|
||
let format = getLocalizedString(for: key)
|
||
if arguments.isEmpty {
|
||
return format
|
||
} else {
|
||
return String(format: format, arguments: arguments)
|
||
}
|
||
}
|
||
|
||
/// 获取本地化字符串(私有方法)
|
||
private func getLocalizedString(for key: String) -> String {
|
||
guard let path = Bundle.main.path(forResource: currentLanguage.rawValue, ofType: "lproj"),
|
||
let bundle = Bundle(path: path) else {
|
||
// 如果找不到对应语言包,返回 key 本身
|
||
return NSLocalizedString(key, comment: "")
|
||
}
|
||
|
||
return NSLocalizedString(key, bundle: bundle, comment: "")
|
||
}
|
||
|
||
// MARK: - 语言切换
|
||
|
||
/// 切换到指定语言
|
||
/// - Parameter language: 目标语言
|
||
func switchLanguage(to language: SupportedLanguage) {
|
||
currentLanguage = language
|
||
}
|
||
|
||
/// 获取系统首选语言
|
||
/// 注意:应用全局默认语言已设置为英文,用户可通过设置手动切换语言
|
||
private static func getSystemPreferredLanguage() -> SupportedLanguage {
|
||
// 全局默认语言设置为英文
|
||
// 用户仍可通过语言设置界面切换到其他支持的语言
|
||
return .english
|
||
}
|
||
}
|
||
|
||
// MARK: - SwiftUI Extensions
|
||
extension View {
|
||
/// 应用本地化字符串
|
||
/// - Parameter key: 本地化 key
|
||
/// - Returns: 带有本地化文本的视图
|
||
@MainActor
|
||
func localized(_ key: String) -> some View {
|
||
self.modifier(LocalizedTextModifier(key: key))
|
||
}
|
||
}
|
||
|
||
// MARK: - 便捷方法
|
||
extension String {
|
||
/// 获取本地化字符串
|
||
@MainActor
|
||
var localized: String {
|
||
return LocalizationManager.shared.localizedString(self)
|
||
}
|
||
/// 获取本地化字符串(带参数)
|
||
@MainActor
|
||
func localized(arguments: CVarArg...) -> String {
|
||
return LocalizationManager.shared.localizedString(self, arguments: arguments)
|
||
}
|
||
}
|
||
|
||
// MARK: - 全局本地化方法
|
||
/// 全局本地化字符串获取方法
|
||
/// 使用 LocalizationManager 而不是系统语言设置
|
||
/// - Parameters:
|
||
/// - key: 本地化 key
|
||
/// - comment: 注释(保持与 NSLocalizedString 兼容)
|
||
/// - Returns: 本地化后的字符串
|
||
@MainActor
|
||
func LocalizedString(_ key: String, comment: String = "") -> String {
|
||
return LocalizationManager.shared.localizedString(key)
|
||
}
|
||
|
||
/// 同步版本的本地化字符串获取方法
|
||
/// 用于 TCA reducer 等同步上下文
|
||
/// - Parameters:
|
||
/// - key: 本地化 key
|
||
/// - comment: 注释(保持与 NSLocalizedString 兼容)
|
||
/// - Returns: 本地化后的字符串
|
||
func LocalizedStringSync(_ key: String, comment: String = "") -> String {
|
||
// 直接从 UserDefaults 读取当前语言设置(避免 @MainActor 隔离问题)
|
||
let currentLanguage = UserDefaults.standard.string(forKey: "AppLanguage") ?? "en"
|
||
|
||
// 根据语言设置获取本地化字符串
|
||
guard let path = Bundle.main.path(forResource: currentLanguage, ofType: "lproj"),
|
||
let bundle = Bundle(path: path) else {
|
||
// 如果找不到对应语言包,返回 key 本身
|
||
return NSLocalizedString(key, comment: comment)
|
||
}
|
||
|
||
return NSLocalizedString(key, bundle: bundle, comment: comment)
|
||
}
|
||
|
||
// MARK: - LocalizedTextModifier
|
||
/// 本地化文本修饰符
|
||
struct LocalizedTextModifier: ViewModifier {
|
||
let key: String
|
||
|
||
func body(content: Content) -> some View {
|
||
content
|
||
.onAppear {
|
||
// 这里可以添加动态更新逻辑
|
||
}
|
||
}
|
||
}
|