我如何使用Swift在程序中进行区域设置更改?

12 浏览
0 Comments

我如何使用Swift在程序中进行区域设置更改?

我正在使用XCODE 6.3和Swift开发iOS应用。我的应用将具有像下面图片中的选择语言功能。

enter image description here

我已经为我的本地语言准备好了storyboard。

但是我无法找到如何通过按钮在应用程序中以编程方式更改本地化的方法。

有人知道如何做吗?

0
0 Comments

在Swift中,有一种方法可以实时改变本地化语言,你可以给String添加一个扩展函数:

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版本:

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: "")

}

}

假设你已经按照正常的方式设置了Localizable.strings文件,并分别放在lang_id.lproj(例如en.lproj, de.lproj等)文件夹中,你可以在任何需要的地方使用这个函数:

var val = "MY_LOCALIZED_STRING".localized("de")

恭喜,这是我找到的迄今为止最好的解决方案。我刚刚进行了一些修改,以便能够动态地改变语言。我将它作为一个答案发布。

但是如何在改变语言后重新加载Storyboard呢?目前,当我改变语言时,使用.localized()的字符串可以正常显示,但是Storyboard没有反映出选择的语言。

嗨Hardik,在这种情况下,你的Storyboard标签需要从代码中设置,并且每次语言改变时都要运行该代码。

这个答案并没有回答问题,问题是关于本地语言的Storyboard,它只是一个将字符串翻译的方法。

0
0 Comments

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

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

1. Localizable.strings

2. Storyboard本地化

我使Pang代码更加Swifty。

首先,创建一个名为BundleExtension.swift的文件,并在其中添加以下代码:

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的文件,并在其中添加以下代码:

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

}

}

}

要使用这些代码,可以按以下方式调用:

var languages: [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的文件,并在其中添加以下代码:

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 splits.count > 1 else { return String(first) }

splits.removeLast()

return String(splits.joined(separator: "-"))

}

static var language: Language? {

return Language(languageCode: languageCode)

}

}

要使用这些代码,可以按以下方式调用:

guard let languageCode = LocaleManager.languageCode, let title = RemoteConfiguration.shared.logIn?.main?.title?[languageCode] else {

return NSLocalizedString("Welcome!", comment: "")

}

return title

希望这个答案能被标记为正确!

0
0 Comments

问题:如何用Swift编程方式更改语言环境?

原因:想要通过更新UserDefaults键来更改语言。

解决方法:

1. 创建一个String的extension,其中包含一个localized的计算属性。这个属性根据UserDefaults中的i18n_language值来返回本地化的字符串。

2. 在使用字符串的地方,通过在字符串后添加.localized来获取本地化的字符串。

3. 若要更改语言,只需通过UserDefaults设置i18n_language的值为目标语言即可。

然而,目前在更改语言后,字符串的本地化工作正常,但是Storyboard并未更改。为了解决这个问题,有人提供了一个解决方案,即在名为"Settings"的视图控制器中更改语言,然后关闭该视图控制器,这样所有的标签和按钮就会实时更改语言。此外,还有其他一些方法,例如在需要更改语言的视图控制器中调用一个updateStrings()方法来重置字符串,但这可能不是一个理想的解决方案。

需要注意的是,不应该使用synchronize()方法来同步UserDefaults,因为据苹果文档所述,这个方法已经过时了。

0