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

如何在Swift 3中基于Base国际化实现iOS App运行时即时切换语言

Runtime Language Switching in Swift 3 (iOS, Base Localization)

Hey there, I’ve tackled this exact runtime language switching issue before—getting it to work without restarting the app using Base localization. Here’s a solid, step-by-step solution that works seamlessly for both iPhone and iPad:

Core Idea

Apple’s default Bundle doesn’t refresh localization resources while the app is running, so we’ll build a custom Bundle subclass to load strings based on the user’s selected language, plus a notification system to trigger UI updates across the entire app.


1. Create a Custom Localization Bundle

This subclass overrides how the app fetches localized strings, pulling from the user’s chosen language bundle instead of the system default:

import UIKit

class LocalizationBundle: Bundle {
    override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String {
        // Fetch the saved language code from UserDefaults
        guard let langCode = UserDefaults.standard.string(forKey: "AppLanguage"),
              let langBundlePath = Bundle.main.path(forResource: langCode, ofType: "lproj"),
              let langBundle = Bundle(path: langBundlePath) else {
            // Fallback to system default if no custom language is set
            return super.localizedString(forKey: key, value: value, table: tableName)
        }
        return langBundle.localizedString(forKey: key, value: value, table: tableName)
    }
}

Then, replace the main bundle’s class in your AppDelegate so the app uses our custom bundle everywhere:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Set default language if none is saved (use system language or fallback to English)
    if UserDefaults.standard.string(forKey: "AppLanguage") == nil {
        let systemDefaultLang = Locale.preferredLanguages.first ?? "en"
        UserDefaults.standard.set(systemDefaultLang, forKey: "AppLanguage")
    }
    
    // Swap the main bundle's class to our custom LocalizationBundle
    object_setClass(Bundle.main, LocalizationBundle.self)
    
    return true
}

2. Add Language Switching Logic

Create a function to handle user language selection—this saves the choice to UserDefaults and triggers a full UI refresh:

func switchAppLanguage(to langCode: String) {
    // Save the selected language code (e.g., "en", "zh-Hans")
    UserDefaults.standard.set(langCode, forKey: "AppLanguage")
    UserDefaults.standard.synchronize()
    
    // Notify all screens to update their UI
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "AppLanguageChanged"), object: nil)
    
    // Refresh the root view controller to apply changes to storyboard-based UI
    if let window = UIApplication.shared.keyWindow {
        window.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
        window.makeKeyAndVisible()
    }
}

Call this from your settings screen when the user selects a language:

// Example: Switch to English
switchAppLanguage(to: "en")
// Example: Switch to Simplified Chinese
switchAppLanguage(to: "zh-Hans")

3. Update UI Elements on Language Change

All view controllers and custom UI components need to listen for the language change notification and refresh their localized text:

For View Controllers:

import UIKit

class HomeViewController: UIViewController {
    @IBOutlet weak var submitButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Set initial localized text
        updateLocalizedUI()
        
        // Listen for language change notifications
        NotificationCenter.default.addObserver(self, selector: #selector(updateLocalizedUI), name: NSNotification.Name(rawValue: "AppLanguageChanged"), object: nil)
    }
    
    @objc private func updateLocalizedUI() {
        self.title = NSLocalizedString("Home_Screen_Title", comment: "Home screen title")
        submitButton.setTitle(NSLocalizedString("Submit_Button_Label", comment: "Submit button text"), for: .normal)
        // Add all other UI elements that need localization here
    }
    
    deinit {
        // Clean up the observer to avoid memory leaks
        NotificationCenter.default.removeObserver(self)
    }
}

For Custom UI Components:

If you have custom buttons/labels, add the observer in their awakeFromNib method:

class CustomLocalizedButton: UIButton {
    override func awakeFromNib() {
        super.awakeFromNib()
        NotificationCenter.default.addObserver(self, selector: #selector(refreshText), name: NSNotification.Name(rawValue: "AppLanguageChanged"), object: nil)
        refreshText()
    }
    
    @objc private func refreshText() {
        // Use a User Defined Runtime Attribute to set the localization key in Interface Builder
        if let key = self.value(forKey: "localizationKey") as? String {
            self.setTitle(NSLocalizedString(key, comment: ""), for: .normal)
        }
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

4. Handle Storyboard/XIB Localization

Since Storyboard/XIB elements don’t auto-refresh at runtime, use one of these fixes:

  • Set all localized text via code (as shown above), or
  • Rely on the root view controller refresh we added in switchAppLanguage to reload storyboard content.

Key Notes

  • Ensure your localization folders are named correctly (e.g., en.lproj, zh-Hans.lproj) and contain a Localizable.strings file with your key-value pairs.
  • For system controls like back buttons, manually set their title in viewWillAppear:
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationItem.backBarButtonItem = UIBarButtonItem(title: NSLocalizedString("Back_Button", comment: ""), style: .plain, target: nil, action: nil)
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:49:52