You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何切换App语言包后即时更新所有界面文本?

嘿,这个问题我之前帮朋友解决过,完全懂你不想重复造轮子的心情!下面给你一套不用硬编码、不用挨个设置IBOutlet的解决方案,核心是靠全局管理器+通知机制让所有文本自动响应语言变化:

实现App语言即时切换(无重复操作版)

1. 先搞个全局本地化管理器

写个单例类,负责管当前语言、切换逻辑,还能发送语言变更通知,让所有控件知道要更新了:

import Foundation

class LocalizationManager {
    static let shared = LocalizationManager()
    
    // 当前语言,自动保存到UserDefaults,下次启动也能记住
    var currentLanguage: String {
        didSet {
            UserDefaults.standard.set(currentLanguage, forKey: "AppSavedLanguage")
            // 发通知告诉所有控件:语言变了!
            NotificationCenter.default.post(name: NSNotification.Name("AppLanguageChanged"), object: nil)
        }
    }
    
    private init() {
        // 初始化时优先取用户之前选的语言,没有就用系统默认
        currentLanguage = UserDefaults.standard.string(forKey: "AppSavedLanguage") 
            ?? Locale.preferredLanguages.first ?? "en"
    }
    
    // 统一获取本地化字符串的方法
    func getLocalizedString(for key: String) -> String {
        guard let bundlePath = Bundle.main.path(forResource: currentLanguage, ofType: "lproj") else {
            return NSLocalizedString(key, comment: "")
        }
        let targetBundle = Bundle(path: bundlePath)!
        return NSLocalizedString(key, bundle: targetBundle, comment: "")
    }
}

2. 给UI控件加自动更新扩展

为了避免每个控件都写重复代码,给常用的UI控件(Label、Button这些)写扩展,让它们能自动监听语言变更通知,自己更新文本:

UILabel扩展

import UIKit

extension UILabel {
    // 用Runtime关联本地化key,不用额外写IBOutlet
    private struct AssociatedKeys {
        static var LocalizationKey = "LabelLocalizationKey"
    }
    
    var localizationKey: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.LocalizationKey) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.LocalizationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            // 设置key时立即更新一次文本
            refreshLocalizedText()
            // 监听语言变更通知
            NotificationCenter.default.addObserver(self, selector: #selector(refreshLocalizedText), name: NSNotification.Name("AppLanguageChanged"), object: nil)
        }
    }
    
    @objc private func refreshLocalizedText() {
        guard let key = localizationKey else { return }
        text = LocalizationManager.shared.getLocalizedString(for: key)
    }
    
    // 销毁时移除监听,防止内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

UIButton扩展(逻辑类似,适配按钮标题)

extension UIButton {
    private struct AssociatedKeys {
        static var LocalizationKey = "ButtonLocalizationKey"
    }
    
    var localizationKey: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.LocalizationKey) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.LocalizationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            refreshLocalizedTitle()
            NotificationCenter.default.addObserver(self, selector: #selector(refreshLocalizedTitle), name: NSNotification.Name("AppLanguageChanged"), object: nil)
        }
    }
    
    @objc private func refreshLocalizedTitle() {
        guard let key = localizationKey else { return }
        setTitle(LocalizationManager.shared.getLocalizedString(for: key), for: .normal)
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

你可以照着这个逻辑,给UITextField(适配placeholder)、UINavigationItem(适配title)等其他需要本地化的控件写扩展。

3. 控件关联本地化Key(两种方式选一种)

方式1:Storyboard/XIB可视化配置

不用写代码,直接在界面编辑器里设置:

  1. 选中需要本地化的控件,打开「Identity Inspector」
  2. 找到「User Defined Runtime Attributes」,点击+号
  3. 填写:
    • Key Path:localizationKey
    • Type:String
    • Value:你的本地化字符串Key(比如"welcome_message")

方式2:代码里设置

如果是代码创建的控件,直接一行代码搞定:

let welcomeLabel = UILabel()
welcomeLabel.localizationKey = "welcome_message"

4. 语言切换按钮的逻辑

在你的切换按钮点击事件里,只需要改管理器的语言就行,剩下的全自动化:

// 切换到阿拉伯文
@IBAction func switchToArabic(_ sender: UIButton) {
    LocalizationManager.shared.currentLanguage = "ar"
}

// 切换到英文
@IBAction func switchToEnglish(_ sender: UIButton) {
    LocalizationManager.shared.currentLanguage = "en"
}

最后要注意的小细节

  • 确保en.lprojar.lproj里的Localizable.strings文件包含对应的Key,比如:
    // en.lproj/Localizable.strings
    "welcome_message" = "Welcome to our App!";
    
    // ar.lproj/Localizable.strings
    "welcome_message" = "أهلاً بك في تطبيقنا!";
    
  • 自定义View或者复杂控件,参照上面的扩展逻辑加个localizationKey属性,就能自动响应语言变化了。

这样一来,你完全不用给每个文本写重复的text.localized(),也不用挨个拖IBOutlet,一次配置好之后,新增控件只要设置个Key就搞定!

内容的提问来源于stack exchange,提问作者Alireza aj

火山引擎 最新活动