Var*_*kul 62 xcode localization ios swift
我正在通过Swift在XCODE 6.3上制作ios应用程序.我的应用程序将具有选择语言功能,如下图所示
我已经有了当地语言的故事板.但我无法找到如何通过按钮以编程方式更改应用程序的本地化.
任何人都知道如何做到这一点
dij*_*iji 72
这是一种使用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: "")
}}
Run Code Online (Sandbox Code Playgroud)
斯威夫特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: "")
}}
Run Code Online (Sandbox Code Playgroud)
然后假设你有使用lang_id.lproj设置的常规Localizable.strings(例如en.lproj,de.lproj等),你可以在任何你需要的地方使用它:
var val = "MY_LOCALIZED_STRING".localized("de")
Run Code Online (Sandbox Code Playgroud)
Ale*_* G. 22
这允许仅通过更新密钥来更改语言.UserDefaults
这是基于@dijipiji的答案.这是一个Swift 3版本.
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: "")
}
}
Run Code Online (Sandbox Code Playgroud)
用法
只需添加.localized
到您的字符串,如下:
"MyString".localized
,MyString
作为Localizable.strings
文件中的一个关键.
改变语言
UserDefaults.standard.set("en", forKey: "i18n_language")
Run Code Online (Sandbox Code Playgroud)
whi*_*gle 10
花了好几天我才真正找到了解决方案.不需要重新推出,很优雅:http://www.factorialcomplexity.com/blog/2015/01/28/how-to-change-localization-internally-in-your-ios-application.html,检查方法#2.它不需要手动重新建立所有标题和文本,只需覆盖自定义NSBundle类别的本地化.适用于Obj-C和Swift项目(经过一些调整后),就像魅力一样.我怀疑它是否会被苹果批准,但实际上确实如此.
Jeremy的答案(这里)也适用于Swift 4(我刚用一个简单的应用程序进行测试,我改变了初始视图控制器中使用的语言).
这是同一段代码的Swift版本(出于某些原因,我的队友更喜欢Swift-only而不是与Objective-C混合,所以我翻译了它):
import UIKit
private var kBundleKey: UInt8 = 0
class BundleEx: Bundle {
override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String {
if let bundle = objc_getAssociatedObject(self, &kBundleKey) {
return (bundle as! Bundle).localizedString(forKey: key, value: value, table: tableName)
}
return super.localizedString(forKey: key, value: value, table: tableName)
}
}
extension Bundle {
static let once: Void = {
object_setClass(Bundle.main, type(of: BundleEx()))
}()
class func setLanguage(_ language: String?) {
Bundle.once
let isLanguageRTL = Bundle.isLanguageRTL(language)
if (isLanguageRTL) {
UIView.appearance().semanticContentAttribute = .forceRightToLeft
} else {
UIView.appearance().semanticContentAttribute = .forceLeftToRight
}
UserDefaults.standard.set(isLanguageRTL, forKey: "AppleTextDirection")
UserDefaults.standard.set(isLanguageRTL, forKey: "NSForceRightToLeftWritingDirection")
UserDefaults.standard.synchronize()
let value = (language != nil ? Bundle.init(path: (Bundle.main.path(forResource: language, ofType: "lproj"))!) : nil)
objc_setAssociatedObject(Bundle.main, &kBundleKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
class func isLanguageRTL(_ languageCode: String?) -> Bool {
return (languageCode != nil && Locale.characterDirection(forLanguage: languageCode!) == .rightToLeft)
}
}
Run Code Online (Sandbox Code Playgroud)
Swift 4中的可用代码:
extension Bundle {
private static var bundle: Bundle!
public static func localizedBundle() -> Bundle! {
if bundle == nil {
let appLang = UserDefaults.standard.string(forKey: "app_lang") ?? "ru"
let path = Bundle.main.path(forResource: appLang, ofType: "lproj")
bundle = Bundle(path: path!)
}
return bundle;
}
public static func setLanguage(lang: String) {
UserDefaults.standard.set(lang, forKey: "app_lang")
let path = Bundle.main.path(forResource: lang, ofType: "lproj")
bundle = Bundle(path: path!)
}
}
Run Code Online (Sandbox Code Playgroud)
和
extension String {
func localized() -> String {
return NSLocalizedString(self, tableName: nil, bundle: Bundle.localizedBundle(), value: "", comment: "")
}
func localizeWithFormat(arguments: CVarArg...) -> String{
return String(format: self.localized(), arguments: arguments)
}
}
Run Code Online (Sandbox Code Playgroud)
呼叫:
let localizedString = "enter".localized()
Run Code Online (Sandbox Code Playgroud)
设置新的语言环境(例如"ru"):
Bundle.setLanguage(lang: "ru")
Run Code Online (Sandbox Code Playgroud)
Swift 4
UserDefaults.standard.set(["es", "de", "it"], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
Run Code Online (Sandbox Code Playgroud)
Swift 3
NSUserDefaults.standardUserDefaults().setObject(["es", "de", "it"], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()
Run Code Online (Sandbox Code Playgroud)
Source: here
斯威夫特4.2
就我而言,如果用户更改语言设置,则必须在运行时更新2件事。
1. Localizable.strings
2.故事板的本地化
我让@John Pang代码更加快捷
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);
}
}
Run Code Online (Sandbox Code Playgroud)
语言速记
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
这样使用
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)
Run Code Online (Sandbox Code Playgroud)
“ 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 1 < splits.count else { return String(first) }
splits.removeLast()
return String(splits.joined(separator: "-"))
}
static var language: Language? {
return Language(languageCode: languageCode)
}
}
Run Code Online (Sandbox Code Playgroud)
这样使用
guard let languageCode = LocaleManager.languageCode, let title = RemoteConfiguration.shared.logIn?.main?.title?[languageCode] else {
return NSLocalizedString("Welcome!", comment: "")
}
return title
Run Code Online (Sandbox Code Playgroud)
以下是苹果公司关于更改语言的说法;
一般来说,您不应在应用程序中更改 iOS 系统语言(通过使用 AppleLanguages pref 键)。这违背了在“设置”应用程序中切换语言的基本 iOS 用户模型,并且还使用了未记录的首选项键,这意味着在将来的某个时候,键名称可能会更改,这会破坏您的应用程序。
因此,建议您将用户导航到应用程序的常规设置页面,该页面位于
设置 -> [your_app_name] -> 首选语言
为了直接从您的应用程序打开应用程序设置,您可以使用这些代码;
对于斯威夫特;
let settingsURL = URL(string: UIApplication.openSettingsURLString)!
UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
Run Code Online (Sandbox Code Playgroud)
对于 Obj-C;
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL options:@{} completionHandler:nil];
Run Code Online (Sandbox Code Playgroud)
提示: 在导航到设置页面之前,最好弹出并说明用户切换到设置页面后应该做什么,这对于您的应用程序来说是更好的用户体验。
归档时间: |
|
查看次数: |
61888 次 |
最近记录: |