首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用Swift以编程方式更改区域设置

如何使用Swift以编程方式更改区域设置
EN

Stack Overflow用户
提问于 2015-05-01 18:55:12
回答 17查看 104.9K关注 0票数 79

我正在通过Swift在XCODE 6.3上制作ios应用程序。我的应用程序将具有如下图所示的选择语言功能

我已经有了我的本地语言的故事板。但我找不到如何通过按钮在应用程序之外以编程方式更改本地化。

有人知道怎么做吗?

EN

回答 17

Stack Overflow用户

发布于 2015-07-31 18:42:49

这是一种使用Swift动态更改它的方法,向String添加一个扩展函数:

代码语言:javascript
复制
extension String {
func localized(lang:String) ->String {

    let path = NSBundle.mainBundle().pathForResource(lang, ofType: "lproj")
    let bundle = NSBundle(path: path!)

    return NSLocalizedString(self, tableName: nil, bundle: bundle!, value: "", comment: "")
}}

Swift 4:

代码语言:javascript
复制
extension String {
func localized(_ lang:String) ->String {

    let path = Bundle.main.path(forResource: lang, ofType: "lproj")
    let bundle = Bundle(path: path!)

    return NSLocalizedString(self, tableName: nil, bundle: bundle!, value: "", comment: "")
}}

然后假设您已经使用lang设置了常规Localizable.strings

_

id.lproj (例如en.lproj、de.lproj等)你可以在你需要的任何地方使用它:

代码语言:js
复制
var val = "MY_LOCALIZED_STRING".localized("de")
票数 97
EN

Stack Overflow用户

发布于 2016-12-14 18:36:34

这允许更改语言就在旁边更新UserDefaults密钥。

这是基于@dijipiji的很好的答案。这是一个Swift 3版本。

代码语言:javascript
复制
extension String {
    var localized: String {
        if let _ = UserDefaults.standard.string(forKey: "i18n_language") {} else {
            // we set a default, just in case
            UserDefaults.standard.set("fr", forKey: "i18n_language")
            UserDefaults.standard.synchronize()
        }

        let lang = UserDefaults.standard.string(forKey: "i18n_language")

        let path = Bundle.main.path(forResource: lang, ofType: "lproj")
        let bundle = Bundle(path: path!)

        return NSLocalizedString(self, tableName: nil, bundle: bundle!, value: "", comment: "")
    }
}

用法

只需添加.localized添加到字符串中,如下所示:

"MyString".localizedMyString成为Localizable.strings文件。

更改语言

代码语言:js
复制
UserDefaults.standard.set("en", forKey: "i18n_language")
票数 30
EN

Stack Overflow用户

发布于 2018-11-23 16:04:52

Swift 4.2

在我的例子中,如果用户更改了语言设置,我必须在运行时更新两个东西。

1. Localizable.strings​

2.故事板本地化

我让@John Pang代码更快

BundleExtension.swift

代码语言:javascript
复制
import UIKit

private var bundleKey: UInt8 = 0

final class BundleExtension: Bundle {

     override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String {
        return (objc_getAssociatedObject(self, &bundleKey) as? Bundle)?.localizedString(forKey: key, value: value, table: tableName) ?? super.localizedString(forKey: key, value: value, table: tableName)
    }
}

extension Bundle {

    static let once: Void = { object_setClass(Bundle.main, type(of: BundleExtension())) }()

    static func set(language: Language) {
        Bundle.once

        let isLanguageRTL = Locale.characterDirection(forLanguage: language.code) == .rightToLeft
        UIView.appearance().semanticContentAttribute = isLanguageRTL == true ? .forceRightToLeft : .forceLeftToRight

        UserDefaults.standard.set(isLanguageRTL,   forKey: "AppleTe  zxtDirection")
        UserDefaults.standard.set(isLanguageRTL,   forKey: "NSForceRightToLeftWritingDirection")
        UserDefaults.standard.set([language.code], forKey: "AppleLanguages")
        UserDefaults.standard.synchronize()

        guard let path = Bundle.main.path(forResource: language.code, ofType: "lproj") else {
            log(.error, "Failed to get a bundle path.")
            return
        }

        objc_setAssociatedObject(Bundle.main, &bundleKey, Bundle(path: path), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

Language.swift

代码语言:javascript
复制
import Foundation

enum Language: Equatable {
    case english(English)
    case chinese(Chinese)
    case korean
    case japanese

    enum English {
        case us
        case uk
        case australian
        case canadian
        case indian
    }

    enum Chinese {
        case simplified
        case traditional
        case hongKong
    }
}

extension Language {

    var code: String {
        switch self {
        case .english(let english):
            switch english {
            case .us:                return "en"
            case .uk:                return "en-GB"
            case .australian:        return "en-AU"
            case .canadian:          return "en-CA"
            case .indian:            return "en-IN"
            }

        case .chinese(let chinese):
            switch chinese {
            case .simplified:       return "zh-Hans"
            case .traditional:      return "zh-Hant"
            case .hongKong:         return "zh-HK"
            }

        case .korean:               return "ko"
        case .japanese:             return "ja"
        }
    }

    var name: String {
        switch self {
        case .english(let english):
            switch english {
            case .us:                return "English"
            case .uk:                return "English (UK)"
            case .australian:        return "English (Australia)"
            case .canadian:          return "English (Canada)"
            case .indian:            return "English (India)"
            }

        case .chinese(let chinese):
            switch chinese {
            case .simplified:       return "简体中文"
            case .traditional:      return "繁體中文"
            case .hongKong:         return "繁體中文 (香港)"
            }

        case .korean:               return "한국어"
        case .japanese:             return "日本語"
        }
    }
}

extension Language {

    init?(languageCode: String?) {
        guard let languageCode = languageCode else { return nil }
        switch languageCode {
        case "en", "en-US":     self = .english(.us)
        case "en-GB":           self = .english(.uk)
        case "en-AU":           self = .english(.australian)
        case "en-CA":           self = .english(.canadian)
        case "en-IN":           self = .english(.indian)

        case "zh-Hans":         self = .chinese(.simplified)
        case "zh-Hant":         self = .chinese(.traditional)
        case "zh-HK":           self = .chinese(.hongKong)

        case "ko":              self = .korean
        case "ja":              self = .japanese
        default:                return nil
        }
    }
}

像这样使用

代码语言:javascript
复制
var language: [Language] = [.korean, .english(.us), .english(.uk), .english(.australian), .english(.canadian), .english(.indian),
                            .chinese(.simplified), .chinese(.traditional), .chinese(.hongKong),
                            .japanese]

Bundle.set(language: languages[indexPath.row].language)

“Locale.current.languageCode“将始终返回系统设置语言。因此我们必须使用”

Locale.preferredLanguages.first“。但是返回值看起来像"ko-US”。这是一个问题!所以我制作了LocaleManager只获取语言代码。

LocaleManager.swift

代码语言:javascript
复制
import Foundation

    struct LocaleManager {

    /// "ko-US" → "ko"
    static var languageCode: String? {
        guard var splits = Locale.preferredLanguages.first?.split(separator: "-"), let first = splits.first else { return nil }
        guard 1 < splits.count else { return String(first) }
        splits.removeLast()
        return String(splits.joined(separator: "-"))
}

    static var language: Language? {
        return Language(languageCode: languageCode)
    }
}

像这样使用

代码语言:javascript
复制
guard let languageCode = LocaleManager.languageCode, let title = RemoteConfiguration.shared.logIn?.main?.title?[languageCode] else {
      return NSLocalizedString("Welcome!", comment: "")
}
return title
票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29985614

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档