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

如何使用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处理(后台/未启动场景):
    1. 创建Notification Service Extension目标
    2. 开启App Groups,将偏好语言存储到共享的UserDefaults中(主App和Extension需用同一App Group)
    3. 在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 06:55:36