Swift:修改App语言后获取iOS系统语言及保留fallback问题
1. 修复修改AppleLanguages后丢失Fallback语言的问题
你当前的setAppleLanguageTo方法只把单一语言存入AppleLanguages,直接覆盖了系统原来的优先级数组,自然就丢失了fallback逻辑。要保留fallback,你需要构建包含用户选择语言+系统原有支持语言的优先级数组,而非只存单一语言。
举个例子,如果用户选择希伯来语(he),可以这样实现:
func setAppleLanguageTo(lang: String) { // 获取系统原生的首选语言数组(不受应用自定义设置影响) let systemLanguages = UserDefaults.standard.persistentDomain(forName: UserDefaults.globalDomain)?["AppleLanguages"] as? [String] ?? [] // 筛选出你的应用支持的语言(en、he、fr) let supportedLanguages = ["en", "he", "fr"] let filteredSystemLanguages = systemLanguages.filter { code in supportedLanguages.contains(code.components(separatedBy: "-").first!) } // 把用户选择的语言放在首位,后续追加去重后的系统支持语言 var newLanguages = [lang] filteredSystemLanguages.forEach { code in if !newLanguages.contains(code) { newLanguages.append(code) } } UserDefaults.standard.set(newLanguages, forKey: "AppleLanguages") UserDefaults.standard.synchronize() // 可选,确保设置立即生效 }
这样设置后,Locale.preferredLanguages会返回类似["he-IL", "en-IL", "fr-IL"]的数组,既保证用户选择的语言优先,又保留了系统级的fallback顺序。
2. 获取设备原生系统语言(不受应用自定义AppleLanguages影响)
应用内修改的AppleLanguages是应用级别的覆盖,要获取系统真实的语言设置,需要从全局UserDefaults域读取,而非应用自身的UserDefaults:
func getSystemPreferredLanguages() -> [String] { return UserDefaults.standard.persistentDomain(forName: UserDefaults.globalDomain)?["AppleLanguages"] as? [String] ?? [] } // 获取系统首选的第一个语言 func getSystemPrimaryLanguage() -> String { return getSystemPreferredLanguages().first ?? "" }
这个方法拿到的就是系统设置里的原生语言数组,完全不受你应用内修改的影响,和Facebook这类应用的实现逻辑一致。
3. 关于Scheme中Application Language的影响
Scheme里设置的Application Language,本质是Xcode在应用启动时,向应用的UserDefaults注入了AppleLanguages键值对,和你自己用代码设置的效果完全相同——都会覆盖系统的语言优先级。所以如果你在Scheme里选了某个语言,应用启动后Locale.preferredLanguages就会变成Scheme设置的值,这是正常的调试行为,发布版不会受此影响。
另外补充个小技巧:修改AppleLanguages后,不需要强制重启应用,通过重新初始化根视图控制器就能让界面语言立即生效,能提升用户体验。
内容的提问来源于stack exchange,提问作者Asaf Baibekov

