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

Swift 5开发的iOS应用内切换语言(本地化)实现方案咨询

Absolutely, in-app language switching is totally supported for Swift 5 iOS apps—and I’ve got a battle-tested, optimal approach to share with you, based on production best practices:

Core Idea

iOS defaults to loading localized resources based on the user’s system language settings. To switch languages within your app, you’ll need to manually manage the user’s language preference and force the app to load resources from your chosen language files instead of relying on the system default.

Step-by-Step Optimal Implementation

1. Create a Singleton Language Manager to Store Preferences

First, we’ll build a shared manager to handle saving/retrieving the user’s selected language. This keeps the logic centralized and easy to access from any screen.

enum AppLanguage: String {
    case english = "en"
    case simplifiedChinese = "zh-Hans"
    // Add more languages here as needed (e.g., .spanish = "es")
}

class LanguageManager {
    static let shared = LanguageManager()
    private let userDefaultsKey = "AppSelectedLanguage"
    
    // Get the current active language (falls back to system default if no preference is saved)
    var currentLanguage: AppLanguage {
        guard let savedLangCode = UserDefaults.standard.string(forKey: userDefaultsKey),
              let language = AppLanguage(rawValue: savedLangCode) else {
            // Fall back to system's preferred language, or default to English
            let systemLangCode = Locale.preferredLanguages.first ?? "en"
            return systemLangCode.starts(with: "zh") ? .simplifiedChinese : .english
        }
        return language
    }
    
    // Set a new language and notify the app to refresh UI
    func setLanguage(_ language: AppLanguage) {
        UserDefaults.standard.set(language.rawValue, forKey: userDefaultsKey)
        // Post a notification so all screens know to update their UI
        NotificationCenter.default.post(name: NSNotification.Name("AppLanguageChanged"), object: nil)
    }
}

2. Build a Custom Localization String Loader

The default NSLocalizedString uses the system language, so we’ll create a custom extension to load strings from the language file matching our manager’s current selection:

extension String {
    func localized() -> String {
        let targetLangCode = LanguageManager.shared.currentLanguage.rawValue
        // Get the bundle for the target language
        guard let langBundlePath = Bundle.main.path(forResource: targetLangCode, ofType: "lproj"),
              let langBundle = Bundle(path: langBundlePath) else {
            // Fall back to system default localization if the target bundle doesn't exist
            return NSLocalizedString(self, comment: "")
        }
        return NSLocalizedString(self, bundle: langBundle, comment: "")
    }
}

// Usage example:
// let greeting = "hello_world".localized()

3. Update Storyboard/XIB Content to Follow Custom Language

Storyboard elements won’t automatically pick up your custom language—you have two solid options here:

Option A: Manual UI Refresh in View Controllers

In each view controller’s viewWillAppear (or a base view controller that all screens inherit from), update your UI elements using the localized() method:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.title = "home_screen_title".localized()
    self.loginButton.setTitle("login_button_label".localized(), for: .normal)
    // Repeat for all text-based elements
}

Option B: Custom Localized UI Components (Cleaner for Storyboards)

Create IBDesignable subclasses for UI elements like buttons, labels, etc., so you can set a localization key directly in Storyboard:

@IBDesignable
class LocalizedLabel: UILabel {
    @IBInspectable var localizationKey: String = "" {
        didSet {
            text = localizationKey.localized()
        }
    }
}

@IBDesignable
class LocalizedButton: UIButton {
    @IBInspectable var localizationKey: String = "" {
        didSet {
            setTitle(localizationKey.localized(), for: .normal)
        }
    }
}

Then, in Storyboard, change your label/button’s class to LocalizedLabel/LocalizedButton and enter the localization key in the Attributes Inspector—no manual code needed for each element!

4. Handle Language Switch Trigger & UI Refresh

When the user taps your language switch button, update the preference and refresh the app’s UI. Two approaches here:

Approach 1: Refresh UI via Notifications

Call the language manager’s setLanguage method, then have each view controller listen for the AppLanguageChanged notification to update their UI:

// In your language switch button's action:
@IBAction func switchToChineseTapped(_ sender: UIButton) {
    LanguageManager.shared.setLanguage(.simplifiedChinese)
}

// In each view controller (or base view controller):
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(refreshLocalizedContent), name: NSNotification.Name("AppLanguageChanged"), object: nil)
}

@objc private func refreshLocalizedContent() {
    self.title = "home_screen_title".localized()
    self.loginButton.setTitle("login_button_label".localized(), for: .normal)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

Approach 2: Restart the Root View Controller (More Thorough)

For a clean, full refresh (great if you have complex UI or nested navigation), replace the app’s root view controller:

@IBAction func switchToEnglishTapped(_ sender: UIButton) {
    LanguageManager.shared.setLanguage(.english)
    
    // Get the app's main window (adjust for SceneDelegate if using iOS 13+)
    guard let window = UIApplication.shared.windows.first else { return }
    let newRootVC = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()!
    window.rootViewController = newRootVC
    window.makeKeyAndVisible()
}

// If using SceneDelegate (iOS 13+):
// guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
//       let window = scene.windows.first else { return }

5. Handle Edge Cases

  • Localized Images: If you have language-specific images, place them in the corresponding .lproj folders, then use a custom image loader:
    func localizedImage(named name: String) -> UIImage? {
        let targetLangCode = LanguageManager.shared.currentLanguage.rawValue
        guard let langBundlePath = Bundle.main.path(forResource: targetLangCode, ofType: "lproj"),
              let langBundle = Bundle(path: langBundlePath) else {
            return UIImage(named: name)
        }
        return UIImage(named: name, in: langBundle, compatibleWith: nil)
    }
    
  • System UI Elements: Things like navigation bar back buttons default to system language. To fix this, set the back button title manually in your base view controller using a localized string.
Key Notes
  • Use standard ISO language codes (e.g., zh-Hans for simplified Chinese, en for English) to match system language file naming conventions.
  • Test thoroughly to ensure all localization keys are present in every language’s .strings file.
  • If you’re using SwiftUI, the approach is similar—use the LanguageManager to observe language changes and refresh views via @ObservedObject or @EnvironmentObject.

内容的提问来源于stack exchange,提问作者New iOS Dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:52:35