如何使用Swift基于后端返回值设置iOS混合应用i18n默认通知语言?
iOS 自定义通知语言(基于后端返回语言代码)
核心思路
iOS 默认跟随系统语言加载通知本地化内容,但要实现基于后端返回语言代码的自定义通知语言,核心是手动控制通知内容的本地化逻辑——不再依赖系统自动匹配,而是根据后端返回的偏好语言,从对应本地化文件中读取字符串后构建通知。
具体实现方案
1. 存储后端返回的偏好语言
首先将后端返回的语言代码(如en/fr)持久化存储,推荐用UserDefaults(如果涉及通知扩展,需用App Groups共享存储):
// 收到后端返回的语言代码后保存 UserDefaults.standard.set("fr", forKey: "preferredNotificationLanguage") UserDefaults.standard.synchronize()
2. 手动加载指定语言的本地化字符串
实现工具方法,根据传入的语言代码读取对应.lproj文件夹中的字符串文件:
func getLocalizedString(forKey key: String, language: String) -> String { // 找到对应语言的lproj文件夹路径 guard let lprojPath = Bundle.main.path(forResource: language, ofType: "lproj"), let languageBundle = Bundle(path: lprojPath) else { // fallback到系统默认语言 return NSLocalizedString(key, comment: "") } // 从指定bundle中读取字符串 return NSLocalizedString(key, bundle: languageBundle, comment: "") }
确保App包内已正确放置本地化文件:en.lproj/Localizable.strings、fr.lproj/Localizable.strings,且包含通知所需的字符串键(如notification_title、notification_body)。
场景一:本地通知的处理
构建本地通知时,直接用上述工具方法获取对应语言的内容:
// 获取存储的偏好语言,默认用en let preferredLang = UserDefaults.standard.string(forKey: "preferredNotificationLanguage") ?? "en" // 读取对应语言的通知内容 let notificationTitle = getLocalizedString(forKey: "notification_title", language: preferredLang) let notificationBody = getLocalizedString(forKey: "notification_body", language: preferredLang) // 构建通知 let content = UNMutableNotificationContent() content.title = notificationTitle content.body = notificationBody content.sound = .default // 设置通知触发条件并添加 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) let request = UNNotificationRequest(identifier: "custom_lang_notification", content: content, trigger: trigger) UNUserNotificationCenter.current().add(request)
场景二:远程推送的处理
远程推送分两种处理方式,根据业务需求选择:
方式A:后端直接推送对应语言的内容(推荐)
让后端维护用户的语言偏好,推送时直接填充对应语言的title和body,App无需额外处理,最简单高效。
方式B:App本地替换推送内容
如果后端仅推送通用的字符串key,需要App在收到推送后替换为对应语言的内容。注意:App在后台/未启动时,需用Notification Service Extension处理。
- 主App内前台处理:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo guard let notificationKey = userInfo["notification_key"] as? String else { completionHandler([.banner, .sound]) return } let preferredLang = UserDefaults.standard.string(forKey: "preferredNotificationLanguage") ?? "en" let title = getLocalizedString(forKey: "\(notificationKey)_title", language: preferredLang) let body = getLocalizedString(forKey: "\(notificationKey)_body", language: preferredLang) // 修改通知内容 let modifiedContent = notification.request.content.mutableCopy() as! UNMutableNotificationContent modifiedContent.title = title modifiedContent.body = body completionHandler([.banner, .sound]) }
- Notification Service Extension处理(后台/未启动场景):
- 创建Notification Service Extension目标
- 开启App Groups,将偏好语言存储到共享的
UserDefaults中(主App和Extension需用同一App Group) - 在Extension中修改推送内容:
class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) guard let content = bestAttemptContent, let notificationKey = content.userInfo["notification_key"] as? String else { contentHandler(content) return } // 从共享App Group读取偏好语言 let sharedDefaults = UserDefaults(suiteName: "your.app.group.id") let preferredLang = sharedDefaults?.string(forKey: "preferredNotificationLanguage") ?? "en" let title = getLocalizedString(forKey: "\(notificationKey)_title", language: preferredLang) let body = getLocalizedString(forKey: "\(notificationKey)_body", language: preferredLang) content.title = title content.body = body contentHandler(content) } func getLocalizedString(forKey key: String, language: String) -> String { guard let lprojPath = Bundle.main.path(forResource: language, ofType: "lproj"), let languageBundle = Bundle(path: lprojPath) else { return NSLocalizedString(key, comment: "") } return NSLocalizedString(key, bundle: languageBundle, comment: "") } override func serviceExtensionTimeWillExpire() { if let handler = contentHandler, let content = bestAttemptContent { handler(content) } } }
注意事项
- 语言代码要和
.lproj文件夹名匹配:如果后端返回fr-FR,需处理为fr才能正确读取fr.lproj - Notification Service Extension需单独配置本地化文件,或者确保主App的本地化资源能被Extension访问
- 若使用App Groups,需在主App和Extension的Capabilities中开启,并填写相同的Group ID
内容的提问来源于stack exchange,提问作者baohoang
相关产品推荐
相关产品推荐

